cmdstan 0.1.7 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b8f1ac614181c49f61854a38bf6c8e7ec1ed7e67fe985a98555e5a8d715f721
4
- data.tar.gz: 7c468282651c7c4641de099d1d113136b91b4962a01e088990eb48962bb32be8
3
+ metadata.gz: ca789cf84801bb8236e317d7fa3d0f4946f1dde0af355975adf48fba6d4aae38
4
+ data.tar.gz: fcf91454404ba92fa54e68102d86826fb51e390f8277d6552b9d8805c8f48ad7
5
5
  SHA512:
6
- metadata.gz: 1acc7f793f86024eb4dc289f7cbb6029aab0991fac2c8423f06b0339b2e4570a90b8a173bf9d659eb1e0d70635d367f5b2d96e753be0a1a91c5d8d2f6f786ec2
7
- data.tar.gz: 9b8ce497e5bec32cec243003f87a5dccbdaeb8139c1b204c7e0f75d610b651bae5bd1191f3b29c627b2fa47db0ef96b549d7537d66a901d89bfe60207b05dd2d
6
+ metadata.gz: 7e093e742ddd620087178b2db7ae8c854f40392e0f8b89f6db84bc9492d897c800d39ed0951523809808b91df08c0b2342503bcfbf2495a750ceb0651b5ea199
7
+ data.tar.gz: 45b9a5b9bc4fdad879d0a72ef8c0aa1d3fbe06a9ea3aeadd5ca1f18b7fae6add8190e539d55412bc46861621e9cba1bcc0e7110aa472237e2cb5383ecd781f68
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 0.2.0 (2022-04-23)
2
+
3
+ - CmdStan now installs when the first model is compiled rather than on gem installation
4
+ - Added `cmdstan_installed?` and `install_cmdstan` methods
5
+ - Updated CmdStan to 2.29.2
6
+ - Fixed issue with `summary` method
7
+ - Dropped support for Ruby < 2.7
8
+
9
+ ## 0.1.9 (2022-02-07)
10
+
11
+ - Added support for Linux ARM
12
+ - Updated CmdStan to 2.28.2
13
+
14
+ ## 0.1.8 (2022-01-16)
15
+
16
+ - Updated CmdStan to 2.28.1
17
+
1
18
  ## 0.1.7 (2021-08-23)
2
19
 
3
20
  - Updated CmdStan to 2.27.0
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  BSD 3-Clause License
2
2
 
3
3
  Copyright (c) 2019, Stan Developers and their Assignees
4
- Copyright (c) 2020-2021, Andrew Kane
4
+ Copyright (c) 2020-2022, Andrew Kane
5
5
  All rights reserved.
6
6
 
7
7
  Redistribution and use in source and binary forms, with or without
data/README.md CHANGED
@@ -2,18 +2,16 @@
2
2
 
3
3
  Bayesian inference for Ruby, powered by [CmdStan](https://github.com/stan-dev/cmdstan)
4
4
 
5
- [![Build Status](https://github.com/ankane/cmdstan/workflows/build/badge.svg?branch=master)](https://github.com/ankane/cmdstan/actions)
5
+ [![Build Status](https://github.com/ankane/cmdstan-ruby/workflows/build/badge.svg?branch=master)](https://github.com/ankane/cmdstan-ruby/actions)
6
6
 
7
7
  ## Installation
8
8
 
9
9
  Add this line to your application’s Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'cmdstan'
12
+ gem "cmdstan"
13
13
  ```
14
14
 
15
- Installation can take a few minutes as CmdStan downloads and builds.
16
-
17
15
  ## Getting Started
18
16
 
19
17
  Create a Stan file, like `bernoulli.stan`
@@ -32,7 +30,7 @@ model {
32
30
  }
33
31
  ```
34
32
 
35
- Compile the model
33
+ Compile the model (this can take a few minutes the first time as CmdStan downloads and builds)
36
34
 
37
35
  ```ruby
38
36
  model = CmdStan::Model.new(stan_file: "bernoulli.stan")
@@ -51,6 +49,12 @@ Summarize the results
51
49
  fit.summary
52
50
  ```
53
51
 
52
+ Load a compiled model
53
+
54
+ ```ruby
55
+ model = CmdStan::Model.new(exe_file: "bernoulli")
56
+ ```
57
+
54
58
  ## Maximum Likelihood Estimation
55
59
 
56
60
  ```ruby
@@ -58,29 +62,42 @@ mle = model.optimize(data: data)
58
62
  mle.optimized_params
59
63
  ```
60
64
 
65
+ ## Reference
66
+
67
+ Check if CmdStan is installed
68
+
69
+ ```ruby
70
+ CmdStan.cmdstan_installed?
71
+ ```
72
+
73
+ Install CmdStan manually
74
+
75
+ ```ruby
76
+ CmdStan.install_cmdstan
77
+ ```
78
+
61
79
  ## Credits
62
80
 
63
81
  This library is modeled after the [CmdStanPy API](https://github.com/stan-dev/cmdstanpy).
64
82
 
65
83
  ## History
66
84
 
67
- View the [changelog](https://github.com/ankane/cmdstan/blob/master/CHANGELOG.md)
85
+ View the [changelog](https://github.com/ankane/cmdstan-ruby/blob/master/CHANGELOG.md)
68
86
 
69
87
  ## Contributing
70
88
 
71
89
  Everyone is encouraged to help improve this project. Here are a few ways you can help:
72
90
 
73
- - [Report bugs](https://github.com/ankane/cmdstan/issues)
74
- - Fix bugs and [submit pull requests](https://github.com/ankane/cmdstan/pulls)
91
+ - [Report bugs](https://github.com/ankane/cmdstan-ruby/issues)
92
+ - Fix bugs and [submit pull requests](https://github.com/ankane/cmdstan-ruby/pulls)
75
93
  - Write, clarify, or fix documentation
76
94
  - Suggest or add new features
77
95
 
78
96
  To get started with development:
79
97
 
80
98
  ```sh
81
- git clone https://github.com/ankane/cmdstan.git
82
- cd cmdstan
99
+ git clone https://github.com/ankane/cmdstan-ruby.git
100
+ cd cmdstan-ruby
83
101
  bundle install
84
- bundle exec ruby ext/cmdstan/extconf.rb
85
102
  bundle exec rake test
86
103
  ```
@@ -0,0 +1,100 @@
1
+ module CmdStan
2
+ module Install
3
+ def cmdstan_version
4
+ "2.29.2"
5
+ end
6
+
7
+ def cmdstan_installed?
8
+ Dir.exist?(CmdStan.path)
9
+ end
10
+
11
+ def install_cmdstan
12
+ version = cmdstan_version
13
+ dir = CmdStan.path
14
+
15
+ # TODO figure out Mac ARM
16
+ if RbConfig::CONFIG["host_os"] !~ /darwin/i && RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
17
+ checksum = "9b7eec78e217cab39d3d794e817a1ca08f36b1e5cb434c4cd8263bb2650ba125"
18
+ url = "https://github.com/stan-dev/cmdstan/releases/download/v#{version}/cmdstan-#{version}-linux-arm64.tar.gz"
19
+ else
20
+ checksum = "567b531fa73ffdf706caa17eb3344e1dfb41e86993caf8ba40875ff910335153"
21
+ url = "https://github.com/stan-dev/cmdstan/releases/download/v#{version}/cmdstan-#{version}.tar.gz"
22
+ end
23
+
24
+ puts "Installing CmdStan version: #{version}"
25
+ puts "Install directory: #{dir}"
26
+
27
+ # only needed if default path
28
+ FileUtils.mkdir_p(File.expand_path("../../tmp", __dir__)) unless ENV["CMDSTAN"]
29
+
30
+ if Dir.exist?(dir)
31
+ puts "Already installed"
32
+ return true
33
+ end
34
+
35
+ Dir.mktmpdir do |tmpdir|
36
+ puts "Downloading..."
37
+ download_path = File.join(tmpdir, "cmdstan-#{version}.tar.gz")
38
+ download_file(url, download_path, checksum)
39
+
40
+ puts "Unpacking..."
41
+ path = File.join(tmpdir, "cmdstan-#{version}")
42
+ FileUtils.mkdir_p(path)
43
+ tar_args = Gem.win_platform? ? ["--force-local"] : []
44
+ system "tar", "xzf", download_path, "-C", path, "--strip-components=1", *tar_args
45
+
46
+ puts "Building..."
47
+ make_command = Gem.win_platform? ? "mingw32-make" : "make"
48
+ Dir.chdir(path) do
49
+ # disable precompiled header to save space
50
+ output, status = Open3.capture2e(make_command, "build", "PRECOMPILED_HEADERS=false")
51
+ if status.exitstatus != 0
52
+ puts output
53
+ raise Error, "Build failed"
54
+ end
55
+ end
56
+
57
+ FileUtils.mv(path, dir)
58
+ end
59
+
60
+ puts "Installed"
61
+
62
+ true
63
+ end
64
+
65
+ private
66
+
67
+ def download_file(url, download_path, checksum, redirects = 0)
68
+ raise Error, "Too many redirects" if redirects > 10
69
+
70
+ uri = URI(url)
71
+ location = nil
72
+
73
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
74
+ request = Net::HTTP::Get.new(uri)
75
+ http.request(request) do |response|
76
+ case response
77
+ when Net::HTTPRedirection
78
+ location = response["location"]
79
+ when Net::HTTPSuccess
80
+ digest = Digest::SHA2.new
81
+
82
+ File.open(download_path, "wb") do |f|
83
+ response.read_body do |chunk|
84
+ f.write(chunk)
85
+ digest.update(chunk)
86
+ end
87
+ end
88
+
89
+ raise Error, "Bad checksum: #{digest.hexdigest}" if digest.hexdigest != checksum
90
+ else
91
+ raise Error, "Bad response"
92
+ end
93
+ end
94
+ end
95
+
96
+ # outside of Net::HTTP block to close previous connection
97
+ download_file(location, download_path, checksum, redirects + 1) if location
98
+ end
99
+ end
100
+ end
data/lib/cmdstan/mcmc.rb CHANGED
@@ -30,7 +30,7 @@ module CmdStan
30
30
  run_command "#{CmdStan.path}/bin/stansummary#{extension}", "--csv_filename=#{path}", *@output_files.map(&:path)
31
31
 
32
32
  result = {}
33
- CSV.foreach(path, headers: true, converters: :numeric) do |row|
33
+ CSV.foreach(path, skip_lines: /^#/, headers: true, converters: :numeric) do |row|
34
34
  value = row.to_h
35
35
  name = value.delete("name")
36
36
  result[name] = value if name == "lp__" || !name.end_with?("__")
data/lib/cmdstan/model.rb CHANGED
@@ -18,8 +18,12 @@ module CmdStan
18
18
  end
19
19
 
20
20
  def compile
21
+ unless ENV["CMDSTAN"] || CmdStan.cmdstan_installed?
22
+ CmdStan.install_cmdstan
23
+ end
24
+
21
25
  Dir.chdir(CmdStan.path) do
22
- run_command make_command, @exe_file
26
+ run_command make_command, @exe_file, "PRECOMPILED_HEADERS=false"
23
27
  end
24
28
  end
25
29
 
@@ -1,3 +1,3 @@
1
1
  module CmdStan
2
- VERSION = "0.1.7"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/cmdstan.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  # stdlib
2
+ require "digest"
2
3
  require "csv"
4
+ require "fileutils"
3
5
  require "json"
6
+ require "net/http"
4
7
  require "open3"
5
8
  require "tempfile"
6
9
 
7
10
  # modules
11
+ require "cmdstan/install"
8
12
  require "cmdstan/utils"
9
13
  require "cmdstan/mcmc"
10
14
  require "cmdstan/mle"
@@ -14,6 +18,8 @@ require "cmdstan/version"
14
18
  module CmdStan
15
19
  class Error < StandardError; end
16
20
 
21
+ extend Install
22
+
17
23
  class << self
18
24
  attr_accessor :path
19
25
  end
metadata CHANGED
@@ -1,34 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmdstan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-23 00:00:00.000000000 Z
11
+ date: 2022-04-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: andrew@ankane.org
15
15
  executables: []
16
- extensions:
17
- - ext/cmdstan/extconf.rb
16
+ extensions: []
18
17
  extra_rdoc_files: []
19
18
  files:
20
19
  - CHANGELOG.md
21
20
  - LICENSE.txt
22
21
  - README.md
23
- - ext/cmdstan/Makefile
24
- - ext/cmdstan/extconf.rb
25
22
  - lib/cmdstan.rb
23
+ - lib/cmdstan/install.rb
26
24
  - lib/cmdstan/mcmc.rb
27
25
  - lib/cmdstan/mle.rb
28
26
  - lib/cmdstan/model.rb
29
27
  - lib/cmdstan/utils.rb
30
28
  - lib/cmdstan/version.rb
31
- homepage: https://github.com/ankane/cmdstan
29
+ homepage: https://github.com/ankane/cmdstan-ruby
32
30
  licenses:
33
31
  - BSD-3-Clause
34
32
  metadata: {}
@@ -40,14 +38,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
40
38
  requirements:
41
39
  - - ">="
42
40
  - !ruby/object:Gem::Version
43
- version: '2.4'
41
+ version: '2.7'
44
42
  required_rubygems_version: !ruby/object:Gem::Requirement
45
43
  requirements:
46
44
  - - ">="
47
45
  - !ruby/object:Gem::Version
48
46
  version: '0'
49
47
  requirements: []
50
- rubygems_version: 3.2.22
48
+ rubygems_version: 3.3.7
51
49
  signing_key:
52
50
  specification_version: 4
53
51
  summary: Bayesian inference for Ruby, powered by CmdStan
data/ext/cmdstan/Makefile DELETED
@@ -1,5 +0,0 @@
1
- install:
2
- @echo "Nothing to do"
3
-
4
- clean:
5
- @echo "Nothing to do"
@@ -1,66 +0,0 @@
1
- require "digest"
2
- require "fileutils"
3
- require "net/http"
4
- require "tmpdir"
5
-
6
- version = "2.27.0"
7
- checksum = "ff71f4d255cf26c2d8366a8173402656a659399468871305056aa3d56329c1d5"
8
- url = "https://github.com/stan-dev/cmdstan/releases/download/v#{version}/cmdstan-#{version}.tar.gz"
9
-
10
- path = ENV["CMDSTAN"] || File.expand_path("../../tmp/cmdstan", __dir__)
11
- FileUtils.mkdir_p(path)
12
- raise "Directory not empty. Run: rake clean" unless Dir.empty?(path)
13
-
14
- $stdout.sync = true
15
-
16
- def download_file(url, download_path, checksum)
17
- uri = URI(url)
18
- location = nil
19
-
20
- Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
21
- request = Net::HTTP::Get.new(uri)
22
- http.request(request) do |response|
23
- case response
24
- when Net::HTTPRedirection
25
- location = response["location"]
26
- when Net::HTTPSuccess
27
- digest = Digest::SHA2.new
28
-
29
- i = 0
30
- File.open(download_path, "wb") do |f|
31
- response.read_body do |chunk|
32
- f.write(chunk)
33
- digest.update(chunk)
34
-
35
- # print progress
36
- putc "." if i % 50 == 0
37
- i += 1
38
- end
39
- end
40
- puts # newline
41
-
42
- abort "Bad checksum" if digest.hexdigest != checksum
43
- else
44
- abort "Bad response"
45
- end
46
- end
47
- end
48
-
49
- # outside of Net::HTTP block to close previous connection
50
- download_file(location, download_path, checksum) if location
51
- end
52
-
53
- # download
54
- puts "Downloading #{url}..."
55
- download_path = "#{Dir.tmpdir}/cmdstan-#{version}.tar.gz"
56
- download_file(url, download_path, checksum)
57
-
58
- # extract
59
- Dir.chdir(path)
60
- # TODO use Gem::Package::TarReader from Rubygems
61
- tar_args = Gem.win_platform? ? ["--force-local"] : []
62
- system "tar", "zxf", download_path, "-C", path, "--strip-components=1", *tar_args
63
-
64
- # build
65
- make_command = Gem.win_platform? ? "mingw32-make" : "make"
66
- system make_command, "build"