Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions content/code/fmr.R
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# plots log(field metabolic rate) against log(body mass) for the Nagy et al
# 1999 dataset to a file fmr.pdf.
# Plot log(field metabolic rate) against log(body mass) for the Nagy et al.
# 1999 dataset. Run from the coursework project root with:
# Rscript code/fmr.R

cat("reading CSV\n")

nagy <- read.csv('../data/nagy_et_al_1999.csv', stringsAsFactors = FALSE)
nagy <- read.csv('data/nagy_et_al_1999.csv', stringsAsFactors = FALSE)

cat("Creating graph\n")
pdf('../results/fmr_plot.pdf', 11, 8.5)
dir.create('results', showWarnings = FALSE)
pdf('results/fmr_plot.pdf', 11, 8.5)
col <- c(Aves='purple3', Mammalia='red3', Reptilia='green3')
stopifnot(all(unique(nagy$Class) %in% names(col)))
plot(log10(nagy$M.g), log10(nagy$FMR.kJ.day.1), pch=19, col=col[nagy$Class],
xlab=~log[10](M), ylab=~log[10](FMR))
for(class in unique(nagy$Class)){
Expand Down
19 changes: 16 additions & 3 deletions content/code/test_r.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#!/usr/bin/env python3

"""Run the small R example and save its output from the project root."""

import subprocess

subprocess.Popen("rscript --verbose test_r.r > \
../results/test_r.rout 2> ../results/test_r_errFile.rout",\
shell=True).wait()

with open("results/test_r.rout", "w") as output_file, \
open("results/test_r_errFile.rout", "w") as error_file:
result = subprocess.run(
["Rscript", "--verbose", "code/test_r.R"],
stdout=output_file,
stderr=error_file,
check=False,
)

print("Return code:", result.returncode)
raise SystemExit(result.returncode)
31 changes: 16 additions & 15 deletions content/notebooks/python.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8964,16 +8964,16 @@
"print(\"Hello, this is R!\")\n",
"```\n",
"\n",
"Then try running it from your bash terminal (*not* from the Python terminal) (e.g., using `Rscript test_r.R`). This should return in your terminal:\n",
"Then run it from your bash terminal (*not* from the Python terminal), starting at the coursework project root: `Rscript code/test_r.R`. This should return in your terminal:\n",
"\n",
"```bash\n",
"[1] \"Hello, this is R!\"\n",
"```\n",
"\n",
"Then try `Rscript --verbose test_r.R`. This should return something like:\n",
"Then try `Rscript --verbose code/test_r.R`. This should return something like:\n",
"\n",
"```bash\n",
" '/usr/lib/r/bin/r --no-echo --no-restore --file=test_r.R'\n",
" '/usr/lib/r/bin/r --no-echo --no-restore --file=code/test_r.R'\n",
"\n",
"[1] \"Hello, this is R!\"\n",
"```\n",
Expand All @@ -8987,10 +8987,10 @@
"Now try:\n",
"\n",
"```bash\n",
"Rscript --verbose test_r.R > ../results/test_r.rout 2> ../results/test_r_errFile.rout\n",
"Rscript --verbose code/test_r.R > results/test_r.rout 2> results/test_r_errFile.rout\n",
"```\n",
"\n",
"Then check the contents of `test_r.rout` and `test_r_errFile.rout`. The former should contain the output of the R script, and the latter the additional information produced by the `--verbose` flag. \n",
"Then check `results/test_r.rout` and `results/test_r_errFile.rout`. The former should contain the output of the R script, and the latter the additional information produced by the `--verbose` flag. \n",
"\n",
"Now try running this using subprocess instead:"
]
Expand All @@ -9001,10 +9001,10 @@
"metadata": {},
"outputs": [],
"source": [
"with open(\"../results/test_r.rout\", \"w\") as output_file, \\\n",
" open(\"../results/test_r_errFile.rout\", \"w\") as error_file:\n",
"with open(\"results/test_r.rout\", \"w\") as output_file, \\\n",
" open(\"results/test_r_errFile.rout\", \"w\") as error_file:\n",
" result = subprocess.run(\n",
" [\"Rscript\", \"--verbose\", \"test_r.R\"],\n",
" [\"Rscript\", \"--verbose\", \"code/test_r.R\"],\n",
" stdout=output_file,\n",
" stderr=error_file,\n",
" check=False,\n",
Expand Down Expand Up @@ -9034,24 +9034,25 @@
"source": [
"import subprocess\n",
"\n",
"with open(\"../results/test_r.rout\", \"w\") as output_file, \\\n",
" open(\"../results/test_r_errFile.rout\", \"w\") as error_file:\n",
"with open(\"results/test_r.rout\", \"w\") as output_file, \\\n",
" open(\"results/test_r_errFile.rout\", \"w\") as error_file:\n",
" result = subprocess.run(\n",
" [\"Rscript\", \"--verbose\", \"test_r.R\"],\n",
" [\"Rscript\", \"--verbose\", \"code/test_r.R\"],\n",
" stdout=output_file,\n",
" stderr=error_file,\n",
" check=False,\n",
" )\n",
"\n",
"print(\"Return code:\", result.returncode)"
"print(\"Return code:\", result.returncode)\n",
"raise SystemExit(result.returncode)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Now run `test_r.py` (or `%run test_r.py` in IPython) and check `test_r.rout` and `test_r_errFile.rout`.\n",
"From the project root, run `python3 code/test_r.py` (or `%run code/test_r.py` in IPython) and check `results/test_r.rout` and `results/test_r_errFile.rout`.\n",
"\n",
"Also check what happens if you run (type directly in `ipython` or `python` console):"
]
Expand All @@ -9063,7 +9064,7 @@
"outputs": [],
"source": [
"result = subprocess.run(\n",
" [\"Rscript\", \"--verbose\", \"NonExistScript.R\"],\n",
" [\"Rscript\", \"--verbose\", \"code/NonExistScript.R\"],\n",
" capture_output=True,\n",
" text=True,\n",
")\n",
Expand Down Expand Up @@ -9138,7 +9139,7 @@
"\n",
"#### Run an R analysis from Python\n",
"\n",
"Download {download}`fmr.R <../code/fmr.R>` into `code/` and {download}`nagy_et_al_1999.csv <../data/nagy_et_al_1999.csv>` into `data/`. Read the R script, then write `run_fmr_r.py` that runs `Rscript fmr.R` from the coursework project's `code/` directory using `subprocess.run()` without `shell=True`.\n",
"Download {download}`fmr.R <../code/fmr.R>` into `code/` and {download}`nagy_et_al_1999.csv <../data/nagy_et_al_1999.csv>` into `data/`. Read the R script, then write `run_fmr_r.py` that runs `Rscript code/fmr.R` from the coursework project root using `subprocess.run()` without `shell=True`.\n",
"\n",
"Capture standard output and standard error as text, print both streams with labels, and print whether the command succeeded based on its return code. On success, verify that `results/fmr_plot.pdf` exists and is non-empty; on failure, exit with a non-zero status. Your wrapper is complete when a normal run reports success and deliberately using a nonexistent R script reports failure without a Python traceback.\n",
"\n",
Expand Down
42 changes: 40 additions & 2 deletions scripts/check_r_file_workflows.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ repository_root <- normalizePath(".")
required_files <- c(
"content/code/basic_io.R",
"content/code/data_wrang.R",
"content/code/fmr.R",
"content/code/test_r.R",
"content/code/test_r.py",
"content/data/trees.csv",
"content/data/nagy_et_al_1999.csv",
"content/data/pound_hill_data.csv",
"content/data/pound_hill_meta_data.csv"
)
Expand All @@ -29,15 +33,24 @@ on.exit(unlink(project_root, recursive = TRUE), add = TRUE)

stopifnot(
all(file.copy(
file.path(repository_root, "content/code", c("basic_io.R", "data_wrang.R")),
file.path(
repository_root,
"content/code",
c("basic_io.R", "data_wrang.R", "fmr.R", "test_r.R", "test_r.py")
),
file.path(project_root, "code"),
overwrite = TRUE
)),
all(file.copy(
file.path(
repository_root,
"content/data",
c("trees.csv", "pound_hill_data.csv", "pound_hill_meta_data.csv")
c(
"trees.csv",
"nagy_et_al_1999.csv",
"pound_hill_data.csv",
"pound_hill_meta_data.csv"
)
),
file.path(project_root, "data"),
overwrite = TRUE
Expand Down Expand Up @@ -65,6 +78,31 @@ run_script("code/basic_io.R")
basic_output <- file.path("results", "MyData.csv")
stopifnot(file.exists(basic_output), file.info(basic_output)$size > 0)

run_script("code/fmr.R")
fmr_output <- file.path("results", "fmr_plot.pdf")
stopifnot(file.exists(fmr_output), file.info(fmr_output)$size > 0)

python_output <- system2(
Sys.which("python3"),
"code/test_r.py",
stdout = TRUE,
stderr = TRUE
)
python_status <- attr(python_output, "status")
if (!is.null(python_status) && python_status != 0) {
stop(paste(python_output, collapse = "\n"), call. = FALSE)
}
stopifnot(
any(grepl("Return code: 0", python_output, fixed = TRUE)),
file.exists(file.path("results", "test_r.rout")),
file.exists(file.path("results", "test_r_errFile.rout")),
grepl(
"Hello, this is R!",
paste(readLines(file.path("results", "test_r.rout")), collapse = "\n"),
fixed = TRUE
)
)

run_script("code/data_wrang.R")
wrangled_output <- read.csv(file.path("results", "pound_hill_long.csv"))
stopifnot(
Expand Down
70 changes: 0 additions & 70 deletions scripts/runtime_path_exceptions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,6 @@ exceptions:
reason: Known statistics workflow path awaiting dependency-aware chapter migration.
owner: Statistics teaching owner
target_phase: Phase 5
- location: code/fmr.R
rule: parent_project_path
value: ../data/nagy_et_al_1999.csv
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: code/fmr.R
rule: parent_project_path
value: ../results/fmr_plot.pdf
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: code/glm.R
rule: parent_project_path
value: ../data/prac_data.csv
Expand Down Expand Up @@ -103,20 +89,6 @@ exceptions:
reason: Known statistics workflow path awaiting dependency-aware chapter migration.
owner: Statistics teaching owner
target_phase: Phase 5
- location: code/test_r.py
rule: parent_project_path
value: ../results/test_r.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: code/test_r.py
rule: parent_project_path
value: ../results/test_r_errFile.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/anova.ipynb:cell 45
rule: parent_project_path
value: ../data/mammals.rdata
Expand Down Expand Up @@ -222,48 +194,6 @@ exceptions:
reason: Known statistics workflow path awaiting dependency-aware chapter migration.
owner: Statistics teaching owner
target_phase: Phase 5
- location: notebooks/python.ipynb:cell 587:fence 4
rule: parent_project_path
value: ../results/test_r.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/python.ipynb:cell 587:fence 4
rule: parent_project_path
value: ../results/test_r_errFile.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/python.ipynb:cell 588
rule: parent_project_path
value: ../results/test_r.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/python.ipynb:cell 588
rule: parent_project_path
value: ../results/test_r_errFile.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/python.ipynb:cell 591
rule: parent_project_path
value: ../results/test_r.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/python.ipynb:cell 591
rule: parent_project_path
value: ../results/test_r_errFile.rout
count: 1
reason: Known Python workflow path awaiting chapter and supplied-script migration.
owner: Python teaching owner
target_phase: Phase 4
- location: notebooks/regress.ipynb:cell 6
rule: parent_project_path
value: ../data/genome_size.csv
Expand Down