galaaz 2.1.3 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -1
- data/README.md +90 -9
- data/bin/gknit +13 -10
- data/bin/gknit_Rscript +2 -4
- data/bin/gstudio_irb.rb +71 -22
- data/blogs/README.md +1 -1
- data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +8 -8
- data/blogs/galaaz_ggplot/galaaz_ggplot.md +6 -6
- data/blogs/gknit/gknit.Rmd +12 -11
- data/blogs/gknit/gknit.md +12 -11
- data/blogs/manual/manual.Rmd +120 -33
- data/blogs/manual/manual.md +90 -9
- data/blogs/oh_my/oh_my.Rmd +7 -7
- data/blogs/oh_my/oh_my.md +7 -7
- data/blogs/ruby_plot/ruby_plot.Rmd +13 -14
- data/blogs/ruby_plot/ruby_plot.md +13 -14
- data/examples/misc/ggplot.rb +1 -1
- data/lib/R_interface/new_bridge_adapter.rb +14 -1
- data/lib/R_interface/r.rb +60 -53
- data/lib/R_interface/r_job.rb +429 -0
- data/lib/galaaz/cli.rb +58 -11
- data/lib/gknit/diagnostics.rb +3 -1
- data/lib/new_bridge/session_client.rb +45 -0
- data/specs/gknit_install_timeout_report_spec.rb +27 -7
- data/specs/r_job_spec.rb +81 -0
- data/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d39a98e695448ffb0166d33746445cc0076efcbd15e6f34250c99512e7c8e71d
|
|
4
|
+
data.tar.gz: eff6228e3febeb502838f1a6b99e38d03186327678b1a5535e58e8548e516d72
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ffe309c54323c08acabe1752c677cd67090878170b33853eb739195f4be36450379b2e100dc5e9ecfa317e4e4373aed8082dfee8407bb5231cd1d5b41c6fbdf2
|
|
7
|
+
data.tar.gz: daef47d66a2f3c20e2e430797ffd6193e9d80cde6ffc9b82856835dab4c0a3e3f8833b17d1b6b3389e4e5e3c5a7cccba8aee42d9b023b2e110758b6e678e9a2c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.5
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `gknit` / `gknit_Rscript`: resolve input with `File.expand_path` so absolute paths
|
|
8
|
+
(e.g. `~/galaaz-blogs/...`) are not prefixed with `Dir.pwd` (broke when run from
|
|
9
|
+
`~/.local/bin`).
|
|
10
|
+
- `galaaz add ledger`: do not strip app Ruby version pins; keep engine-agnostic
|
|
11
|
+
RubyGems `gem "galaaz"` rewrites only.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Omarchy `omarchy-galaaz-add`: install pandoc via `pandoc-bin` or the latest GitHub
|
|
16
|
+
linux binary into `~/.local/bin` — not Arch `pandoc` / `pandoc-cli` (Haskell deps).
|
|
17
|
+
- Omarchy menu Docs / GitHub rows use `omarchy-launch-webapp` (same as Omarchy Learn).
|
|
18
|
+
- `galaaz add arrow` / ledger path: prefer Apache `LIBARROW_BINARY` prebuilt libarrow
|
|
19
|
+
(avoid Arch pacman arrow version skew on Omarchy).
|
|
20
|
+
|
|
21
|
+
## 2.1.4
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **`R::Job`**: long CRAN installs (and arbitrary R via `R::Job.eval`) run in a **child
|
|
26
|
+
Rscript** process, not on the NewBridge gatekeeper. Logs and metadata live under
|
|
27
|
+
`~/.local/share/galaaz/jobs/` (override with `GALAAZ_JOBS_DIR`). One install at a
|
|
28
|
+
time (`install.lock`). Bridge R stays free while Ruby awaits the job. Clears stale
|
|
29
|
+
`00LOCK-<pkg>` dirs before install (left behind after kill-on-timeout).
|
|
30
|
+
- **Layer C:** `R::Job.eval` / `R::Job.script` for long arbitrary R. Child gets
|
|
31
|
+
`setwd(job.dir)`, `GALAAZ_JOB_DIR`, and `result_path` (default `result.rds`). After
|
|
32
|
+
success, `job.load_rds` does a short sync `readRDS` on the bridge. Block form
|
|
33
|
+
awaits and yields the job (`coef = R::Job.eval(code) { |j| j.load_rds }`).
|
|
34
|
+
Documented in the manual section **Background R jobs (`R::Job`)** (README /
|
|
35
|
+
`blogs/manual/manual.Rmd`).
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- `R.install_rlibs` / `R.install_and_loads` use `R::Job.install` and **await until
|
|
40
|
+
finished** by default (no bridge 60s install timeout). Optional await limit via
|
|
41
|
+
`install_timeout_sec:` or `GALAAZ_INSTALL_TIMEOUT_SEC` (also `gknit
|
|
42
|
+
--install_timeout_sec`); on timeout the child process group is killed so compile
|
|
43
|
+
work cannot OOM the shell. gknit reports install-job timeouts in the internal
|
|
44
|
+
error summary.
|
|
45
|
+
|
|
3
46
|
## 2.1.3
|
|
4
47
|
|
|
5
48
|
### Fixed
|
|
@@ -85,4 +128,6 @@ Galaaz 2.0 drives **GNU R** from **JRuby** or **CRuby** over a process bridge. I
|
|
|
85
128
|
- `grun`, `gknit_Rscript`, and the polyglot path in `gknit-draft` are leftover from the Graal era; use `galaaz-jruby` / `gknit` (or `GALAAZ_RUBY=ruby` for CRuby).
|
|
86
129
|
- The gatekeeper must be compiled on the install machine (Rcpp + C++ toolchain); it is not a prebuilt binary in the gem.
|
|
87
130
|
- Multi-runtime Docker R (Phase 4.5) is a slow integration spec, not part of cold-install CI.
|
|
88
|
-
- The gknit installation-timeout spec
|
|
131
|
+
- The gknit installation-timeout spec covers `R::Job` await timeouts
|
|
132
|
+
(`GALAAZ_INSTALL_TIMEOUT_SEC`); SimpleCov is a development gem and is not installed in
|
|
133
|
+
the smoke image.
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "Galaaz Manual"
|
|
3
3
|
subtitle: "R-on-Rails: GNU R meets Ruby for the web"
|
|
4
4
|
author: "Rodrigo Botafogo"
|
|
5
|
-
tags: [Galaaz, "R-on-Rails", Ruby, Rails, JRuby, R, "GNU R", ggplot2, knitr, dplyr, Bioconductor, Arrow]
|
|
5
|
+
tags: [Galaaz, "R-on-Rails", Ruby, Rails, JRuby, CRuby, R, "GNU R", ggplot2, knitr, dplyr, Bioconductor, Arrow]
|
|
6
6
|
date: "2026"
|
|
7
7
|
bibliography: "../../examples/Bibliography/stats.bib"
|
|
8
8
|
output:
|
|
@@ -73,7 +73,7 @@ rewrite in another stack. **R-on-Rails** means:
|
|
|
73
73
|
1. **Keep your science in R** — packages, formulas, plots, Bioconductor, the same engine as RStudio.
|
|
74
74
|
2. **Learn enough Ruby/Rails** — routes, controllers, views, jobs, auth—not a second statistics career.
|
|
75
75
|
3. **Call R from the app** — Galaaz loads R behind the scenes; long jobs can complete asynchronously
|
|
76
|
-
while Rails stays responsive (see later sections on the bridge and `R::
|
|
76
|
+
while Rails stays responsive (see later sections on the bridge, `R::Async`, and `R::Job`).
|
|
77
77
|
4. **Ship alone when you need to** — one developer can own both the analysis and the product UI,
|
|
78
78
|
without waiting for a separate “stats engineer” and “Rails engineer.”
|
|
79
79
|
|
|
@@ -358,7 +358,13 @@ A **table of all `bin/` scripts** (bootstrap, Ruby launcher, gstudio, gknit, tes
|
|
|
358
358
|
**`bin/run_all_rspec`** (same `GALAAZ_RUBY` rule). **`bin/galaaz-jruby`** remains a thin
|
|
359
359
|
wrapper that forces JRuby.
|
|
360
360
|
|
|
361
|
-
A **gstudio** try image
|
|
361
|
+
A **gstudio** try image with Galaaz already installed is available for both engines:
|
|
362
|
+
**JRuby** — `docker run --rm -it ghcr.io/rbotafogo/galaaz-try:gstudio` (or
|
|
363
|
+
`./docker/try-gstudio/run.sh` from a checkout); **CRuby** —
|
|
364
|
+
`docker run --rm -it ghcr.io/rbotafogo/galaaz-try:cruby` (or `./docker/try-cruby/run.sh`).
|
|
365
|
+
Maintainers can prove a RubyGems install on a throwaway Ubuntu machine (no repo inside
|
|
366
|
+
the container) with `./docker/cold-install/run.sh published-specs` (JRuby) or
|
|
367
|
+
`./docker/cold-install-cruby/run.sh published-specs` (CRuby).
|
|
362
368
|
|
|
363
369
|
## Windows + WSL2 (optional: Docker / R in a container)
|
|
364
370
|
|
|
@@ -394,11 +400,18 @@ WSL integration is enabled for the distro where Galaaz is installed.
|
|
|
394
400
|
``` ruby
|
|
395
401
|
vec = R.c(1, 2, 3, 4)
|
|
396
402
|
puts vec
|
|
403
|
+
|
|
404
|
+
# R.foo(...) calls an R *function*. Datasets are objects — fetch with ~:
|
|
405
|
+
df = ~R[:mtcars]
|
|
406
|
+
puts R.summary(df)
|
|
397
407
|
```
|
|
398
408
|
|
|
399
409
|
```
|
|
400
410
|
## [1] 1 2 3 4
|
|
401
411
|
```
|
|
412
|
+
|
|
413
|
+
(`R.mtcars` is wrong: it becomes `mtcars()` in R and fails. With
|
|
414
|
+
`using Galaaz::SymbolDSL`, the short form `~:mtcars` also works.)
|
|
402
415
|
|
|
403
416
|
* Run all specs
|
|
404
417
|
|
|
@@ -456,8 +469,13 @@ driver). For concurrency tests on the bridge itself, see `specs/bridge_concurren
|
|
|
456
469
|
|
|
457
470
|
## Long-running R calls and a completion block
|
|
458
471
|
|
|
459
|
-
For R work that can take a long time
|
|
460
|
-
scheduling the call and resuming in a **block** when the `RET` arrives.
|
|
472
|
+
For R work that can take a long time **on the bridge**, the bridge can avoid a Ruby-side
|
|
473
|
+
**wait timeout** by scheduling the call and resuming in a **block** when the `RET` arrives.
|
|
474
|
+
|
|
475
|
+
**Important distinction:** this keeps the **same** GNU R process busy. Other sync
|
|
476
|
+
`eval_r` / gknit chunks still wait on that R. For CRAN installs and other work that must
|
|
477
|
+
**not** monopolize the bridge (or that can OOM a small VM if abandoned mid-compile), use
|
|
478
|
+
**`R::Job`** in the next section instead.
|
|
461
479
|
|
|
462
480
|
- **`R.eval_r_async(code, timeout: nil) { |result| ... }`** — string eval; on success, `result.value`
|
|
463
481
|
is the same formatted string as **`R.eval_r`** (use `timeout: nil` for no Ruby-side limit).
|
|
@@ -514,6 +532,67 @@ the outcome to storage, and notify the client (poll, WebSocket, Turbo Stream, et
|
|
|
514
532
|
Ruby pattern above is only to show **when** the result exists (inside the block, or after data
|
|
515
533
|
written there is observed elsewhere). Runnable specs live in **`new_bridge_specs/eval_r_async_spec.rb`**.
|
|
516
534
|
|
|
535
|
+
## Background R jobs (`R::Job`)
|
|
536
|
+
|
|
537
|
+
`R::Async` / `R.eval_r_async` free the **Ruby** thread while the **same** bridge R process
|
|
538
|
+
runs your code. That is enough for Rails-style “don’t block the request thread,” but not
|
|
539
|
+
enough for heavy `install.packages` or multi-minute model fits: the gatekeeper R is still
|
|
540
|
+
busy, other chunks time out, and abandoning the wait can leave compile work burning RAM.
|
|
541
|
+
|
|
542
|
+
**`R::Job`** runs that work in a **child `Rscript` process**. The bridge stays free. Logs and
|
|
543
|
+
metadata live under `~/.local/share/galaaz/jobs/` (override with `GALAAZ_JOBS_DIR`).
|
|
544
|
+
|
|
545
|
+
### Package installs
|
|
546
|
+
|
|
547
|
+
`R.install_and_loads` / `R.install_rlibs` use `R::Job.install` and **await until the child
|
|
548
|
+
finishes** (default: no wall-clock limit). Optional limit: `GALAAZ_INSTALL_TIMEOUT_SEC` or
|
|
549
|
+
`install_timeout_sec:`. On timeout the child process group is killed so leftover
|
|
550
|
+
`make`/`gcc` cannot OOM the shell. Stale `00LOCK-*` dirs are cleared before the next install.
|
|
551
|
+
Only one install runs at a time (`install.lock`).
|
|
552
|
+
|
|
553
|
+
``` ruby
|
|
554
|
+
# May take a long time the first time (e.g. caret); the bridge is not used for compile.
|
|
555
|
+
R.install_and_loads 'caret'
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Long arbitrary R (`eval` / `script`)
|
|
559
|
+
|
|
560
|
+
Prefer the **block** form (like `File.open`): await the child, yield the job, return the
|
|
561
|
+
block’s value. Without a block, the methods still await by default and return the `Job`.
|
|
562
|
+
|
|
563
|
+
``` ruby
|
|
564
|
+
coef = R::Job.eval(<<~R) { |job| job.load_rds }
|
|
565
|
+
fit <- lm(mpg ~ wt, data = mtcars)
|
|
566
|
+
saveRDS(unname(coef(fit)), result_path)
|
|
567
|
+
R
|
|
568
|
+
puts coef
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
```
|
|
572
|
+
## [1] 37.285126 -5.344472
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
``` ruby
|
|
576
|
+
# Without a block: awaits (wait: true is the default) and returns the Job
|
|
577
|
+
job = R::Job.eval(code)
|
|
578
|
+
job = R::Job.eval(code, wait: false) # start only; call job.wait later
|
|
579
|
+
|
|
580
|
+
# Script file; trailing args → commandArgs(trailingOnly=TRUE) in the child
|
|
581
|
+
res = R::Job.script('train.R', '5') { |job| job.load_rds }
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
In the child: `setwd(job.dir)`, `.libPaths` includes the Galaaz user library,
|
|
585
|
+
`GALAAZ_JOB_DIR` is set, and **`result_path`** defaults to
|
|
586
|
+
`file.path(GALAAZ_JOB_DIR, "result.rds")`. Persist with `saveRDS(..., result_path)`, then
|
|
587
|
+
load on the bridge with **`job.load_rds`** (short sync `readRDS` → a normal Galaaz R object).
|
|
588
|
+
|
|
589
|
+
### Choosing async vs Job
|
|
590
|
+
|
|
591
|
+
| Need | Use |
|
|
592
|
+
|------|-----|
|
|
593
|
+
| Don’t freeze a Ruby thread; short/medium R on the bridge is OK | `R::Async` / `R.eval_r_async` |
|
|
594
|
+
| Install CRAN packages, or long R that must not block the bridge | `R::Job` / `R.install_and_loads` |
|
|
595
|
+
|
|
517
596
|
## Galaaz + Rails (R-on-Rails) integration baseline
|
|
518
597
|
|
|
519
598
|
This is the practical **R-on-Rails** starter: an R scientist’s analysis behind a small Rails
|
|
@@ -1873,7 +1952,8 @@ using even a very complex package as 'caret' is trivial with Galaaz.
|
|
|
1873
1952
|
|
|
1874
1953
|
A word of advice: the 'caret' package has lots of dependencies and installing
|
|
1875
1954
|
it in a Linux system is a time consuming operation. Method 'R.install_and_loads'
|
|
1876
|
-
will install the package if it is not already installed
|
|
1955
|
+
will install the package if it is not already installed (via **`R::Job`**: a child
|
|
1956
|
+
`Rscript`, so the bridge stays free) and can take a while.
|
|
1877
1957
|
|
|
1878
1958
|
````
|
|
1879
1959
|
```{include model}
|
|
@@ -4194,10 +4274,11 @@ pulls in several dependencies; the first install can take several minutes.
|
|
|
4194
4274
|
## Example: DESeq2 on the airway dataset
|
|
4195
4275
|
|
|
4196
4276
|
The script **`examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb`** is the canonical
|
|
4197
|
-
version in the repository. Run it from the **Galaaz repository root** with
|
|
4277
|
+
version in the repository. Run it from the **Galaaz repository root** with either engine, for example:
|
|
4198
4278
|
|
|
4199
4279
|
```text
|
|
4200
|
-
bin/galaaz-
|
|
4280
|
+
bin/galaaz-ruby examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
|
|
4281
|
+
# or: bin/galaaz-jruby examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
|
|
4201
4282
|
```
|
|
4202
4283
|
|
|
4203
4284
|
The workflow in Ruby mirrors a standard DESeq2 vignette:
|
|
@@ -4226,7 +4307,7 @@ manual is knitted, because **DESeq2** is heavy and may be absent on the build ma
|
|
|
4226
4307
|
|
|
4227
4308
|
``` ruby
|
|
4228
4309
|
# Canonical script: examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
|
|
4229
|
-
# Run: bin/galaaz-
|
|
4310
|
+
# Run: bin/galaaz-ruby examples/.../deseq2_airway_galaaz.rb (repo root).
|
|
4230
4311
|
|
|
4231
4312
|
require 'galaaz'
|
|
4232
4313
|
|
data/bin/gknit
CHANGED
|
@@ -65,26 +65,22 @@ that are created during rendering.") do |opt|
|
|
|
65
65
|
opts.on("--callback_timeout_ms TIMEOUT_MS", Integer, "Callback timeout in milliseconds for R<->Ruby calls inside chunk execution. Use for long installs/computation (e.g., 7200000 for 2h).") do |opt|
|
|
66
66
|
options[:callback_timeout_ms] = opt
|
|
67
67
|
end
|
|
68
|
-
opts.on("--bridge_timeout_sec TIMEOUT_SEC", Integer, "Bridge request timeout in seconds for Ruby->R eval calls (default 60).
|
|
68
|
+
opts.on("--bridge_timeout_sec TIMEOUT_SEC", Integer, "Bridge request timeout in seconds for Ruby->R eval calls (default 60). For CRAN installs via R::Job, use GALAAZ_INSTALL_TIMEOUT_SEC instead.") do |opt|
|
|
69
69
|
options[:bridge_timeout_sec] = opt
|
|
70
70
|
end
|
|
71
|
+
opts.on("--install_timeout_sec TIMEOUT_SEC", Integer, "Await limit in seconds for R::Job package installs (sets GALAAZ_INSTALL_TIMEOUT_SEC). Default: wait until the child finishes.") do |opt|
|
|
72
|
+
options[:install_timeout_sec] = opt
|
|
73
|
+
end
|
|
71
74
|
end
|
|
72
75
|
|
|
73
76
|
remaining_args = parser.permute(ARGV.dup)
|
|
74
77
|
ARGV.replace(remaining_args)
|
|
75
78
|
|
|
76
|
-
# Sets the directory
|
|
77
|
-
dir = Dir.pwd
|
|
78
|
-
|
|
79
|
-
#=========================================================================================
|
|
80
|
-
# Check if the name of the file to gKnit was given and that it exists. If not,
|
|
81
|
-
# issue error.
|
|
82
|
-
#=========================================================================================
|
|
83
|
-
|
|
84
79
|
options[:input_file] = ARGV[0] if !ARGV[0].nil?
|
|
85
80
|
raise "Input file name is required for gKnitting. Add -f FILE or --input_file FILE. For help, type gknit -h" if
|
|
86
81
|
options[:input_file].nil?
|
|
87
|
-
|
|
82
|
+
# File.expand_path keeps absolute paths intact (do not prefix Dir.pwd).
|
|
83
|
+
options[:input_file] = File.expand_path(options[:input_file])
|
|
88
84
|
raise "File #{options[:input_file]} does not exist!" if !File.exist?(options[:input_file])
|
|
89
85
|
|
|
90
86
|
#=========================================================================================
|
|
@@ -153,6 +149,7 @@ input_dir = File.dirname(input_file)
|
|
|
153
149
|
code = <<EOF
|
|
154
150
|
ENV['GALAAZ_CALLBACK_TIMEOUT_MS'] = #{options[:callback_timeout_ms].to_s.inspect} if #{!options[:callback_timeout_ms].nil?}
|
|
155
151
|
ENV['GALAAZ_BRIDGE_TIMEOUT_SEC'] = #{options[:bridge_timeout_sec].to_s.inspect} if #{!options[:bridge_timeout_sec].nil?}
|
|
152
|
+
ENV['GALAAZ_INSTALL_TIMEOUT_SEC'] = #{options[:install_timeout_sec].to_s.inspect} if #{!options[:install_timeout_sec].nil?}
|
|
156
153
|
require %q(galaaz)
|
|
157
154
|
require %q(gknit)
|
|
158
155
|
|
|
@@ -199,6 +196,11 @@ Dir.chdir(#{input_dir.inspect}) do
|
|
|
199
196
|
STDERR.puts "Likely bridge timeout during long-running Ruby->R evaluation."
|
|
200
197
|
STDERR.puts "Current bridge timeout: \#{bridge_sec} sec; callback timeout: \#{callback_ms} ms."
|
|
201
198
|
STDERR.puts "Use gknit --bridge_timeout_sec <sec> and/or --callback_timeout_ms <ms> for longer operations."
|
|
199
|
+
elsif e.message.to_s.match?(/install job timed out/i)
|
|
200
|
+
install_sec = ENV['GALAAZ_INSTALL_TIMEOUT_SEC'] || '(none - wait until done)'
|
|
201
|
+
STDERR.puts "Likely R::Job install await timeout."
|
|
202
|
+
STDERR.puts "Current GALAAZ_INSTALL_TIMEOUT_SEC: \#{install_sec}."
|
|
203
|
+
STDERR.puts "Use gknit --install_timeout_sec <sec> (or unset it to wait forever), or install the package outside gknit."
|
|
202
204
|
end
|
|
203
205
|
if missing_pkg
|
|
204
206
|
STDERR.puts "Likely missing LaTeX package: \#{missing_pkg} (install with tlmgr)."
|
|
@@ -218,6 +220,7 @@ libx = File.expand_path('../lib', File.dirname(__FILE__))
|
|
|
218
220
|
require File.join(libx, 'galaaz_ruby')
|
|
219
221
|
ENV['GALAAZ_CALLBACK_TIMEOUT_MS'] = options[:callback_timeout_ms].to_s if !options[:callback_timeout_ms].nil?
|
|
220
222
|
ENV['GALAAZ_BRIDGE_TIMEOUT_SEC'] = options[:bridge_timeout_sec].to_s if !options[:bridge_timeout_sec].nil?
|
|
223
|
+
ENV['GALAAZ_INSTALL_TIMEOUT_SEC'] = options[:install_timeout_sec].to_s if !options[:install_timeout_sec].nil?
|
|
221
224
|
exec "#{GalaazRuby.shell_invocation(libx)} -e #{Shellwords.escape(code)}"
|
|
222
225
|
|
|
223
226
|
=begin
|
data/bin/gknit_Rscript
CHANGED
|
@@ -30,9 +30,6 @@ OptionParser.new do |opts|
|
|
|
30
30
|
end
|
|
31
31
|
end.parse!
|
|
32
32
|
|
|
33
|
-
# Sets the directory
|
|
34
|
-
dir = Dir.pwd
|
|
35
|
-
|
|
36
33
|
#=========================================================================================
|
|
37
34
|
# Check if the name of the file to gKnit was given and that it exists. If not,
|
|
38
35
|
# issue error.
|
|
@@ -41,7 +38,8 @@ dir = Dir.pwd
|
|
|
41
38
|
options[:input_file] = ARGV[0] if !ARGV[0].nil?
|
|
42
39
|
raise "Input file name is required for gKnitting. Add -f FILE or --input_file FILE. For help, type gknit -h" if
|
|
43
40
|
options[:input_file].nil?
|
|
44
|
-
|
|
41
|
+
# File.expand_path keeps absolute paths intact (do not prefix Dir.pwd).
|
|
42
|
+
options[:input_file] = File.expand_path(options[:input_file])
|
|
45
43
|
raise "File #{options[:input_file]} does not exist!" if !File.exist?(options[:input_file])
|
|
46
44
|
|
|
47
45
|
#=========================================================================================
|
data/bin/gstudio_irb.rb
CHANGED
|
@@ -1,36 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'galaaz'
|
|
2
4
|
require 'ggplot'
|
|
3
|
-
require 'irb/completion'
|
|
4
5
|
require 'pp'
|
|
6
|
+
require 'irb'
|
|
7
|
+
require 'reline'
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
:PROMPT_I => "galaaz >> ",
|
|
8
|
-
:PROMPT_S => "%l>> ",
|
|
9
|
-
:PROMPT_C => ".. ",
|
|
10
|
-
:PROMPT_N => ".. ",
|
|
11
|
-
:RETURN => "=> %s\n"
|
|
12
|
-
}
|
|
9
|
+
# --- terminal capability -------------------------------------------------------
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
def gstudio_colorize?
|
|
12
|
+
return false unless ENV['NO_COLOR'].to_s.empty?
|
|
13
|
+
return false if ENV['TERM'].to_s == 'dumb'
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def gstudio_version
|
|
18
|
+
spec = Gem.loaded_specs['galaaz']
|
|
19
|
+
return spec.version.to_s if spec
|
|
20
|
+
|
|
21
|
+
version_rb = File.expand_path('../../version.rb', __FILE__)
|
|
22
|
+
if File.file?(version_rb)
|
|
23
|
+
load version_rb
|
|
24
|
+
return $version.to_s if defined?($version) && $version
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
'?'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
colorize = gstudio_colorize?
|
|
31
|
+
dumb = ENV['TERM'].to_s == 'dumb'
|
|
32
|
+
|
|
33
|
+
# --- modern IRB defaults (Ruby >= 3.1 / Reline) --------------------------------
|
|
34
|
+
|
|
35
|
+
IRB.conf[:USE_MULTILINE] = !dumb
|
|
36
|
+
IRB.conf[:USE_COLORIZE] = colorize
|
|
37
|
+
IRB.conf[:USE_AUTOCOMPLETE] = !dumb
|
|
15
38
|
IRB.conf[:AUTO_INDENT] = true
|
|
16
39
|
IRB.conf[:SAVE_HISTORY] = 1000
|
|
17
|
-
IRB.conf[:HISTORY_FILE] = '~/.galaaz.history'
|
|
40
|
+
IRB.conf[:HISTORY_FILE] = File.expand_path('~/.galaaz.history')
|
|
41
|
+
# R-like session: expression results are printed by Galaaz/R, not Ruby inspect.
|
|
18
42
|
IRB.conf[:ECHO] = false
|
|
19
43
|
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
cyan = colorize ? "\e[36m" : ''
|
|
45
|
+
bold = colorize ? "\e[1m" : ''
|
|
46
|
+
reset = colorize ? "\e[0m" : ''
|
|
47
|
+
|
|
48
|
+
IRB.conf[:PROMPT][:CUSTOM] = {
|
|
49
|
+
PROMPT_I: "#{bold}#{cyan}galaaz#{reset} >> ",
|
|
50
|
+
PROMPT_S: '%l>> ',
|
|
51
|
+
PROMPT_C: '.. ',
|
|
52
|
+
PROMPT_N: '.. ',
|
|
53
|
+
RETURN: "=> %s\n"
|
|
54
|
+
}
|
|
55
|
+
IRB.conf[:PROMPT_MODE] = :CUSTOM
|
|
56
|
+
|
|
57
|
+
prior_rc = IRB.conf[:IRB_RC]
|
|
58
|
+
IRB.conf[:IRB_RC] = lambda do |context|
|
|
59
|
+
prior_rc.call(context) if prior_rc.respond_to?(:call)
|
|
60
|
+
puts "Galaaz #{gstudio_version} on #{RUBY_ENGINE} #{RUBY_VERSION} " \
|
|
61
|
+
"(IRB #{IRB::VERSION}). Tab completes; `history` lists input."
|
|
62
|
+
end
|
|
22
63
|
|
|
23
|
-
|
|
24
|
-
history_array = Readline::HISTORY.to_a
|
|
64
|
+
# --- session helpers -----------------------------------------------------------
|
|
25
65
|
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
count =
|
|
66
|
+
module Kernel
|
|
67
|
+
# Print recent input lines. Optional +count+ limits to the last N entries.
|
|
68
|
+
def history(count = 0)
|
|
69
|
+
history_array =
|
|
70
|
+
if defined?(Reline::HISTORY)
|
|
71
|
+
Reline::HISTORY.to_a
|
|
72
|
+
elsif defined?(Readline::HISTORY)
|
|
73
|
+
Readline::HISTORY.to_a
|
|
74
|
+
else
|
|
75
|
+
[]
|
|
76
|
+
end
|
|
29
77
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end
|
|
78
|
+
if count.is_a?(Integer) && count > 0
|
|
79
|
+
history_array = history_array.last(count)
|
|
80
|
+
end
|
|
34
81
|
|
|
35
|
-
|
|
82
|
+
puts history_array.join("\n")
|
|
83
|
+
nil
|
|
84
|
+
end
|
|
36
85
|
end
|
data/blogs/README.md
CHANGED
|
@@ -95,6 +95,6 @@ GALAAZ_DEBUG_R=1 bin/run_example examples/sthda_ggplot/all.rb
|
|
|
95
95
|
|
|
96
96
|
## Requirements
|
|
97
97
|
|
|
98
|
-
- **JRuby** (same as specs/examples).
|
|
98
|
+
- **JRuby** or **CRuby** (same as specs/examples; use `bin/galaaz-ruby` / `GALAAZ_RUBY`).
|
|
99
99
|
- **R** with packages used by the document (e.g. `rmarkdown`, `knitr`, `ggplot2`).
|
|
100
100
|
- Run from the project root so `lib` and `bin` resolve correctly.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Ruby Plotting with Galaaz"
|
|
3
|
-
subtitle: "An example of tightly coupling Ruby and R (JRuby + GNU R, Galaaz 2.0)"
|
|
3
|
+
subtitle: "An example of tightly coupling Ruby and R (JRuby or CRuby + GNU R, Galaaz 2.0)"
|
|
4
4
|
author: "Rodrigo Botafogo"
|
|
5
|
-
tags: [Galaaz, Ruby, R, JRuby, "GNU R", ggplot2]
|
|
5
|
+
tags: [Galaaz, Ruby, R, JRuby, CRuby, "GNU R", ggplot2]
|
|
6
6
|
date: "16 October 2018 (narrative updated for Galaaz 2.0, 2026)"
|
|
7
7
|
output:
|
|
8
8
|
html_document:
|
|
@@ -36,11 +36,11 @@ widely used examples among **many thousands** of packages on PyPI for numerical
|
|
|
36
36
|
With Galaaz we do not intend to re-implement any of the scientific libraries in R; we allow
|
|
37
37
|
for very tight coupling between the two languages to the point that the Ruby developer does
|
|
38
38
|
not need to think about R syntax for every call. **Galaaz 2.0** does this with **[JRuby](https://www.jruby.org/)**
|
|
39
|
-
and **GNU R**: a **bridge** evaluates R from Ruby and exchanges data between processes.
|
|
39
|
+
or **CRuby** and **GNU R**: a **bridge** evaluates R from Ruby and exchanges data between processes.
|
|
40
40
|
|
|
41
41
|
An **earlier** Galaaz prototype used Oracle’s **GraalVM** with **TruffleRuby** and **FastR** in one JVM.
|
|
42
|
-
That stack is **historical**; today’s documentation and tooling assume **JRuby
|
|
43
|
-
project manual and **`bin/galaaz-
|
|
42
|
+
That stack is **historical**; today’s documentation and tooling assume **NewBridge on JRuby or CRuby**
|
|
43
|
+
(see the project manual and **`bin/galaaz-ruby`** / **`bin/gknit`**).
|
|
44
44
|
|
|
45
45
|
For background on the old stack:
|
|
46
46
|
|
|
@@ -68,7 +68,7 @@ Galaaz is the Portuguese name for "Galahad". From Wikipedia:
|
|
|
68
68
|
|
|
69
69
|
## Prerequisites (Galaaz 2.0)
|
|
70
70
|
|
|
71
|
-
* **JRuby** and a compatible **JDK**
|
|
71
|
+
* **JRuby** and a compatible **JDK**, *or* **CRuby 3.3+**
|
|
72
72
|
* **GNU R** on your `PATH`
|
|
73
73
|
|
|
74
74
|
The following R packages will be automatically installed when necessary, but could be installed prior
|
|
@@ -334,5 +334,5 @@ nicely complement R packages.
|
|
|
334
334
|
|
|
335
335
|
For the Ruby developer, Galaaz allows the immediate use of R functions with minimal ceremony. As
|
|
336
336
|
shown in the second example above, class `ScatterPlot` hides most R call details from the Ruby
|
|
337
|
-
developer. **JRuby**
|
|
338
|
-
ecosystem
|
|
337
|
+
developer. Prefer **JRuby** when you want **real parallel threads** on the Ruby side and access to
|
|
338
|
+
the JVM ecosystem; **CRuby** works equally for the Galaaz bridge itself.
|
|
@@ -12,13 +12,13 @@ With Galaaz we do not intend to re-implement any of the scientific
|
|
|
12
12
|
libraries in R; we allow for very tight coupling between the two
|
|
13
13
|
languages to the point that the Ruby developer does not need to think
|
|
14
14
|
about R syntax for every call. **Galaaz 2.0** does this with
|
|
15
|
-
**[JRuby](https://www.jruby.org/)** and **GNU R**: a **bridge**
|
|
15
|
+
**[JRuby](https://www.jruby.org/)** or **CRuby** and **GNU R**: a **bridge**
|
|
16
16
|
evaluates R from Ruby and exchanges data between processes.
|
|
17
17
|
|
|
18
18
|
An **earlier** Galaaz prototype used Oracle’s **GraalVM** with
|
|
19
19
|
**TruffleRuby** and **FastR** in one JVM. That stack is **historical**;
|
|
20
|
-
today’s documentation and tooling assume **JRuby
|
|
21
|
-
project manual and **`bin/galaaz-
|
|
20
|
+
today’s documentation and tooling assume **NewBridge on JRuby or CRuby**
|
|
21
|
+
(see the project manual and **`bin/galaaz-ruby`** / **`bin/gknit`**).
|
|
22
22
|
|
|
23
23
|
For background on the old stack:
|
|
24
24
|
|
|
@@ -47,7 +47,7 @@ Galaaz is the Portuguese name for “Galahad”. From Wikipedia:
|
|
|
47
47
|
|
|
48
48
|
## Prerequisites (Galaaz 2.0)
|
|
49
49
|
|
|
50
|
-
- **JRuby** and a compatible **JDK**
|
|
50
|
+
- **JRuby** and a compatible **JDK**, *or* **CRuby 3.3+**
|
|
51
51
|
- **GNU R** on your `PATH`
|
|
52
52
|
|
|
53
53
|
The following R packages will be automatically installed when necessary,
|
|
@@ -360,5 +360,5 @@ nicely complement R packages.
|
|
|
360
360
|
For the Ruby developer, Galaaz allows the immediate use of R functions
|
|
361
361
|
with minimal ceremony. As shown in the second example above, class
|
|
362
362
|
`ScatterPlot` hides most R call details from the Ruby developer.
|
|
363
|
-
**JRuby**
|
|
364
|
-
to the JVM ecosystem
|
|
363
|
+
Prefer **JRuby** when you want **real parallel threads** on the Ruby side and access
|
|
364
|
+
to the JVM ecosystem; **CRuby** works equally for the Galaaz bridge itself.
|
data/blogs/gknit/gknit.Rmd
CHANGED
|
@@ -3,7 +3,7 @@ title: "How to do reproducible research in Ruby with gKnit"
|
|
|
3
3
|
author:
|
|
4
4
|
- "Rodrigo Botafogo"
|
|
5
5
|
- "Daniel Mossé - University of Pittsburgh"
|
|
6
|
-
tags: [Tech, Data Science, Ruby, R, JRuby, "GNU R", Galaaz, gKnit, knitr]
|
|
6
|
+
tags: [Tech, Data Science, Ruby, R, JRuby, CRuby, "GNU R", Galaaz, gKnit, knitr]
|
|
7
7
|
date: "29/04/2019 (narrative updated for Galaaz 2.0, 2026)"
|
|
8
8
|
bibliography: stats.bib
|
|
9
9
|
output:
|
|
@@ -109,7 +109,7 @@ written both in Ruby and/or R and output it in any of the available formats of _
|
|
|
109
109
|
allows ruby developers to do literate programming and reproducible research by allowing them to
|
|
110
110
|
have in a single document, text and code.
|
|
111
111
|
|
|
112
|
-
gKnit runs with **JRuby**, **GNU R**, and **Galaaz** (the integration layer between Ruby and R—see below).
|
|
112
|
+
gKnit runs with **JRuby or CRuby**, **GNU R**, and **Galaaz** (the integration layer between Ruby and R—see below).
|
|
113
113
|
Knitr and **R Markdown** orchestrate the document; Galaaz’s engine keeps **Ruby state across chunks**
|
|
114
114
|
and talks to R through the **bridge**. Ruby chunks can read and update R variables (`~R[:name]`, `R.*`)
|
|
115
115
|
without GraalVM-style polyglot interop.
|
|
@@ -139,7 +139,7 @@ title: "How to do reproducible research in Ruby with gKnit"
|
|
|
139
139
|
author:
|
|
140
140
|
- "Rodrigo Botafogo"
|
|
141
141
|
- "Daniel Mossé - University of Pittsburgh"
|
|
142
|
-
tags: [Tech, Data Science, Ruby, R, JRuby, "GNU R", Galaaz]
|
|
142
|
+
tags: [Tech, Data Science, Ruby, R, JRuby, CRuby, "GNU R", Galaaz]
|
|
143
143
|
date: "20/02/2019"
|
|
144
144
|
output:
|
|
145
145
|
html_document:
|
|
@@ -610,7 +610,8 @@ using even a very complex package as 'caret' is trivial with Galaaz.
|
|
|
610
610
|
|
|
611
611
|
A word of advice: the 'caret' package has lots of dependencies and installing
|
|
612
612
|
it in a Linux system is a time consuming operation. Method 'R.install_and_loads'
|
|
613
|
-
will install the package if it is not already installed
|
|
613
|
+
will install the package if it is not already installed (via **`R::Job`**: a child
|
|
614
|
+
`Rscript`, so the bridge stays free) and can take a while.
|
|
614
615
|
|
|
615
616
|
````
|
|
616
617
|
```{include model}`r ''`
|
|
@@ -633,7 +634,7 @@ puts model.test.head
|
|
|
633
634
|
gKnit also allows developers to document and load files that are not in the same directory
|
|
634
635
|
of the '.Rmd' file.
|
|
635
636
|
|
|
636
|
-
Here is an example of loading the 'find.rb' file from
|
|
637
|
+
Here is an example of loading the 'find.rb' file from Ruby (via `$LOAD_PATH`). In this example, relative
|
|
637
638
|
is set to FALSE, so Ruby will look for the file in its $LOAD\_PATH, and the user does not
|
|
638
639
|
need to know its directory.
|
|
639
640
|
|
|
@@ -657,9 +658,9 @@ the Yaml header to generate this blog in PDF format instead of HTML:
|
|
|
657
658
|
|
|
658
659
|
```
|
|
659
660
|
---
|
|
660
|
-
title: "gKnit - Ruby and R Knitting with Galaaz (JRuby + GNU R)"
|
|
661
|
+
title: "gKnit - Ruby and R Knitting with Galaaz (JRuby or CRuby + GNU R)"
|
|
661
662
|
author: "Rodrigo Botafogo"
|
|
662
|
-
tags: [Galaaz, Ruby, R, JRuby, "GNU R", knitr, gknit]
|
|
663
|
+
tags: [Galaaz, Ruby, R, JRuby, CRuby, "GNU R", knitr, gknit]
|
|
663
664
|
date: "29 October 2018"
|
|
664
665
|
output:
|
|
665
666
|
pdf\_document:
|
|
@@ -682,13 +683,13 @@ be imported from files in the system. Ideally, in reproducible research, all th
|
|
|
682
683
|
needed to rebuild a report should be easily packed together (in the same zipped directory)
|
|
683
684
|
and distributed to peers for reexecution.
|
|
684
685
|
|
|
685
|
-
**Galaaz 2.0** pairs **JRuby** with **GNU R**: you keep the full CRAN/Bioconductor world in R while
|
|
686
|
+
**Galaaz 2.0** pairs **JRuby or CRuby** with **GNU R**: you keep the full CRAN/Bioconductor world in R while
|
|
686
687
|
writing orchestration, reuse, and application code in Ruby. The effort to wrap Ruby over R (Galaaz)
|
|
687
688
|
and to wrap Knitr as gKnit was tiny compared to reimplementing R’s ecosystem in Ruby—much like
|
|
688
689
|
Python’s investment in NumPy and Pandas, which no Ruby project is likely to duplicate.
|
|
689
690
|
|
|
690
691
|
An **earlier** prototype used Oracle’s **GraalVM** and Truffle interop; the **current** stack is
|
|
691
|
-
deliberately **standard GNU R** plus the Galaaz **bridge
|
|
692
|
+
deliberately **standard GNU R** plus the Galaaz **bridge** on JRuby or CRuby, documented in the project manual.
|
|
692
693
|
|
|
693
694
|
More interesting than wrapping the R libraries with Ruby, is that Ruby adds
|
|
694
695
|
value to R, by allowing developers to use powerful and modern constructs for code reuse that
|
|
@@ -700,7 +701,7 @@ readability.
|
|
|
700
701
|
|
|
701
702
|
## Prerequisites (Galaaz 2.0)
|
|
702
703
|
|
|
703
|
-
* **JRuby** and a compatible **JDK**
|
|
704
|
+
* **JRuby** and a compatible **JDK**, *or* **CRuby 3.3+**
|
|
704
705
|
* **GNU R** on your `PATH`
|
|
705
706
|
|
|
706
707
|
The following R packages will be automatically installed when necessary, but could be installed prior
|
|
@@ -720,7 +721,7 @@ the usual build tools are typically enough. On macOS, Xcode command-line tools
|
|
|
720
721
|
## Usage
|
|
721
722
|
|
|
722
723
|
* **`bin/gknit`** \<filename\> (from the Galaaz repo or your install layout); use **`--output_format all`** for HTML and PDF together.
|
|
723
|
-
* Run Ruby with **`bin/galaaz-jruby`** when you need
|
|
724
|
+
* Run Ruby with **`bin/galaaz-ruby`** (either engine) or **`bin/galaaz-jruby`** when you need JRuby JVM flags (see the manual).
|
|
724
725
|
|
|
725
726
|
|
|
726
727
|
# References
|