def get_meaning_life_universe_everything():
"""Retrieves the answer to the ultimate question"""
return 42
print(get_meaning_life_universe_everything())
42
Health Service Modelling Associates Programme
I want us to be able to provide meaningful and timely help with your projects when other avenues have failed to unstick things.
There are a few things you can do to make it easier for us to help you.
If all else fails - I really am happy to help (and have taken a look at various issues for people this year)!
It helps if you can give me as much information as possible about
Having your code available on GitHub is the easiest way for us to troubleshoot issues.
If you cannot provide it on GitHub, sending code files to us on Slack is acceptable, but please attach it as a file to a Slack message rather than copying and pasting.
Please either provide
If you are using branches, please make it clear which branch we need to be looking at!
We might still be able to help!
Can you give us the gist of your problem? Like before, this might involve talking about
You could also look into
Understanding someone else’s code can be tricky - and time-consuming - at the best of times.
The following will really help us!
CTRL + /
can make it easier to get temporarily comment out bits of codeOne of the best ways to make your code even easier for us to work with is to use docstrings.
Docstrings are like a super-comment that makes it easier to understand your functions, classes, and methods - wherever you are accessing them in the code.
When you start using a function from a package and it pops up with a load of extra useful details, that’s its docstring you are seeing.
Docstrings are put after you define a function name
A simple docstring might look like this:
def get_meaning_life_universe_everything():
"""Retrieves the answer to the ultimate question"""
return 42
print(get_meaning_life_universe_everything())
42
Here’s an article with a great introduction to writing docstrings.
For more advanced docstrings, we also specify details about the inputs and outputs using specific notation.
There are various formats that exist, like PyDoc and Google Docstrings - my personal favourite is numpydoc
def multiply_two_numbers(number_1, number_2):
"""
Multiplies two numbers and prints the result.
Parameters
----------
number_1 : int or float
The first number to be multiplied.
number_2 : int or float
The second number to be multiplied.
Returns
-------
None
This function prints the result but does not return it.
"""
print(number_1 * number_2)
This is something that AI is generally decent at (though check its output!)
Feed it your function, tell it your preferred docstring format, et voila!
This can save a lot of time with functions with extensive inputs over using a template - though there are good VSCode extensions to help you with this like autoDocstring.
A ‘quick meeting’ can often take a lot more time than you’d think!
(and in all honesty, unless it’s something like a typo or a very simple methodological question, I’m unlikely to be able to resolve it within a call)
However, I can often squeeze in some time looking at problems or questions and then send you details of
However, I recognise that sometimes only a chat will do!
I will be opening up some more bookable slots soon and sharing a link!
GitHub isn’t just a great place to version control your code…
It’s a great place to
Tip
Want a reminder of how to use GitHub?
Take a look at session 7a here:
https://hsma.co.uk/hsma_content/modules/current_module_details/7_git_and_web_development
Or scan the QR code
GitHub issues are a great built-in (and free) way of tracking aspects of your project.
They are almost a built in to-do list to help you track what needs to happen - and what’s already happened.
They can be particularly useful for collaborative projects, but can also be very handy for solo projects.
The great thing about your repo… is that it’s your repo!
Established projects may have more rules about what can be an issue and how it’s formatted, but you can set the rules on your project.
So you could use issues for
In the vidigi issues, I’m primarily talking to myself and using it as a big to-do list.
In another project, we have used it for three of us to be able to communicate asynchronously about the project
Helena has been using these very effectively in her project
Including to summon me! (more on this later)
In your repositories, whether they are public or private, you should see an ‘Issues’ tab.
When we first load this up, there’s nothing here… so let’s change that!
We’ll click the ‘New Issue’ button
The minimum we need to provide is a title (though it’s a good idea to put in some description too)
This will take us to a view where we can add comments to the issue.
Heading back to our ‘issues’ page we can now see this in our list of issues.
Labels allow us to
Github provides us with a selection of predefined labels that we can choose from.
By clicking on ‘edit labels’…
… we are taken to a page where we can create any label we fancy
On our issues page, we can then click on the ‘labels’ dropdown to only find certain kinds of issue.
Warning
Note - the filter won’t happen until you click elsewhere on the screen (outside of the label popup)
It can be really helpful to mention issues on other issues, or in pull requests!
Typing a #
symbol brings up a list of recent issues, and by starting to type you can filter it down by number…
… or by name
Mentioned issues will turn into a link when you save the description or comment
And they’ll show up in the linked issues and pull requests too
If you mention someone by their GitHub username - prefacing it with an @ symbol - then they will get a notification.
On a public repo - or one where you’ve added me as a collaborator - you could summon me like that!
When you are done with an issue, we can write a comment (optional, but recommended!) and close it down.
Note
If we want to, we can mention the ID of the pull request that closes this issue, or even the exact commit hash!
In pull requests, if we mention an issue by ID with the #
notation, it will
In your projects, you may have different milestones you are working towards.
You might want to keep track of the issues you are aiming to achieve by different stages of the project - and then track your progress towards that.
In vidigi, I just use it to track issues I’m planning to fix in each minor version
In another project, we’ve tied it in more detail to due dates and goals.
From the issue page, click ‘milestones’.
Then ‘new milestone’
From this, you can then enter a title of your choice, an optional due date, and any details to flesh out things like key goals or requirements.
Now, when we click on the milestone header, we are given the option to add any issue to our new milestone.
Projects are an optional extra that you can use to enhance your use of issues.
We can access them from the ‘Projects’ header.
We’ll click ‘new project’
We’ll be provided with a list of possible project layouts.
My favourite is Kanban - but feel free to experiment!
Give your project a name.
Initially we’re presented with a list of empty columns.
We then click on ‘add item’
This brings up a search bar
Clicking on the plus gives us some more options.
If we click ‘add items from repository’ we can access our current repo’s issues - or issues from other repos!
Once this is done, we have an issue in the column.
We can move this around as we progress.
Moving it to done automatically closes it (though it might take 10-15 seconds to do so)!
Clicking on the three dots allows us to change the default limit for issues per column (0 = no limit)
We can also add, delete (make sure you delete the column, not the items!) and reorder columns (by clicking and dragging them).
Why do I bang on so much about documentation?
In my experience, lack of documentation
And the process of writing documentation is crucial for
It’s possible to set up a Quarto project within the same folder as your main repository.
Using the ‘book’ template, you can write a detailed, interactive document that covers the important details of your project, allowing you to tailor chapters or sections to readers interested in different levels of detail.
Tip
Want a reminder of how to use Quarto?
Take a look at session 8a here:
https://hsma.co.uk/hsma_content/modules/current_module_details/8_modern_analytics
Or scan the QR code
I’ve recently being diving into quartodoc too - this is a really cool addon for quarto that allows you to generate documentation for various functions in your project as well and weave that into a quarto book
It’s a bit more tricky to get started with than pure quarto (and is something you could look to incorporate at a later stage in an already established quarto book)
https://github.com/machow/quartodoc
Another more established and popular alternative is sphinx, though I haven’t used it myself.
The documentation for my package vidigi is made using quarto + quartodoc
With pages like this being automatically generated by quartodoc
There’s a good introduction to quartodoc in their documentation: https://machow.github.io/quartodoc/get-started/overview.html
Note that you can also set it up without turning your project into a package: https://machow.github.io/quartodoc/get-started/basic-content.html#documenting-source-files-that-are-not-a-package
The _quarto.yml for vidigi would also be a good starting point if combining traditional quarto with quartodoc is something you want to do: https://github.com/Bergam0t/vidigi/blob/main/_quarto.yml
There are a wide range of checklists out there for helping you ensure your code is as reusable and well documented as possible.
I’m going to cover just a few today to give you inspiration - but I’d love to hear about any others people come across.
STRESS-DES is 20-item checklist. It was designed to improve the reporting of DES models, ensuring that your report includes enough information for others to understand, evaluate and replicate the findings of your work.
While it’s designed for DES models, you may still find it provides some useful prompts for other kinds of models.
Section/Subsection | Item | Recommendation |
---|---|---|
Purpose of the model | 1.1 | Explain the background and objectives for the model. |
Model outputs | 1.2 | Define all quantitative performance measures that are reported, using equations where necessary. Specify how and when they are calculated during the model run along with how any measures of error such as confidence intervals are calculated. |
Experimentation aims | 1.3 | If the model has been used for experimentation, state the objectives that it was used to investigate. (A) Scenario based analysis – Provide a name and description for each scenario, providing a rationale for the choice of scenarios and ensure that item 2.3 (below) is completed. (B) Design of experiments – Provide details of the overall design of the experiments with reference to performance measures and their parameters (provide further details in data below). (C) Simulation Optimisation – (if appropriate) Provide full details of what is to be optimised, the parameters that were included and the algorithm(s) that was be used. Where possible provide a citation of the algorithm(s). |
Section/Subsection | Item | Recommendation |
---|---|---|
Base model overview diagram | 2.1 | Describe the base model using appropriate diagrams and description. This could include one or more process flow, activity cycle or equivalent diagrams sufficient to describe the model to readers. Avoid complicated diagrams in the main text. The goal is to describe the breadth and depth of the model with respect to the system being studied. |
Base model logic | 2.2 | Give details of the base model logic. Give additional model logic details sufficient to communicate to the reader how the model works.. |
Scenario logic | 2.3 | Give details of the logical difference between the base case model and scenarios (if any). This could be incorporated as text or where differences are substantial could be incorporated in the same manner as 2.2.. |
Algorithms | 2.4 | Provide further detail on any algorithms in the model that (for example) mimic complex or manual processes in the real world (i.e. scheduling of arrivals/ appointments/ operations/ maintenance, operation of a conveyor system, machine breakdowns, etc.). Sufficient detail should be included (or referred to in other published work) for the algorithms to be reproducible. Pseudo-code may be used to describe an algorithm. |
Section/Subsection | Item | Recommendation |
---|---|---|
Components - entities | 2.5.1 | Give details of all entities within the simulation including a description of their role in the model and a description of all their attributes. |
Components - activities | 2.5.2 | Describe the activities that entities engage in within the model. Provide details of entity routing into and out of the activity. |
Components - resources | 2.5.3 | List all the resources included within the model and which activities make use of them. |
Components - queues | 2.5.4 | Give details of the assumed queuing discipline used in the model (e.g. First in First Out, Last in First Out, prioritisation, etc.). Where one or more queues have a different discipline from the rest, provide a list of queues, indicating the queuing discipline used for each. If reneging, balking or jockeying occur, etc., provide details of the rules. Detail any delays or capacity constraints on the queues. |
Components - entry/exit points | 2.5.5 | Give details of the model boundaries i.e. all arrival and exit points of entities. Detail the arrival mechanism (e.g. ‘thinning’ to mimic a non-homogenous Poisson process or balking). |
Section/Subsection | Item | Recommendation |
---|---|---|
Data sources | 3.1 | List and detail all data sources. Sources may include: • Interviews with stakeholders, • Samples of routinely collected data, • Prospectively collected samples for the purpose of the simulation study, • Public domain data published in either academic or organisational literature. Provide, where possible, the link and DOI to the data or reference to published literature. All data source descriptions should include details of the sample size, sample date ranges and use within the study. |
Pre-processing | 3.2 | Provide details of any data manipulation that has taken place before its use in the simulation, e.g. interpolation to account for missing data or the removal of outliers. |
Section/Subsection | Item | Recommendation |
---|---|---|
Input parameters | 3.3 | List all input variables in the model. Provide a description of their use and include parameter values. For stochastic inputs provide details of any continuous, discrete or empirical distributions used along with all associated parameters. Give details of all time dependent parameters and correlation. Clearly state: • Base case data • Data use in experimentation, where different from the base case. • Where optimisation or design of experiments has been used, state the range of values that parameters can take. • Where theoretical distributions are used, state how these were selected and prioritised above other candidate distributions. |
Assumptions | 3.4 | Where data or knowledge of the real system is unavailable what assumptions are included in the model? This might include parameter values, distributions or routing logic within the model. |
Section/Subsection | Item | Recommendation |
---|---|---|
Initialisation | 4.1 | Report if the system modelled is terminating or non-terminating. State if a warm-up period has been used, its length and the analysis method used to select it. For terminating systems state the stopping condition. State what if any initial model conditions have been included, e.g., pre-loaded queues and activities. Report whether initialisation of these variables is deterministic or stochastic. |
Run length | 4.2 | Detail the run length of the simulation model and time units. |
Estimation approach | 4.3 | State the method used to account for the stochasticity: For example, two common methods are multiple replications or batch means. Where multiple replications have been used, state the number of replications and for batch means, indicate the batch length and whether the batch means procedure is standard, spaced or overlapping. For both procedures provide a justification for the methods used and the number of replications/size of batches. |
Section/Subsection | Item | Recommendation |
---|---|---|
Software or programming language | 5.1 | State the operating system and version and build number. State the name, version and build number of commercial or open source DES software that the model is implemented in. State the name and version of general-purpose programming languages used (e.g. Python 3.5). Where frameworks and libraries have been used provide all details including version numbers. |
Random sampling | 5.2 | State the algorithm used to generate random samples in the software/programming language used e.g. Mersenne Twister. If common random numbers are used, state how seeds (or random number streams) are distributed among sampling processes. |
Section/Subsection | Item | Recommendation |
---|---|---|
Model execution | 5.3 | State the event processing mechanism used e.g. three phase, event, activity, process interaction. Note that in some commercial software the event processing mechanism may not be published. In these cases authors should adhere to item 5.1 software recommendations. State all priority rules included if entities/activities compete for resources. If the model is parallel, distributed and/or use grid or cloud computing, etc., state and preferably reference the technology used. For parallel and distributed simulations the time management algorithms used. If the HLA is used then state the version of the standard, which run-time infrastructure (and version), and any supporting documents (FOMs, etc.) |
System specification | 5.4 | State the model run time and specification of hardware used. This is particularly important for large scale models that require substantial computing power. For parallel, distributed and/or use grid or cloud computing, etc. state the details of all systems used in the implementation (processors, network, etc.). |
Section/Subsection | Item | Recommendation |
---|---|---|
Computer model sharing statement | 6.1 | Describe how someone could obtain the model described in the paper, the simulation software and any other associated software (or hardware) needed to reproduce the results. Provide, where possible, the link and Digital Object Identifiers (DOIs) to these. |
STARS stands for ‘Sharing Tools and Artefacts for Reusable Simulation’
The STARS framework is a set of practical guidelines to help modellers share their simulation models in a way that makes them:
✅ Accessible – so others can easily find and access your model.
✅ Reusable - so people can use and adapt the model for their own work.
✅ Understandable and well-documented - so others can engage with and understand your model better.
Overview of the STARS Framework from Monks et al. (2024) (CC BY 4.0).
Read the full release notes here
Read the full release notes here
Read the full release notes here
Make sure you update version numbers in your requirements.txt or environment.yml file!
I’ve adapted some code to make a neat little metric card that can acept icons from the material icon library.
def iconMetricContainer(key,icon_unicode,css_style=None,icon_color='grey', family="filled", type="icons"):
"""Function that returns a CSS styled container for adding a Material Icon to a Streamlit st.metric value
CREDIT for starter version of this code: https://discuss.streamlit.io/t/adding-an-icon-to-a-st-metric-easily/59140?u=sammi1
Args:
key (str): Unique key for the component
iconUnicode (str): Code point for a Material Icon, you can find them here https://fonts.google.com/icons. Sample \e8b6
css_style(str, optional): Additional CSS to apply
icon_color (str, optional): HTML Hex color value for the icon. Defaults to 'grey'.
family(str, optional): "filled" or "outline". Only works with type = "icons"
type(str, optional): "icons" or "symbols"
Returns:
DeltaGenerator: A container object. Elements can be added to this container using either the 'with'
notation or by calling methods directly on the returned object.
"""
if (family == "filled") and (type=="icons"):
font_family = "Material Icons"
elif (family == "outline") and (type=="icons"):
font_family = "Material Icons Outlined"
# elif (family == "filled") and (type=="symbols"):
# font_family = "Material Symbols"
elif type=="symbols":
font_family = "Material Symbols Outlined"
else:
print("ERROR - Check Params for iconMetricContainer")
font_family = "Material Icons"
css_style_icon=f'''
div[data-testid="stMetricValue"]>div::before
{{
font-family: {font_family};
content: "\{icon_unicode}";
vertical-align: -20%;
color: {icon_color};
}}
'''
if css_style is not None:
css_style_icon += """
"""
css_style_icon += css_style
iconMetric=stylable_container(
key=key,
css_styles=css_style_icon
)
return iconMetric
Is there something clunky you have to keep looking up in VSCode?
Turn it into your own reusable snippet!
Open the menu from file –> preferences
We will now be presented with a list of possible snippet languages.
If working with Quarto, choose ‘Quarto’ from the dropdown. There’s a neat little shortcut in VSCode we can use to access snippets while writing quarto docs (CTRL + SPACE).
Alternatively, select Python - in Python, our snippets will automatically be suggested as we start typing.
Here, I’ve written a sample
You can find more out writing snippets here
{
// Place your snippets for markdown here. Each snippet is defined under a snippet name and has a prefix, body and
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
// same ids are connected.
// Example:
// "Print to console": {
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Make a two-column layout": {
"prefix": "col2",
"body": [
":::: {.columns}",
"",
"::: {.column width='50%'}",
"",
":::",
"",
"::: {.column width='50%'}",
"",
":::",
"",
"::::"
],
"description": "Create a column layout in quarto with two columns of equal width"
},
"Make a fragment": {
"prefix": "frag",
"body": [
"::: {.fragment}",
"",
":::"
],
"description": "Create a quarto fragment for incremental revealing of content"
},
"Make an incremental list": {
"prefix": "inc",
"body": [
"::: {.incremental}",
"",
":::"
],
"description": "Create a quarto incremental list container for revealing one bullet point at a time"
}
}
Now, when I press CTRL + SPACE, I can type in my snippet IDs and select them to make them populate my document
Python snippets are similar!
Here we’ve defined a snippet called ‘condlist’ for generating a conditional list comprehension.
{
// Place your snippets for python here. Each snippet is defined under a snippet name and has a prefix, body and
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
// same ids are connected.
// Example:
// "Print to console": {
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Conditional list comprehension": {
"prefix": "condlist",
"body": [
"['Even' if n % 2 == 0 else 'Odd' for n in a]"
],
"description": "Provide an adaptable template for conditional logic in a list comprehension"
}
}
To find out more on snippets, click here