cmdstan 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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"