Make source code publicly accessible from day one

Overview

Teaching: 0 min
Exercises: 0 min
Questions
  • What are the benefits of making my software project public from the beginning?

  • How do I make my project publicly accessible?

  • What resources are available to help me document my software?

  • What are the best practices in open software development?

  • How do I publish my open source software?

Objectives
  • create a new software project on GitHub

  • list three things that should be included in ‘bare minimum’ software documentation

  • explain the difference between user- and developer-oriented documentation

  • describe three steps that can be taken to increase the (re)usability of software

  • describe how external resources can be used at the stage of publishing OS software

Hosting a project on GitHub

Perhaps the most important aspect of good research software is that it is accessible. Even the fastest, most accurate, beautifully-written software can’t fulfill its potential if no-one but the developer knows that it exists. Luckily, the internet and search engines have made it easier than ever before to find and compare software and projects that could be used to research.

Software that is easy to find, clearly documented, and under regular, visible development, is attractive to researchers who are keen not to waste time on tools and resources that are difficult to use and/or error-prone. A software project whose most recent version is available alongside a whole history of the changes and contributions that have been made to that software, is

Several publicly-accessible platforms exist online for hosting software projects. GitHub is one of the most popular and comprehenive of these platforms, facilitating licensing, documentation, and publication of code as well as providing a remote version control repository.

When first creating a project, you will need to make a decision about what the project will be called. This is also the appropriate time to consider other factors that will have an impact on how people perceive and interact with your project. Bear in mind that the health and longevity of an open source software project relies on external contributions, so work to make yours welcoming and inclusive. For more on this topic, and other advice on starting an open source project, check out the Open Source Guide on naming & branding.

README - The ‘front page’ of your project

To format the contents of this file you will use Markdown syntax. If you want to know more about it you can use this cheatsheet or this short guide

Challenge: Improve the README

The README.md file that GitHub generated when we created the project is quite boring. Add some more content using some of the Markdown syntax introduced above. You could add a few sentences about the purpose of your software, some details of the author(s) and their affiliation(s), or anything else that you think is important.

Discussion: How does version control help your project?

5 minutes

You may already be aware of the benefits of software version control in relation to a programming project. In small groups, discuss how following best practices in version control, such as making regular, small, self-contained commits, and having project members work on branches to avoid conflicts, can benefit a project hosted publicly on GitHub.

Solution

As well as making it easier to collaborate and to track and revert changes in the code, following best practices in version control:

  • keeps progress on your project visible
  • encourages contributions and suggestions from the community
  • facilitates recognition of contributions at time of publication
  • promotes good programming practice amongst project members

Documentation

For people to use or contribute to a software project it needs to be documented.

Discussion

  • What experiences have you had with good or bad documentation?
  • What was important for you as a user?
  • What was important for you as a developer?

The documentation of a software should be developed to target two types of audience: the end-users and the potential contributors (usually developers).

For the end-user, a good documentation should clearly state what problems the software is designed to solve and who the target audience is. Installation instructions should include a list of dependencies and, ideally, how to install such dependencies. The documentation should also depict some examples of how to use the software with explanations of the expected inputs and outputs.

Additionally, if the software has an API, all functions/methods from the API should be documented including example inputs and outputs.

Notes

As an example, the Journal of Open Source Software requirements has defined that a software can be accepted for publication if it has at least in its documentation:

  • A statement of need: Do the authors clearly state what problems the software is designed to solve and who the target audience is?
  • Installation instructions: Is there a clearly-stated list of dependencies? Ideally these should be handled with an automated package management solution.
  • Example usage: Do the authors include examples of how to use the software (ideally to solve real-world analysis problems).
  • Functionality documentation: Is the core functionality of the software documented to a satisfactory level (e.g., API method documentation)?

Challenge

Try to use the following software (link…)

  1. What information was missing?
  2. Talk to your neighbour and see if your lists agree.

Solution

  • No input definition

One of the main challenge of documentation is to keep it up-to-date, following the evolution of the software. To avoid this issue, a good documentation follow these recommendations:

The simplest documentation is the README.md file. For more visibility, a small website can be easily created to host the documentation, for example using the GitHub pages or ReadTheDoc.

Challenge

Create a simple page of documentation for your software using the GitHub page

Solution

  • Create a docs folder at the root of your repository
  • Add an index.md file there
  • Fill the index.md with minimum documentation mentioned before
  • Commit and push it to GitHub
  • Go to the repository on GitHub
  • Click on Setting on the top
  • Scroll to GitHub Pages
  • Select master branch /docs folder as source
  • Click on Save
  • Copy the link that should now appear
  • Check it
  • Go back to the root repository on GitHub
  • Click on the Edit button
  • Paste the link to Website
  • Click on Save

More complex documentation can be also be generated using Sphinx. For example, the docstrings for each function could be extracted to populate an extensive API documentation. Even complex, this documentation can be stored on GitHub: it is only text.

Good documentation can make a big difference on how a software is used but also in creating a community around it to support it.

Making software (re)usable

As we discussed earlier, a piece of research software can be considered successful if many people find it useful and cite it. As well as providing good documentation, there are other steps that you should take to encourage people to use and contribute to your research software.

Challenge

Think about a negative experience that you’ve had with a piece of software. What could have been done to improve your experience? Discuss this with the person next to you. Based on this discussion, can you make any recommendations to the rest of the group around how to encourage other people to use their research software?

The importance of good code

Following good coding standards is always important. Even when writing code that you never intend to share with anyone else, it’s worth following putting the effort into organising your code and making it readable. There are several reasons for this: it’s good to keep yourself in the habit for when it really matters; you never know when you might need to come back and adapt/update the code, and understandable code helps to reduce the pain induced when doing so; it makes debugging considerable less painful, and; it reduces your embarrassment when, one day, you find that you do need to share your code with someone.

Beyond these points, it’s particularly important to maintain a good standard and consistency of code when establishing an open source project. For research software to be successful, it has to work, and it should be used by other people. Code that is well-written and documented has the following advantages:

The Software Carpentry lessons on Programming with Python and Programming with R contain plenty of advice on good programming practices. Some languages have coding standards that have been adopted with varying levels of fervour by their developer community. Examples include PEP8 for Python, Hadley Wickham’s Style Guide for R, and the ISO standards for C++. Google also have their own set of styles guides for all languages currently popular. Incidentally, Google’s guides are hosted via GitHub Pages (see below).

Challenge

Many of these communities have developed tooling around the style guides for their language of choice (these are referred to as “linters”). One such example is the pycodestyle executable, which scans through Python code and flags up anything in the script(s) that doesn’t conform to the standards for the language.

The script positive_limits.py takes the name of a file containing lines of numbers and returns the lower and upper positive (i.e. >0) limits of those numbers. Look at the script and, without making any changes, make a note of the changes that you would make to improve the style of the script. Now, in the shell, run

pycodestyle --show-source positive_limits.py

and look through the output. How closely does the output of pycodestyle match your list? Did you notice anything that the linter didn’t?

Main points for this section:

Publishing

Making your software reusable with Docker

What’s Docker

Docker is an open source project that automates the deployment of software applications in a sandbox (called container).

Containers are a way to package software so that it can be run isolated on an operating system, e.g. Linux. Unlike virtual machines, containers do not bundle a full operating system - only libraries and settings, required to make the software work. This makes containers efficient, lightweight systems and guarantees that software runs reproducibly, regardless of where it is deployed.

Why is it a good idea to use Docker?

Your software/code/application is meant to run on a specific environment which includes many dependencies. If you use Docker you replicate this exact environment for others to run your software/code in. In that sense, Docker images help you resolve the “Dependency hell”.

Dockerfiles (Dockerfile reference) store the configuration of your environment, which are used to build Docker images. You can save versions of your Dockerfile to build new Docker images. These versions are a version control system for the code and the environment in which the code is run. For reproducibility, you have the option to save a Dockerfile to build a Docker image when you need it. Alternatively, you can keep the respective images built from a Docker file. This is recommended if you are frequently using these images, and/or you have the necessary storage space for it (some images have several GB in size).

This setup frees you and your users from barriers to adopt and re-use your code/software/application. It is also a good idea to use Dockerfiles for distributing/collaborating/testing your code in a customized and persistent environment. Even sharing a Dockerfile with yourself, will help you run your code on your laptop in the same environment as you have on your server.

How does this work

Docker images are used to configure and distribute application states. Think of it as a template with which to create the container. With a Docker image, we can quickly spin up (aka run) containers with the same configuration. We can then share these images with our team, so we will all be running containers which all have the same configuration.

There are several ways to create Docker images, but the best way is to create a Dockerfile and use the docker build command. The most convenient and widely used way to distribute your images is using Docker Hub. Additionally, if your Dockerfile is hosted on GitHub, you can configure an automated build on Docker Hub. A similar registry to Docker Hub, recommended for life sciences, is BioContainers.

Example

A general example of a Dockerfile is the following: it starts from a base Ubuntu image with a specific version (18.04 in this instance) and installs all the dependencies for Python 3.7 and then runs the “tool” (a simple “Hello World” python command).

FROM ubuntu:18.04

RUN apt-get update -y && apt-get install -y python-pip python3.7-dev build-essential libpq-dev

CMD /usr/bin/python3.7 -c "print('Hello from Python in Docker')"

For more information on how to build more complex Docker images, the Docker Documentation and the Docker Curriculum are excellent resources.

Moreover, if you are building a BioContainer, you should also be adhering to the specific BioContainer meta-data specifications. These increase the findability and accessibility of your tool.

Finally, anyone can run the tool using the exact same environment described by the Dockerfile using the following commands:

docker pull fpsom/jupyter-kernels

docker run --name=jupyter fpsom/jupyter-kernels

The first command will download the correct image from the repository (the fpsom\jupyter-kernels image from the DockerHub repository in this instance). The second command runs the image / tool; if we do not pass the --name parameter, Docker will pick a random name for our container. Many images require some extra parameters to be passed to the run command, so take some time to read through the documentation of an image before you use it (Docker image for Jupyter notebook with multiple kernels in this particular example). Also, take some time to read the documentation of the docker run command.

To complete these steps, you can see your running containers using the docker ps command. To see all containers, add the -a flag - docker ps -a.

Use of notebooks

A computational notebook is an application that allows you to create and share live code, equations, visualisations and narrative text Notebook Interface. It is a great way to combine data analysis and documentation in a single page.

What is Jupyter?

Jupyter Notebook, formerly known as IPython Notebook, is a flexible and powerful open source research tool that can help you keep a narrative of your coding process. The name Jupyter is an acronym of the first three languages that this Notebook supported: JUlia, PYThon, and R. Project Jupyter can be used for interactive data science and scientific computing. Later it supported over 40 other programming languages. There are a lot of resources that can help you better understand how to prepare and structure a Jupyter notebook, such as the official Documentation and the Introduction materials for Reproducible Research Curriculum.

Jupyter is one type of computational notebooks. Another type that shares the same philosophy and overall structure (but has a different syntax) are the R notebooks written in RMarkdown.

How can I make my notebook public?

Sharing the notebook file itself (as a ipynb or rmd file) is the exact same as sharing any other piece of code; create a repository with the correct structure in a version control system (such as git). However, there are a few additional steps that one might take to improve the reproducibility and accessibility of the notebook.

By default, all notebooks are rendered in GitHub (i.e. text, code and produced output is visible and well formatted), but it is a static representation. You cannot make changes to the code or make any time of execution to it. However, you can allow the execution of the entire notebook by providing some additional context (such as the expected execution environment) as well as linking the repository itself to a service that provides execution.

How can I make my notebook public and dynamic?

The most widely used service is MyBinder - as the host of our Jupyter Notebook it allows anyone to run (and therefore reproduce) our code. What MyBinder does, is that it allows you to create custom computing environments that can be shared and used by many remote users.

MyBinder makes it simple to generate reproducible computing environments from a GitHub repository. It uses the BinderHub technology to generate a Docker image from a given repository, by reading through the specified requirements.txt, environment.yml or Dockerfile. The image will have all the components that you specify along with the Jupyter Notebooks inside. Ultimately you will be able to share a URL with users that can immediately begin interacting with this environment.

If you use the publicly available service, there are some limits in resources; while running, you are guaranteed to have at least 1G of RAM but there is an upper-limit of 4GB (if you use more than 4GB your kernel will be restarted). You can also setup a local mybinder service if you have the infrastructure to support it.

Advantages of including a notebook with your traditional source code

MyBinder allows for other people to re-run your code / notebook. However, you can also:

Key Points

  • Services like GitHub can be used to make your project public and findable.

  • Using these tools appropriately encourages and credits contributions to the project.

  • Making your project public encourages better practices in developing and documenting software.

  • GitHub makes it easier to get a DOI and publish your software.