datafarming 1.4.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/README.md +10 -6
- data/datafarming.gemspec +11 -6
- data/exe/datafarming.rb +33 -27
- data/exe/generate_design.rb +306 -0
- data/lib/datafarming/freq_sets.rb +52 -243
- data/lib/datafarming/nolh_designs.rb +19105 -4483
- data/lib/datafarming/res_v_seqs.rb +57 -0
- data/lib/datafarming/scale_design.rb +29 -0
- data/lib/datafarming/screen_freq_sets.rb +143 -0
- data/lib/datafarming/version.rb +5 -0
- data/lib/datafarming.rb +8 -0
- metadata +42 -18
- data/DESCRIPTIONS.html +0 -1107
- data/DESCRIPTIONS.md +0 -45
- data/exe/augment_design.rb +0 -66
- data/exe/scaled_fde.rb +0 -169
- data/exe/scaled_rf_cubed.rb +0 -173
- data/exe/stack_nolhs.rb +0 -174
- data/lib/datafarming/factorial_generator.rb +0 -49
data/DESCRIPTIONS.md
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
#### COMMAND-LINE TOOLS
|
2
|
-
|
3
|
-
Ruby is a powerful and concise object-oriented scripting language. Scripts are normally run from a command-line or terminal environment by typing the `ruby` command followed by a script name, often followed by one or more command-line arguments. However, scripts installed as gems do not need the `ruby` command to be typed explicitly. For example, typing `stripheaderdups.rb my_file.txt` will invoke the `stripheaderdups.rb` script and apply it to file `my_file.txt` in your current working directory. Note that on Windows the `.rb` suffix is not needed to run your scripts, e.g., `stripheaderdups my_file.txt` will suffice.
|
4
|
-
|
5
|
-
All scripts in this distribution are self documenting if run with a `--help`, `-h`, or `-?` option. Quick descriptions follow.
|
6
|
-
|
7
|
-
#### DATA MANIPULATION
|
8
|
-
- `blank2csv.rb` —
|
9
|
-
convert whitespace-delimited files to Comma Separated Values (CSV) files
|
10
|
-
- `cat.rb` —
|
11
|
-
Unix `cat` program work-alike for Windows—for viewing or creating text files or concatenating multiple files, based on stdio
|
12
|
-
- `convert_line_endings.rb` —
|
13
|
-
convert text files (including CSV files) to your current operating system environment (e.g., DOS to Unix or Unix to DOS)
|
14
|
-
- `csv2blank.rb` —
|
15
|
-
convert CSV files to whitespace-delimited files
|
16
|
-
- `pool_files.rb` —
|
17
|
-
pool columns from separate files into a new file, useful for combining design file & output files or multiple output files
|
18
|
-
- `stripheaders.rb`, `stripheaderdups.rb` —
|
19
|
-
remove column headers from a file, or duplicate headers within a file, respectively
|
20
|
-
|
21
|
-
#### DESIGN GENERATORS
|
22
|
-
- `augment_design.rb` —
|
23
|
-
generate star points to augment an already existing factorial design
|
24
|
-
- `cross.rb` —
|
25
|
-
create a combinatorial design by crossing all combinations of any # of individual smaller designs
|
26
|
-
- `scaled_fde.rb` —
|
27
|
-
generate fully orthogonal quadratic designs based on discrete Fourier frequencies, with factor scaling
|
28
|
-
- `scaled_rf_cubed.rb` —
|
29
|
-
generate 2-level Resolution V fractional factorial designs and Central Composite Designs (CCDs), with factor scaling
|
30
|
-
- `stack_nolhs.rb` —
|
31
|
-
generate designs by reassigning columns from pre-tabled NOLHs, with factor scaling, for up to 100 factors
|
32
|
-
|
33
|
-
#### RUN CONTROL
|
34
|
-
- `batchrunner.rb` —
|
35
|
-
run a model interactively with replication
|
36
|
-
- `rundesign_general.rb` —
|
37
|
-
run control to replicate a designed experiment applied to a model
|
38
|
-
|
39
|
-
#### CONFIDENCE INTERVALS FOR TIME SERIES
|
40
|
-
- `mser.rb` —
|
41
|
-
use MSER truncation to remove initial transient effects for time-series output, reporting truncated average and number of observations for each run to facilitate construction of a properly weighted confidence interval.
|
42
|
-
- `mser_nolbm.rb` —
|
43
|
-
use MSER truncation to remove initial transient effects for time-series output, then calculate a 95% confidence interval on the remaining data using non-overlapping batch means.
|
44
|
-
- `mser_olbm.rb` —
|
45
|
-
use MSER truncation to remove initial transient effects for time-series output, then calculate a 95% confidence interval on the remaining data using overlapping batch means.
|
data/exe/augment_design.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -w
|
2
|
-
|
3
|
-
# This script generates star points to augment a fractional factorial
|
4
|
-
# so you can check for quadratic effects.
|
5
|
-
|
6
|
-
require 'colorize'
|
7
|
-
|
8
|
-
String.disable_colorization false
|
9
|
-
|
10
|
-
require 'optparse'
|
11
|
-
require 'datafarming/error_handling'
|
12
|
-
|
13
|
-
help_msg = [
|
14
|
-
'Generate star points to augment a fractional factorial ' \
|
15
|
-
'with quadratic effects.',
|
16
|
-
'Results are white-space delimited data written to ' +
|
17
|
-
'stdout'.light_blue + ', and can be redirected', 'as desired.', '',
|
18
|
-
'Syntax:',
|
19
|
-
"\n\t#{ErrorHandling.prog_name} [--help] FACTOR_INFO".yellow, '',
|
20
|
-
"Arguments in square brackets are optional. A vertical bar '|'",
|
21
|
-
'indicates valid alternatives for invoking the option. Prefix',
|
22
|
-
'the command with "' + 'ruby'.yellow +
|
23
|
-
'" if it is not on your PATH.', '',
|
24
|
-
' --help | -h | -? | ?'.green,
|
25
|
-
"\tProduce this help message.",
|
26
|
-
' FACTOR_INFO'.green,
|
27
|
-
"\tEITHER the number of factors (produces standardized +/-1 design),",
|
28
|
-
"\tOR pairs of values " + 'low1 hi1 low2 hi2...lowN hiN'.green +
|
29
|
-
' for each of the',
|
30
|
-
"\tN factors.", ''
|
31
|
-
]
|
32
|
-
|
33
|
-
OptionParser.new do |opts|
|
34
|
-
opts.banner = "Usage: #{$PROGRAM_NAME} [-h|--help] [number of factors]"
|
35
|
-
opts.on('-h', '-?', '--help') { ErrorHandling.clean_abort help_msg }
|
36
|
-
end.parse!
|
37
|
-
|
38
|
-
if ARGV.length == 0 || (ARGV[0] == '?') || (ARGV.length > 1 && ARGV.length.odd?)
|
39
|
-
ErrorHandling.clean_abort help_msg
|
40
|
-
else
|
41
|
-
num_factors = 0
|
42
|
-
if ARGV.length == 1
|
43
|
-
num_factors = ARGV.shift.to_i
|
44
|
-
x = Array.new(num_factors, ' 0')
|
45
|
-
ranges = Array.new(2 * num_factors)
|
46
|
-
ranges.each_index { |i| ranges[i] = (i.even? ? '-1' : ' 1') }
|
47
|
-
else
|
48
|
-
num_factors = ARGV.length / 2
|
49
|
-
x = Array.new(num_factors)
|
50
|
-
ranges = ARGV
|
51
|
-
num_factors.times do |i|
|
52
|
-
x[i] = 0.5 * (ranges[2 * i].to_f + ranges[2 * i + 1].to_f)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
# create and print an array at the global center point (0,0,...,0)
|
56
|
-
puts x.join(' ')
|
57
|
-
|
58
|
-
# now generate and print the star points at +/-1 along each factor axis
|
59
|
-
num_factors.times do |i|
|
60
|
-
y = x.clone
|
61
|
-
y[i] = ranges[2 * i]
|
62
|
-
puts y.join(' ')
|
63
|
-
y[i] = ranges[2 * i + 1]
|
64
|
-
puts y.join(' ')
|
65
|
-
end
|
66
|
-
end
|
data/exe/scaled_fde.rb
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -w
|
2
|
-
|
3
|
-
require 'colorize'
|
4
|
-
String.disable_colorization false
|
5
|
-
|
6
|
-
require 'datafarming/error_handling'
|
7
|
-
require 'datafarming/freq_sets'
|
8
|
-
|
9
|
-
help_msg = [
|
10
|
-
'Generate scaled FDE designs with shifting and stacking. The resulting',
|
11
|
-
'design is written to ' +
|
12
|
-
'stdout'.light_blue + '.', '',
|
13
|
-
'Syntax:',
|
14
|
-
"\n\t#{$PROGRAM_NAME.split(%r{/|\\})[-1]} [--help]".yellow +
|
15
|
-
" [-c] [-d #] [-e] [-k #] [-s #] [file_name]\n".yellow,
|
16
|
-
"Arguments in square brackets are optional. A vertical bar '|'",
|
17
|
-
'indicates valid alternatives for invoking the option. Prefix',
|
18
|
-
'the command with "' + 'ruby'.yellow +
|
19
|
-
'" if it is not on your PATH.', '',
|
20
|
-
' --help | -h | -? | ?'.green,
|
21
|
-
"\tProduce this help message. Supersedes any other choices.",
|
22
|
-
' --csv | -c'.green,
|
23
|
-
"\tGenerate output as comma-separated-values.",
|
24
|
-
' --num_factors # | -k #'.green,
|
25
|
-
"\tSpecify number of factors using standard (+/-1) scaling.",
|
26
|
-
' --design # | -d #'.green,
|
27
|
-
"\tSpecify which design number you want. Default is highest",
|
28
|
-
"\tfrequency set available for the target number of factors.",
|
29
|
-
"\tAn input larger than the available number will produce an",
|
30
|
-
"\terror message that identifies the allowable range.",
|
31
|
-
' --stack # | -s #'.green,
|
32
|
-
"\t# specifies the number of stackings. The specified value cannot",
|
33
|
-
"\texceed the number of columns in the design being used. If this",
|
34
|
-
"\toption is omitted then only the base design is generated.",
|
35
|
-
' --excel-style-input | -e'.green,
|
36
|
-
"\tSpecify factor ranges similarly to the NOLH spreadsheet, i.e.,",
|
37
|
-
"\tthe first line is the set of minimum range values for all factors,",
|
38
|
-
"\tand the second line is maximum range values. Without this option,",
|
39
|
-
"\tthe default input format is one line per factor, comprised of the",
|
40
|
-
"\tmin and max separated by commas or whitespace.",
|
41
|
-
' file_name'.green,
|
42
|
-
"\tThe name of a file containing the factor specifications. If no",
|
43
|
-
"\tfilename is given, the user can enter the values interactively in",
|
44
|
-
"\tthe desired form or use file redirection with '<'.", '',
|
45
|
-
'Options may be given in any order, but must come before the file name',
|
46
|
-
'if one is provided.'
|
47
|
-
]
|
48
|
-
|
49
|
-
# Scaler objects will rescale a FDE design from standard units
|
50
|
-
# to a range specified by min and max
|
51
|
-
class Scaler
|
52
|
-
def initialize(min = -1, max = 1)
|
53
|
-
@mid = 0.5 * (max + min)
|
54
|
-
@amplitude = 0.5 * (max - min)
|
55
|
-
end
|
56
|
-
|
57
|
-
def scale(value)
|
58
|
-
@mid + @amplitude * value
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def make_design(number_of_factors, design_num = -1)
|
63
|
-
design = Array.new(number_of_factors)
|
64
|
-
ds = FDE::DESIGN_SETS[number_of_factors]
|
65
|
-
freqs = ds.freqs[design_num].map { |f| Rational(f, ds.nyq) }
|
66
|
-
design.each_index do |column|
|
67
|
-
omega = freqs[column]
|
68
|
-
design[column] = Array.new(ds.nyq) do |i|
|
69
|
-
Math.sin(((i * omega) % 1) * FDE::TWO_PI)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
design.transpose
|
73
|
-
end
|
74
|
-
|
75
|
-
excel_style_inputs = false
|
76
|
-
csv_out = false
|
77
|
-
design_num = -1
|
78
|
-
num_stackings = 1
|
79
|
-
n = nil
|
80
|
-
while ARGV[0] && (ARGV[0][0] == '-' || ARGV[0][0] == 45 || ARGV[0][0] == '?')
|
81
|
-
current_value = ARGV.shift
|
82
|
-
case current_value
|
83
|
-
when '--csv', '-c'
|
84
|
-
csv_out = true
|
85
|
-
when '--design', '-d'
|
86
|
-
design_num = ARGV.shift.to_i - 1
|
87
|
-
when '--num_factors', '-k'
|
88
|
-
n = ARGV.shift.to_i
|
89
|
-
when '--stack', '-s'
|
90
|
-
num_stackings = ARGV.shift.to_i
|
91
|
-
when '--excel-style-input', '-e'
|
92
|
-
excel_style_inputs = true
|
93
|
-
when '--help', '-h', '-help', '-?', '?'
|
94
|
-
ErrorHandling.clean_abort help_msg
|
95
|
-
else
|
96
|
-
ErrorHandling.message ['Unknown argument: '.red + current_value.yellow]
|
97
|
-
ErrorHandling.clean_abort help_msg
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
if n
|
102
|
-
factor = Array.new(n) { Scaler.new }
|
103
|
-
else
|
104
|
-
begin
|
105
|
-
if excel_style_inputs
|
106
|
-
if ARGF.filename == '-'
|
107
|
-
STDERR.puts 'Enter one line of min values, and one of max values.'.green
|
108
|
-
end
|
109
|
-
min_values = ARGF.gets.strip.split(/\s*[,;:]\s*|\s+/).map(&:to_f)
|
110
|
-
max_values = ARGF.gets.strip.split(/\s*[,;:]\s*|\s+/).map(&:to_f)
|
111
|
-
else
|
112
|
-
if ARGF.filename == '-'
|
113
|
-
STDERR.puts 'To terminate input enter '.green + 'ctrl-d'.cyan +
|
114
|
-
' (Mac/Unix/Linux)'.green + ' or '.green + 'ctrl-z'.cyan +
|
115
|
-
' (Windows).'.green
|
116
|
-
STDERR.puts 'Enter ranges for each factor on a separate line.'.green
|
117
|
-
STDERR.puts "\nMIN\tMAX".cyan
|
118
|
-
end
|
119
|
-
min_values = []
|
120
|
-
max_values = []
|
121
|
-
while line = ARGF.gets
|
122
|
-
values = line.strip.split(/\s*[,;:]\s*|\s+/).map(&:to_f)
|
123
|
-
min_values << values.shift
|
124
|
-
max_values << values.shift
|
125
|
-
end
|
126
|
-
end
|
127
|
-
rescue StandardError => e
|
128
|
-
ErrorHandling.message [e.message.red]
|
129
|
-
ErrorHandling.clean_abort help_msg
|
130
|
-
end
|
131
|
-
|
132
|
-
n = min_values.size
|
133
|
-
if max_values.size != n
|
134
|
-
ErrorHandling.message ['Unequal counts for min, max'.red]
|
135
|
-
ErrorHandling.clean_abort help_msg
|
136
|
-
end
|
137
|
-
|
138
|
-
factor = Array.new(n) do |i|
|
139
|
-
Scaler.new(min_values[i], max_values[i])
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
if design_num >= FDE::DESIGN_SETS[n].freqs.length
|
144
|
-
ErrorHandling.clean_abort [
|
145
|
-
"Design number cannot exceed #{FDE::DESIGN_SETS[n].freqs.length} for #{n} factors".red
|
146
|
-
]
|
147
|
-
end
|
148
|
-
|
149
|
-
design = make_design(n, design_num)
|
150
|
-
|
151
|
-
num_columns = design[0].length
|
152
|
-
if num_stackings > num_columns
|
153
|
-
ErrorHandling.clean_abort [
|
154
|
-
'Requested stacking exceeds number of columns in FDE '.red +
|
155
|
-
"(#{num_columns})".red
|
156
|
-
]
|
157
|
-
end
|
158
|
-
|
159
|
-
num_stackings.times do |_stack_num|
|
160
|
-
design.each_with_index do |dp, i|
|
161
|
-
scaled_dp = dp.slice(0, n).map.with_index { |x, k| factor[k].scale(x) }
|
162
|
-
if csv_out
|
163
|
-
puts scaled_dp.join ','
|
164
|
-
else
|
165
|
-
puts scaled_dp.join "\t"
|
166
|
-
end
|
167
|
-
design[i] = dp.rotate
|
168
|
-
end
|
169
|
-
end
|
data/exe/scaled_rf_cubed.rb
DELETED
@@ -1,173 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -w
|
2
|
-
|
3
|
-
require 'colorize'
|
4
|
-
String.disable_colorization false
|
5
|
-
|
6
|
-
require_relative '../lib/datafarming/error_handling'
|
7
|
-
require_relative '../lib/datafarming/factorial_generator'
|
8
|
-
|
9
|
-
def print_descriptor
|
10
|
-
description = [
|
11
|
-
"\nCreate a Resolution V fractional factorial design, either in standard +/-1",
|
12
|
-
'notation or scaled as per user-provided input. The design can optionally ',
|
13
|
-
'be supplemented with CCD center and star points. Output is written to',
|
14
|
-
'stdout'.blue + ' with formatting controlled by command-line options.'
|
15
|
-
]
|
16
|
-
STDERR.puts description
|
17
|
-
end
|
18
|
-
|
19
|
-
def print_directions # :nodoc:
|
20
|
-
prog = $PROGRAM_NAME.split(/\//)[-1]
|
21
|
-
help_msg = [
|
22
|
-
'', 'Syntax:', '',
|
23
|
-
" ruby #{prog} [Options] #factors | low/high-settings".yellow, '',
|
24
|
-
"The vertical bar '|' indicates valid alternatives.", '',
|
25
|
-
'Command-line args must specify either:',
|
26
|
-
' - the number of factors for the design; or',
|
27
|
-
' - low and hi values for all factors.', '',
|
28
|
-
"\nOptions:",
|
29
|
-
' --help | -h | -? | ?'.green,
|
30
|
-
"\tProduce this help message.",
|
31
|
-
' --design-only | -d'.green,
|
32
|
-
"\tprint the design without labeling",
|
33
|
-
' --csv | -c'.green,
|
34
|
-
"\tprint the design as comma separated",
|
35
|
-
' --center | -a'.green,
|
36
|
-
"\tadd global center pt to check linearity",
|
37
|
-
' --star | -s'.green,
|
38
|
-
"\taugment with Central Composite Design pts (includes --center)",
|
39
|
-
' --rotatable | -r'.green,
|
40
|
-
"\tscale a CCD design to be rotatable (includes --star)",
|
41
|
-
''
|
42
|
-
]
|
43
|
-
STDERR.puts help_msg
|
44
|
-
end
|
45
|
-
|
46
|
-
(print_descriptor && print_directions && exit) if ARGV.empty?
|
47
|
-
begin
|
48
|
-
labels = true
|
49
|
-
csv = false
|
50
|
-
scaled = false
|
51
|
-
center = false
|
52
|
-
star = false
|
53
|
-
rotatable = false
|
54
|
-
fmt_size = '5'
|
55
|
-
fmt_type = 'd'
|
56
|
-
|
57
|
-
while ARGV[0] =~ /^(-\D|\?)/
|
58
|
-
arg = ARGV.shift
|
59
|
-
case arg
|
60
|
-
when '-c', '--csv'
|
61
|
-
csv = true
|
62
|
-
when '-d', '--design-only'
|
63
|
-
labels = false
|
64
|
-
when '-a', '--center'
|
65
|
-
center = true
|
66
|
-
when '-s', '--star'
|
67
|
-
star = true
|
68
|
-
center = true
|
69
|
-
when '-r', '--rotatable'
|
70
|
-
rotatable = true
|
71
|
-
star = true
|
72
|
-
center = true
|
73
|
-
fmt_size = '11.8'
|
74
|
-
fmt_type = 'f'
|
75
|
-
when '-h', '--help', '-?', '?'
|
76
|
-
print_descriptor
|
77
|
-
print_directions
|
78
|
-
exit
|
79
|
-
else
|
80
|
-
raise "Unknown option #{arg}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
if ARGV.empty?
|
85
|
-
raise 'Must specify a design size'
|
86
|
-
elsif ARGV.length == 1
|
87
|
-
n = ARGV.shift.to_i
|
88
|
-
elsif (ARGV.length & 1).nonzero? # Odd number of args remaining!
|
89
|
-
raise 'Number of levels is odd: low/hi values must occur in pairs'
|
90
|
-
else
|
91
|
-
n = ARGV.length / 2
|
92
|
-
scaled = true
|
93
|
-
unless rotatable
|
94
|
-
fmt_type = 's'
|
95
|
-
fmt_size = [ARGV.map(&:length).max + 1, fmt_size.to_i].max
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
my_design = make_design n
|
100
|
-
if rotatable && star
|
101
|
-
inverse_len = 1.0 / Math.sqrt(n)
|
102
|
-
my_design.each_with_index do |row, i|
|
103
|
-
my_design[i] = row.map { |elt| elt * inverse_len }
|
104
|
-
end
|
105
|
-
end
|
106
|
-
my_design += [Array.new(n, 0)] if center
|
107
|
-
|
108
|
-
if star
|
109
|
-
star_design = Array.new(2 * n)
|
110
|
-
star_design.each_index { |row| star_design[row] = Array.new(n, 0) }
|
111
|
-
n.times do |col|
|
112
|
-
row = 2 * col
|
113
|
-
star_design[row][col] = -1
|
114
|
-
star_design[row + 1][col] = 1
|
115
|
-
end
|
116
|
-
my_design += star_design
|
117
|
-
end
|
118
|
-
|
119
|
-
if scaled
|
120
|
-
temp = my_design.transpose
|
121
|
-
temp.each_with_index do |factor, idx|
|
122
|
-
factor.map! do |value|
|
123
|
-
case value
|
124
|
-
when -1
|
125
|
-
ARGV[2 * idx + 1]
|
126
|
-
when 1
|
127
|
-
ARGV[2 * idx]
|
128
|
-
when 0
|
129
|
-
begin
|
130
|
-
0.5 * (Float(ARGV[2 * idx + 1]) + Float(ARGV[2 * idx]))
|
131
|
-
rescue
|
132
|
-
raise 'All factors must be numeric for augmented designs.'
|
133
|
-
end
|
134
|
-
else
|
135
|
-
begin
|
136
|
-
lo = Float(ARGV[2 * idx])
|
137
|
-
hi = Float(ARGV[2 * idx + 1])
|
138
|
-
range = hi - lo
|
139
|
-
0.5 * (hi + lo + value * range)
|
140
|
-
rescue
|
141
|
-
raise 'All factors must be numeric for augmented designs.'
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
my_design = temp.transpose
|
147
|
-
end
|
148
|
-
|
149
|
-
if labels
|
150
|
-
if csv
|
151
|
-
print ' DP#'
|
152
|
-
n.times { |i| print ",X#{i + 1}" }
|
153
|
-
else
|
154
|
-
print ' DP#'
|
155
|
-
n.times { |i| printf " %#{fmt_size}s", "X#{i + 1}" }
|
156
|
-
end
|
157
|
-
puts
|
158
|
-
end
|
159
|
-
|
160
|
-
my_design.each_with_index do |design_point, row_number|
|
161
|
-
if csv
|
162
|
-
printf('%d,', row_number + 1) if labels
|
163
|
-
puts design_point.join(',')
|
164
|
-
else
|
165
|
-
printf('%5d', row_number + 1) if labels
|
166
|
-
design_point.each { |value| printf " %#{fmt_size}#{fmt_type}", value }
|
167
|
-
puts
|
168
|
-
end
|
169
|
-
end
|
170
|
-
rescue StandardError => e
|
171
|
-
STDERR.print "\n", e.message, "\n"
|
172
|
-
print_directions
|
173
|
-
end
|
data/exe/stack_nolhs.rb
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby -w
|
2
|
-
|
3
|
-
require 'colorize'
|
4
|
-
String.disable_colorization false
|
5
|
-
|
6
|
-
require 'datafarming/error_handling'
|
7
|
-
require 'datafarming/nolh_designs'
|
8
|
-
|
9
|
-
help_msg = [
|
10
|
-
'Generate scaled Latin hypercube designs with shifting and stacking. ',
|
11
|
-
'Results are a white-space delimited NOLH design written to ' +
|
12
|
-
'stdout'.light_blue + '.', '',
|
13
|
-
'Syntax:',
|
14
|
-
"\n\t#{$PROGRAM_NAME.split(%r{/|\\})[-1]} [--help]".yellow +
|
15
|
-
" [--stack #] [--levels #] [-e] [file_name]\n".yellow,
|
16
|
-
"Arguments in square brackets are optional. A vertical bar '|'",
|
17
|
-
'indicates valid alternatives for invoking the option. Prefix',
|
18
|
-
'the command with "' + 'ruby'.yellow +
|
19
|
-
'" if it is not on your PATH.', '',
|
20
|
-
' --help | -h | -? | ?'.green,
|
21
|
-
"\tProduce this help message. Supersedes any other choices.",
|
22
|
-
' --stack # | -s #'.green,
|
23
|
-
"\t# specifies the number of stackings. A value of 1 means print the",
|
24
|
-
"\tbase design. If this option is not specified the number of stackings",
|
25
|
-
"\tdefaults to the number of columns in the design. The specified value",
|
26
|
-
"\tcannot exceed the number of columns in the design being used.",
|
27
|
-
' --levels # | -l #'.green,
|
28
|
-
"\t# specifies the desired number of levels in the NOLH (17, 33, 65, 129,",
|
29
|
-
"\t257, or 512). Defaults to the smallest design which can accommodate the",
|
30
|
-
"\tnumber of factors if this option is not specified.",
|
31
|
-
' --excel-style-input | -e'.green,
|
32
|
-
"\tSpecify factor ranges and decimals as in the NOLH spreadsheet, i.e.,",
|
33
|
-
"\tthe first line is the set of minimum range values for each factor;",
|
34
|
-
"\tthe second line is maximum range values; and the third is the number",
|
35
|
-
"\tof decimal places to use for the range scaling. Without this option,",
|
36
|
-
"\tthe default input format is one line per factor, comprised of the min,",
|
37
|
-
"\tmax, and number of decimal places separated by commas or whitespace.",
|
38
|
-
' file_name'.green,
|
39
|
-
"\tThe name of a file containing the factor specifications. If no",
|
40
|
-
"\tfilename is given, the user can enter the values interactively in",
|
41
|
-
"\tthe desired form or use file redirection with '<'.", '',
|
42
|
-
'Options may be given in any order, but must come before the file name',
|
43
|
-
'if one is provided.'
|
44
|
-
]
|
45
|
-
|
46
|
-
# Scaler objects will rescale a Latin Hypercube design from standard units
|
47
|
-
# to a range as specified by min, max, and num_decimals
|
48
|
-
class Scaler
|
49
|
-
def initialize(min, max, num_decimals, lh_max = 17)
|
50
|
-
@min = min
|
51
|
-
@range = (max - min) / (lh_max - 1).to_r
|
52
|
-
@scale_factor = 10.to_r**num_decimals
|
53
|
-
end
|
54
|
-
|
55
|
-
def scale(value)
|
56
|
-
new_value = @min + @range * (value.to_r - 1.to_r)
|
57
|
-
if @scale_factor == 1
|
58
|
-
new_value.round
|
59
|
-
else
|
60
|
-
((@scale_factor * new_value).round / @scale_factor).to_f
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
excel_style_inputs = false
|
66
|
-
while ARGV[0] && (ARGV[0][0] == '-' || ARGV[0][0] == 45 || ARGV[0][0] == '?')
|
67
|
-
current_value = ARGV.shift
|
68
|
-
case current_value
|
69
|
-
when '--stack', '-s'
|
70
|
-
num_stackings = ARGV.shift.to_i
|
71
|
-
when '--levels', '-l'
|
72
|
-
lh_levels = ARGV.shift.to_i
|
73
|
-
unless NOLH::DESIGN_TABLE.keys.include?(lh_levels)
|
74
|
-
ErrorHandling.clean_abort [
|
75
|
-
"Invalid number of levels for Latin hypercube: #{lh_levels}".red,
|
76
|
-
'Use 17, 33, 65, 129, 257, or 512.'.yellow
|
77
|
-
]
|
78
|
-
end
|
79
|
-
when '--excel-style-input', '-e'
|
80
|
-
excel_style_inputs = true
|
81
|
-
when '--help', '-h', '-help', '-?', '?'
|
82
|
-
ErrorHandling.clean_abort help_msg
|
83
|
-
else
|
84
|
-
ErrorHandling.message ['Unknown argument: '.red + current_value.yellow]
|
85
|
-
ErrorHandling.clean_abort help_msg
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
begin
|
90
|
-
if excel_style_inputs
|
91
|
-
if ARGV.empty?
|
92
|
-
STDERR.puts 'Enter one line of min values, one of max values,'.green +
|
93
|
-
' and one of #decimals.'.green
|
94
|
-
end
|
95
|
-
min_values = ARGF.gets.strip.split(/\s*[,;:]\s*|\s+/).map(&:to_f)
|
96
|
-
max_values = ARGF.gets.strip.split(/\s*[,;:]\s*|\s+/).map(&:to_f)
|
97
|
-
decimals = ARGF.gets.strip.split(/\s*[,;:]\s*|\s+/).map(&:to_i)
|
98
|
-
else
|
99
|
-
if ARGV.empty?
|
100
|
-
STDERR.puts 'To terminate input enter '.green + 'ctrl-d'.cyan +
|
101
|
-
' (Mac/Unix/Linux)'.green + ' or '.green + 'ctrl-z'.cyan +
|
102
|
-
' (Windows).'.green
|
103
|
-
STDERR.puts 'Enter ranges for each factor on a separate line.'.green
|
104
|
-
STDERR.puts "\nMIN\tMAX\t#DIGITS".cyan
|
105
|
-
end
|
106
|
-
min_values = []
|
107
|
-
max_values = []
|
108
|
-
decimals = []
|
109
|
-
while line = ARGF.gets
|
110
|
-
values = line.strip.split(/\s*[,;:]\s*|\s+/)
|
111
|
-
min_values << values.shift.to_f
|
112
|
-
max_values << values.shift.to_f
|
113
|
-
decimals << values.shift.to_i
|
114
|
-
end
|
115
|
-
end
|
116
|
-
rescue StandardError => e
|
117
|
-
ErrorHandling.message [e.message.red]
|
118
|
-
ErrorHandling.clean_abort help_msg
|
119
|
-
end
|
120
|
-
|
121
|
-
n = min_values.size
|
122
|
-
if max_values.size != n || decimals.size != n
|
123
|
-
ErrorHandling.message ['Unequal counts for min, max, and decimals'.red]
|
124
|
-
ErrorHandling.clean_abort help_msg
|
125
|
-
end
|
126
|
-
minimal_size = case min_values.size
|
127
|
-
when 1..7
|
128
|
-
17
|
129
|
-
when 8..11
|
130
|
-
33
|
131
|
-
when 12..16
|
132
|
-
65
|
133
|
-
when 17..22
|
134
|
-
129
|
135
|
-
when 23..29
|
136
|
-
257
|
137
|
-
when 30..100
|
138
|
-
512
|
139
|
-
else
|
140
|
-
ErrorHandling.message ['invalid number of factors'.red]
|
141
|
-
ErrorHandling.clean_abort help_msg
|
142
|
-
end
|
143
|
-
|
144
|
-
lh_levels ||= minimal_size
|
145
|
-
|
146
|
-
if lh_levels < minimal_size
|
147
|
-
ErrorHandling.clean_abort [
|
148
|
-
"Latin hypercube with #{lh_levels} levels is too small for #{n} factors.".red
|
149
|
-
]
|
150
|
-
end
|
151
|
-
|
152
|
-
factor = Array.new(n) do |i|
|
153
|
-
Scaler.new(min_values[i], max_values[i], decimals[i], lh_levels)
|
154
|
-
end
|
155
|
-
|
156
|
-
design = NOLH::DESIGN_TABLE[lh_levels]
|
157
|
-
|
158
|
-
num_columns = design[0].length
|
159
|
-
num_stackings ||= num_columns
|
160
|
-
if num_stackings > num_columns
|
161
|
-
ErrorHandling.clean_abort [
|
162
|
-
'Requested stacking exceeds number of columns in latin hypercube '.red +
|
163
|
-
"(#{num_columns})".red
|
164
|
-
]
|
165
|
-
end
|
166
|
-
|
167
|
-
mid_range = lh_levels / 2
|
168
|
-
num_stackings.times do |stack_num|
|
169
|
-
design.each_with_index do |dp, i|
|
170
|
-
scaled_dp = dp.slice(0, n).map.with_index { |x, k| factor[k].scale(x) }
|
171
|
-
puts scaled_dp.join "\t" unless stack_num > 0 && i == mid_range && lh_levels < 512
|
172
|
-
design[i] = dp.rotate
|
173
|
-
end
|
174
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'fwt'
|
2
|
-
|
3
|
-
# Generate a Resolution V Fractional Factorial design for the specified
|
4
|
-
# number of factors. The design is guaranteed to yield unconfounded
|
5
|
-
# interactions for all pairs of factors. The design uses standardized
|
6
|
-
# notation, i.e., -1 represents a low setting and 1 represents a high
|
7
|
-
# setting for each factor.
|
8
|
-
#
|
9
|
-
# *Arguments*::
|
10
|
-
# - +number_of_factors+ -> the number of factors in your design. Limit is 120.
|
11
|
-
# *Returns*::
|
12
|
-
# - a two-dimensional array specifying the design, where each column
|
13
|
-
# corresponds to a factor and each row is a design point.
|
14
|
-
#
|
15
|
-
# Author:: Paul J Sanchez (mailto:pjs@alum.mit.edu)
|
16
|
-
# Copyright:: Copyright (c) 2020 Paul J Sanchez
|
17
|
-
# License:: MIT
|
18
|
-
#
|
19
|
-
INDEX = [1, 2, 4, 8, 15, 16, 32, 51, 64, 85, 106, 128, 150, 171,
|
20
|
-
219, 237, 247, 256, 279, 297, 455, 512, 537, 557, 594, 643, 803,
|
21
|
-
863, 998, 1024, 1051, 1070, 1112, 1169, 1333, 1345, 1620, 1866,
|
22
|
-
2048, 2076, 2085, 2185, 2372, 2456, 2618, 2800, 2873, 3127, 3284,
|
23
|
-
3483, 3557, 3763, 4096, 4125, 4135, 4174, 4435, 4459, 4469, 4497,
|
24
|
-
4752, 5255, 5732, 5804, 5915, 6100, 6369, 6907, 7069, 8192, 8263,
|
25
|
-
8351, 8422, 8458, 8571, 8750, 8858, 9124, 9314, 9500, 10_026,
|
26
|
-
10_455, 10_556, 11_778, 11_885, 11_984, 13_548, 14_007, 14_514,
|
27
|
-
14_965, 15_125, 15_554, 16_384, 16_457, 16_517, 16_609, 16_771,
|
28
|
-
16_853, 17_022, 17_453, 17_891, 18_073, 18_562, 18_980, 19_030,
|
29
|
-
19_932, 20_075, 20_745, 21_544, 22_633, 23_200, 24_167, 25_700,
|
30
|
-
26_360, 26_591, 26_776, 28_443, 28_905, 29_577, 32_705]
|
31
|
-
POWER = [1, 2, 4, 8, 16, 16, 32, 64, 64, 128, 128, 128, 256, 256,
|
32
|
-
256, 256, 256, 256, 512, 512, 512, 512, 1024, 1024, 1024, 1024,
|
33
|
-
1024, 1024, 1024, 1024, 2048, 2048, 2048, 2048, 2048, 2048, 2048,
|
34
|
-
2048, 2048, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
|
35
|
-
4096, 4096, 4096, 4096, 4096, 8192, 8192, 8192, 8192, 8192, 8192,
|
36
|
-
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
|
37
|
-
16_384, 16_384, 16_384, 16_384, 16_384, 16_384, 16_384, 16_384,
|
38
|
-
16_384, 16_384, 16_384, 16_384, 16_384, 16_384, 16_384, 16_384,
|
39
|
-
16_384, 16_384, 16_384, 16_384, 16_384, 16_384, 16_384, 32_768,
|
40
|
-
32_768, 32_768, 32_768, 32_768, 32_768, 32_768, 32_768, 32_768,
|
41
|
-
32_768, 32_768, 32_768, 32_768, 32_768, 32_768, 32_768, 32_768,
|
42
|
-
32_768, 32_768, 32_768, 32_768, 32_768, 32_768, 32_768, 32_768,
|
43
|
-
32_768, 32_768, 32_768]
|
44
|
-
|
45
|
-
def make_design(number_of_factors)
|
46
|
-
Array.new(number_of_factors) do |i|
|
47
|
-
Array.new(POWER[number_of_factors], 0).tap { |a| a[INDEX[i]] = 1 }.hadamard
|
48
|
-
end.transpose
|
49
|
-
end
|