Skip to content

Commit

Permalink
Add start of description about collaboration
Browse files Browse the repository at this point in the history
  • Loading branch information
arnold-c committed Nov 5, 2023
1 parent d276f40 commit 603f9c2
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 2 deletions.
Binary file added _book/figs/Collaboration_GitHub-issue-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _book/figs/Collaboration_issue-branch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ book:
- git-mechanics.qmd
- basic-git-workflow.qmd
- branching-strategies.qmd
- collaboration.qmd
- recommended-practices.qmd
- part: "Troubleshooting Examples"
chapters:
- deleting-branches.qmd
- merge-conflicts.qmd
- misc-troubleshooting.qmd
- references.qmd
repo-url: https://github.com/arnold-c/psu-intro-to-git
Expand Down
4 changes: 2 additions & 2 deletions branching-strategies.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ final_size_df <- map2_dfr(
func = sirmod,
parms = c(mu = 0, N = 1, beta = .x, gamma = 1/2)
)

tibble(
R0 = .y,
final_size = equil$y["R"]
Expand Down Expand Up @@ -243,4 +243,4 @@ git branch -d final-size-calc
```

</p>
</details>
</details>
234 changes: 234 additions & 0 deletions collaboration.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
# How to Collaborate
Often in science, we're not the only people who are working on a project.
If we are working with others, it is worth learning about effective ways to use Git, allowing for asynchronous collaboration and minimizing the risk of **merge conflicts**.
Fortunately for us, much of this revolves around the **branching** concept outlined in [the previous chapter](branching-strategies.qmd).

## Feature Branches

The main principal is that every new feature/change, where that is a bug fix or new model, has its own branch.
Ideally, each one will will only be a small change, but sometimes this gets away from us and results in 500 lines changes.

### Why GitHub Issues

GitHub has a couple of useful features that make this easy to work with, as well as track progress in your todo list of features.
The first key concept is the liberal use of **GitHub issues**.
For every feature I want to add, I create an **issue** (I promise this is going somewhere).
Each issue should be small enough that is only does one thing and is easy to understand and review (though it will likely be comprised of multiple **commits**).

For example, say I have just added my final size calculation code and I realize that I want update my model to be an SEIR model instead of an SIR model.
I could just make a new branch and be done with it, but creating an **issue** allows us to track which **commits** are involved in the change.
It also allows us to outline a number of changes we wish to make over the next short while and link them, making it easier to remember what we wanted to do when we come back to a project, as well as who was working on the changes.

### Creating an Issue

To create an issue, simply navigate to your project in GitHub, click on the Issues tab, and then on the "New Issue" button.

![Creating an issue](./figs/Collaboration_GitHub-issue-01.png)

From here, add a short and descriptive title, explanation, and assign the issue to someone (if you're the only person in the project, this obviously isn't necessary).
You may also find it useful to add a label to the issue to distinguish it from other issues later on (e.g., use the default "enhancement" label for new features and "bug" for bugs).

::: {.callout-tip}
You can also create a GitHub issue from directly within GitKraken if you are signed into your GitHub account.
:::

Once you have created the issue, you will see an option on the right side that suggests you "Create a branch", under the "Development" heading.
You can use this, or you can open up GitKraken and do the same thing there as GitKraken will take care of connecting the new local branch to your GitHub repository, so that's what we'll do.
Opening up your repository, you will see in the sidebar a heading "GitHub Issues".
Clicking on that will reveal your issues, and upon selecting the correct one you will see an option to create a feature branch.

![Creating an issue branch in GitKraken](./figs/Collaboration_issue-branch.png)

Going through the next steps, you can name your branch whatever you like (though I tend to leave the default suggestion as they're not hanging around for long), and which branch you want to use for the base.
If you're following the short-lived branch strategy, your base should probably be the **main** branch, an no others should be around for long enough that extra features can be branches off of them.
Once you have your new **local** branch created, you should push it so there is a copy on your **remote** repository.
At this point, you're ready to update your code.

Below is code that updates the simulation files (*simulation.R* and *simulation.py*).


<details>
<summary>
R Code
</summary>
<p>

```r
library(deSolve)
library(tidyverse)
library(rootSolve)

theme_set(theme_minimal())

sirmod <- function(t, y, parms) {
# Pull state variables from y vector
S <- y[1]
E <- y[2]
I <- y[3]
R <- y[4]

# Pull parameter values from parms vector
beta <- parms["beta"]
sigma <- parms["sigma"]
mu <- parms["mu"]
gamma <- parms["gamma"]
N <- parms["N"]

# Define equations
dS <- mu * (N - S) - beta * S * I / N
dE <- beta * S * I / N - sigma * E
dI <- sigma * E - (mu + gamma) * I
dR <- gamma * I - mu * R
res <- c(dS, dE, dI, dR)

# Return list of gradients
list(res)
}


times <- seq(0, 26, by = 1 / 10)
parms <- c(mu = 0, N = 1, beta = 2, sigma = 1, gamma = 1 / 2)
start <- c(S = 0.999, E = 0.0, I = 0.001, R = 0)

out <- ode(y = start, times = times, func = sirmod, parms = parms)
out_df <- as_tibble(out) %>%
pivot_longer(cols = -time, names_to = "state", values_to = "number") %>%
mutate(
time = as.numeric(time),
number = as.numeric(number),
state = factor(state, levels = c("S", "E", "I", "R")),
number = round(number, 6)
)

ggplot(out_df, aes(x = time, y = number, color = state)) +
geom_line(linewidth = 2) +
labs(x = "Time", y = "Number", color = "State")


# Candidate values for R0 and beta
R0 <- seq(0.1, 5, length = 50)
betas <- R0 * 1 / 2

# Calculate proportion infected for each value of R0
# map2_dfr is a {purrr} function that applies a function to two vectors i.e., it is a vectorized version of a for loop, and returns a data frame
final_size_df <- map2_dfr(
.x = betas,
.y = R0,
.f = function(.x, .y) {
equil <- runsteady(
y = c(S = 1 - 1E-5, E = 0.0, I = 1E-5, R = 0),
times = c(0, 1E5),
func = sirmod,
parms = c(mu = 0, N = 1, beta = .x, sigma = 1, gamma = 1 / 2)
)

tibble(
R0 = .y,
final_size = equil$y["R"]
)
}
)

ggplot(final_size_df, aes(x = R0, y = final_size)) +
geom_line(linewidth = 2) +
labs(x = "R0", y = "Final size")

```

</p>
</details>

<details>
<summary>Python Code</summary>
<p>

```python
# %%
import numpy as np
import pandas as pd
from scipy.integrate import solve_ivp
from plotnine import *


# %%
def sirmod(t, y, beta, mu, sigma, gamma, N):
# Unpack states
S, E, I, R = y

# Define equations
dS = mu * (N - S) - beta * S * I / N
dE = beta * S * I / N - sigma * E
dI = sigma * E - (mu + gamma) * I
dR = gamma * I - mu * R

# Return list of gradients
return dS, dE, dI, dR


# %%
tmin = 0
tmax = 26
tstep = 1 / 10
times = np.arange(tmin, tmax, tstep)

beta = 2
mu = 0
sigma = 1
gamma = 1 / 2
N = 1
parms = (beta, mu, sigma, gamma, N)

S0 = 0.999
E0 = 0
I0 = 0.001
R0 = 0
start = (S0, E0, I0, R0)

# %%
out = solve_ivp(sirmod, [tmin, tmax], np.array(start), args=parms, t_eval=times)

# %%
out_df = (
pd.DataFrame(out.y).transpose().rename(columns={0: "S", 1: "E", 2: "I", 3: "R"})
)
out_df["time"] = out.t
out_df = out_df.melt(id_vars="time", value_vars=["S", "E", "I", "R"]).rename(
columns={"variable": "state", "value": "number"}
)

# %%
theme_set(theme_minimal())

(
ggplot(out_df, aes(x="time", y="number", color="state"))
+ geom_line(size=2)
+ labs(x="Time", y="Number", color="State")
)

# %%
# Candidate values for R0 and beta
R0 = np.linspace(0.1, 5, 50)
betas = R0 * 1 / 2

# %%
solve_ivp(sirmod, [tmin, 1e5], start, args=parms).y[2, -1]

# %%
final_size_df = pd.DataFrame({"R0": R0, "final_size": np.zeros(len(R0))})

for index, beta in enumerate(betas):
p = (beta, mu, sigma, gamma, N)
final_size_df.final_size[index] = solve_ivp(sirmod, [tmin, 1e5], start, args=p).y[
2, -1
]

# %%
(
ggplot(final_size_df, aes(x="R0", y="final_size"))
+ geom_line(size=2)
+ labs(x="R0", y="Final size")
)
```

</p>
</details>
Binary file added figs/Collaboration_GitHub-issue-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added figs/Collaboration_issue-branch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 603f9c2

Please sign in to comment.