Class: Renjin

Inherits:
Object
  • Object
show all
Defined in:
lib/JRubyR/list.rb,
lib/JRubyR/rbsexp.rb,
lib/JRubyR/rbsexp.rb,
lib/JRubyR/indexed.rb,
lib/JRubyR/callback.rb,
lib/JRubyR/function.rb,
lib/JRubyR/dataframe.rb,
lib/JRubyR/attributes.rb,
lib/JRubyR/environment.rb,
lib/JRubyR/logical_value.rb,
lib/JRubyR/vector.rb,
lib/JRubyR/vector.rb,
lib/JRubyR/renjin.rb

Overview

Defined Under Namespace

Modules: Index, RBSexp Classes: Attributes, Callback, Closure, ComplexVector, DataFrame, Environment, Function, List, Logical, Primitive, RubySexp, Vector, Writer

Constant Summary collapse

ParseError =

Parse error

Class.new(Exception)

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeRenjin


R is invoked within a Ruby script (or the interactive “irb” prompt denoted >>) using:

>> require "scicom"

The previous statement reads the definition of the RinRuby class into the current Ruby interpreter and creates an instance of the RinRuby class named R. There is a second method for starting an instance of R which allows the user to use any name for the instance, in this case myr:

>> require "scicom"
>> myr = RinRuby.new
>> myr.eval "rnorm(1)"

Any number of independent instances of R can be created in this way.




119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/JRubyR/renjin.rb', line 119

def initialize

  @session = SessionBuilder.new
             .bind(PackageLoader.java_class, AetherPackageLoader.new)
             .withDefaultPackages
             .build
  @engine = RenjinScriptEngineFactory.new.getScriptEngine(@session);

  @default_std_out = @session.getStdOut()
  @default_std_err = @session.connectionTable.getStderr()
  
  # factory = Java::JavaxScript.ScriptEngineManager.new()
  # @engine = factory.getEngineByName("Renjin")
  raise "Renjin not found. Please check your CLASSPATH: #{$CLASSPATH}" if @engine == nil
  super

end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object


When calling a R.<id>, we will call method_missing. This can be an assignment: R.name = <value>, can be a variable access: puts R.name, a call to a function without arguments R.<function> or a function with arguments. If it is a call to a function with arguments, then all arguments need to be parsed (and converted to R) and then the function is called.




236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/JRubyR/renjin.rb', line 236

def method_missing(symbol, *args)

  name = symbol.id2name
  name.gsub!(/__/,".")
  # Method 'rclass' is a substitute for R method 'class'.  Needed, as 'class' is also
  # a Ruby method on an object
  name.gsub!("rclass", "class")

  if name =~ /(.*)=$/
    ret = assign($1,args[0])
  else
    if (args.length == 0)
      # is_var = false
      # Try to see if name is a variable or a method.
      ret = (eval("\"#{name}\" %in% ls()").gt)? eval("#{name}") : eval("#{name}()")
    else
      params = parse(*args)
      # p "#{name}(#{params})"
      ret = eval("#{name}(#{params})")
    end
  end

  ret

end

Class Attribute Details

.stackObject

Returns the value of attribute stack.



90
91
92
# File 'lib/JRubyR/renjin.rb', line 90

def stack
  @stack
end

Instance Attribute Details

#engineObject (readonly)





97
98
99
# File 'lib/JRubyR/renjin.rb', line 97

def engine
  @engine
end

Instance Method Details

#alternate_errObject





177
178
179
# File 'lib/JRubyR/renjin.rb', line 177

def alternate_err
  @alternate_err.string
end

#alternate_outObject





155
156
157
# File 'lib/JRubyR/renjin.rb', line 155

def alternate_out
  @alternate_out.string
end

#assign(name, value) ⇒ Object


Data is copied from Ruby to R using the assign method or a short-hand equivalent. For example:

>> names = ["Lisa","Teasha","Aaron","Thomas"]
>> R.assign "people", names
>> R.eval "sort(people)"

produces the following :

[1] "Aaron"     "Lisa"     "Teasha" "Thomas"

The short-hand equivalent to the assign method is simply:

>> R.people = names

Some care is needed when using the short-hand of the assign method since the label (i.e., people in this case) must be a valid method name in Ruby. For example, R.copy.of.names = names will not work, but R.copy_of_names = names is permissible.

The assign method supports Ruby variables of type Fixnum (i.e., integer), Bignum (i.e., integer), Float (i.e., double), String, and arrays of one of those three fundamental types. Note that Fixnum or Bignum values that exceed the capacity of R’s integers are silently converted to doubles. Data in other formats must be coerced when copying to R.

Parameters that can be passed to the assign method:

  • name: The name of the variable desired in R.

  • value: The value the R variable should have.

The assign method is an alternative to the simplified method, with some additional flexibility. When using the simplified method, the parameters of name and value are automatically used, in other words:

>> R.test = 144

is the same as:

>> R.assign("test",144)

Of course it would be confusing to use the shorthand notation to assign a variable named eval, echo, or any other already defined function. RinRuby would assume you were calling the function, rather than trying to assign a variable.

When assigning an array containing differing types of variables, RinRuby will follow R’s conversion conventions. An array that contains any Strings will result in a character vector in R. If the array does not contain any Strings, but it does contain a Float or a large integer (in absolute value), then the result will be a numeric vector of Doubles in R. If there are only integers that are suffciently small (in absolute value), then the result will be a numeric vector of integers in R.




415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/JRubyR/renjin.rb', line 415

def assign(name, value)

  original_value = value

  if ((value.is_a? MDArray)) # || (value.is_a? RubySexp))
    if (value.sexp != nil)
      # MDArray already represented in R
      value = value.sexp
    else
      value = build_vector(value)
    end
  elsif (value.is_a? RubySexp)
    # puts "I'm a Sexp: #{value} and value.sexp is #{value.sexp}"
    value = value.sexp
  elsif (value == nil)
    value = NULL
  end

  @engine.put(name, value)
  original_value
  
end

#convert(param) ⇒ Object


Converts the given parameter into an R object. If the parameter is already an R object, then leave it unchanged.




358
359
360
# File 'lib/JRubyR/renjin.rb', line 358

def convert(param)
  R.eval(parse(param))
end

#d(value) ⇒ Object



527
528
529
# File 'lib/JRubyR/renjin.rb', line 527

def d(value)
  eval("#{value}")
end

#direct_eval(expression) ⇒ Object


Evaluates an expression but does not wrap the return in a RubySexp. Needed for intermediate evaluation done by internal methods. In principle, should not be called by users.




289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/JRubyR/renjin.rb', line 289

def direct_eval(expression)
  begin
    ret = @engine.eval(expression)
  rescue Java::OrgRenjinEval::EvalException => e 
    p e.message
  ensure
=begin
    Renjin.stack.each do |sexp|
      sexp.destroy
    end
=end
  end

  ret

end

#eval(expression) ⇒ Object





266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/JRubyR/renjin.rb', line 266

def eval(expression)
  begin
    ret = Renjin::RubySexp.build(@engine.eval(expression))
  rescue Java::OrgRenjinEval::EvalException => e 
    p e.message
  rescue Java::OrgRenjinParser::ParseException => e
    p e.message
  ensure
    Renjin.stack.each do |sexp|
      sexp.destroy
    end
  end

  ret

end

#fassign(sexp, function, value) ⇒ Object


function is either a function name alone represented by a ruby symbol or a hash with the function name and its arguments or indexes Ex:

fassign(sexp, :rowname, "x1")
fassign(sexp, {f: :rowname, index: [[1]]}, "x1")
fassign(sexp, {f: :somefunc, params: "(2, 3, 4)"}, "x1")



455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# File 'lib/JRubyR/renjin.rb', line 455

def fassign(sexp, function, value)

  if (function.is_a? Hash)
    index = function[:index]
    params = function[:params]
    function = function[:f]
    if (index)
      eval("#{function.to_s}(#{sexp.r})#{index} = #{value.r}")
    else
    end
  else
    eval("#{function.to_s}(#{sexp.r}) = #{value.r}")
  end

  sexp

end

#finite?(x) ⇒ Boolean



Returns:

  • (Boolean)


224
225
226
# File 'lib/JRubyR/renjin.rb', line 224

def finite?(x)
  R.is__finite(x)
end

#i(value) ⇒ Object



523
524
525
# File 'lib/JRubyR/renjin.rb', line 523

def i(value)
  eval("#{value}L")
end

#install__package(name) ⇒ Object





477
478
479
480
481
482
# File 'lib/JRubyR/renjin.rb', line 477

def install__package(name)

  pm = PackageManager.new
  pm.load_package(name)

end

#lettersObject



511
512
513
# File 'lib/JRubyR/renjin.rb', line 511

def letters
  eval("letters")
end

#LETTERSObject



507
508
509
# File 'lib/JRubyR/renjin.rb', line 507

def LETTERS
  eval("LETTERS")
end

#md(value) ⇒ Object


Creates a new Renjin Vector based on an MDArray




535
536
537
# File 'lib/JRubyR/renjin.rb', line 535

def md(value)
  Renjin::Vector.new(build_vector(value))
end

#month__abbObject



515
516
517
# File 'lib/JRubyR/renjin.rb', line 515

def month__abb
  eval("month.abb")
end

#month__nameObject



519
520
521
# File 'lib/JRubyR/renjin.rb', line 519

def month__name
  eval("month.name")
end

#na?(x) ⇒ Boolean


The integer constant used to designate elements or values that are missing in the statistical sense, or literally “Not Available”. For integers (Fixnum) this is represented as the minimum integer from Java Integer.MIN_VALUE


Returns:

  • (Boolean)


216
217
218
# File 'lib/JRubyR/renjin.rb', line 216

def na?(x)
  R.is__na(x)
end

#nan?(x) ⇒ Boolean



Returns:

  • (Boolean)


205
206
207
# File 'lib/JRubyR/renjin.rb', line 205

def nan?(x)
  is__nan(x)
end

#parse(*args) ⇒ Object


Parse an argument and returns a piece of R script needed to build a complete R statement.




311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/JRubyR/renjin.rb', line 311

def parse(*args)

  params = Array.new
  
  args.each do |arg|
    if (arg.is_a? Numeric)
      params << arg
    elsif(arg.is_a? String)
      params << "\"#{arg}\""
    elsif (arg.is_a? Symbol)
      var = eval("#{arg.to_s}")
      params << var.r
    elsif (arg.is_a? TrueClass)
      params << "TRUE"
    elsif (arg.is_a? FalseClass)
      params << "FALSE"
    elsif (arg == nil)
      params << "NULL"
    elsif (arg.is_a? NegRange)
      final_value = (arg.exclude_end?)? (arg.end - 1) : arg.end
      params << "-(#{arg.begin}:#{final_value})"
    elsif (arg.is_a? Range)
      final_value = (arg.exclude_end?)? (arg.end - 1) : arg.end
      params << "(#{arg.begin}:#{final_value})"
    elsif (arg.is_a? Hash)
      arg.each_pair do |key, value|
        params << "#{key.to_s} = #{parse(value)}"
      end
    elsif ((arg.is_a? Renjin::RubySexp) || (arg.is_a? Array) || (arg.is_a? MDArray))
      params << arg.r
    # elsif 
    #  params << arg.inspect
    else
      raise "Unknown parameter type for R: #{arg}"
    end
    
  end

  params.join(",")
    
end

#piObject


R built-in constants




503
504
505
# File 'lib/JRubyR/renjin.rb', line 503

def pi
  eval("pi")
end

#pull(name) ⇒ Object





442
443
444
# File 'lib/JRubyR/renjin.rb', line 442

def pull(name)
  eval(name)
end

#rpack(ruby_class, scope: :external) ⇒ Object


Packs a ruby class inside a RBSexp, so that methods in the Ruby class can be called back from inside an R script




544
545
546
# File 'lib/JRubyR/renjin.rb', line 544

def rpack(ruby_class, scope: :external)
  Renjin::Callback.pack(ruby_class, scope: scope)
end

#set_default_std_errObject





196
197
198
199
# File 'lib/JRubyR/renjin.rb', line 196

def set_default_std_err
  $stderr = STDERR
  @session.setStdErr(@default_std_err)
end

#set_default_std_outObject





185
186
187
188
189
190
# File 'lib/JRubyR/renjin.rb', line 185

def set_default_std_out
  
  $stdout = STDOUT
  @session.setStdOut(@default_std_out)
  
end

#set_std_err(buffer) ⇒ Object





163
164
165
166
167
168
169
170
171
# File 'lib/JRubyR/renjin.rb', line 163

def set_std_err(buffer)

  $stderr = StringIO.new(buffer)
  @alternate_err = Writer.new(buffer)
  print_writer = Java::JavaIo::PrintWriter.new(@alternate_err)
  @session.setStdErr(print_writer)
  self
  
end

#set_std_out(buffer) ⇒ Object





141
142
143
144
145
146
147
148
149
# File 'lib/JRubyR/renjin.rb', line 141

def set_std_out(buffer)

  $stdout = StringIO.new(buffer)
  @alternate_out = Writer.new(buffer)
  print_writer = Java::JavaIo::PrintWriter.new(@alternate_out)
  @session.setStdOut(print_writer)
  self
  
end