Class: Renjin

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

Overview

Defined Under Namespace

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

Constant Summary

ParseError =

Parse error

Class.new(Exception)

Class Attribute Summary (collapse)

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Renjin) initialize


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.




81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/JRubyR/renjin.rb', line 81

def initialize

  @platform = 
    case RUBY_PLATFORM
    when /mswin/ then 'windows'
    when /mingw/ then 'windows'
    when /bccwin/ then 'windows'
    when /cygwin/ then 'windows-cygwin'
    when /java/
      require 'java' #:nodoc:
      if java.lang.System.getProperty("os.name") =~ /[Ww]indows/
        'windows-java'
      else
        'default-java'
      end
    else 'default'
    end

  factory = Java::JavaxScript.ScriptEngineManager.new()
  @engine = factory.getEngineByName("Renjin")
  super

end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(symbol, *args)





136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/JRubyR/renjin.rb', line 136

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 =~ /(.*)=$/
    super if args.length != 1
    ret = assign($1,args[0])
  else
    # super if args.length != 0
    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

+ (Object) stack

Returns the value of attribute stack



52
53
54
# File 'lib/JRubyR/renjin.rb', line 52

def stack
  @stack
end

Instance Attribute Details

- (Object) engine (readonly)





59
60
61
# File 'lib/JRubyR/renjin.rb', line 59

def engine
  @engine
end

Instance Method Details

- (Object) assign(name, value)


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.




344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/JRubyR/renjin.rb', line 344

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 == nil)
    value = NULL
  end

  @engine.put(name, value)
  original_value
  
end

- (Object) build_vector(mdarray)


Builds a Renjin vector from an MDArray. Should be private, but public for testing.




434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'lib/JRubyR/renjin.rb', line 434

def build_vector(mdarray)
  
  shape = mdarray.shape
  # index = mdarray.nc_array.getIndex()
  # index = MDArray.index_factory(shape)
  # representation of shape in R is different from shape in MDArray.  Convert MDArray
  # shape to R shape.
  if (shape.size > 2)
    shape.reverse!
    shape[0], shape[1] = shape[1], shape[0]
  end

  # AttributeMap attributes = AttributeMap.builder().setDim(new IntVector(dim)).build();
  attributes = Java::OrgRenjinSexp::AttributeMap.builder()
    .setDim(Java::OrgRenjinSexp::IntArrayVector.new(*(shape))).build()

  # vector = Java::RbScicom::MDDoubleVector.new(mdarray.nc_array, attributes, index,
  #   index.stride)
  
  case mdarray.type
  when "int"
    vector = Java::RbScicom::MDIntVector.factory(mdarray.nc_array, attributes)
  when "double"
    vector = Java::RbScicom::MDDoubleVector.factory(mdarray.nc_array, attributes)
  when "byte"
    vector = Java::RbScicom::MDLogicalVector.factory(mdarray.nc_array, attributes)
  when "string"
    vector = Java::RbScicom::MDStringVector.factory(mdarray.nc_array, attributes)
  when "boolean"
    raise "Boolean vectors cannot be converted to R vectors.  If you are trying to \
convert to an R Logical object, use a :byte MDArray"
  else
    raise "Cannot convert MDArray #{mdarray.type} to R vector"
  end

end

- (Object) d(value)



192
193
194
# File 'lib/JRubyR/renjin.rb', line 192

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

- (Object) direct_eval(expression)


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.




228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/JRubyR/renjin.rb', line 228

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

- (Object) eval(expression)





205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/JRubyR/renjin.rb', line 205

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

- (Object) fassign(sexp, function, value)


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")



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/JRubyR/renjin.rb', line 381

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

- (Boolean) finite?(x)



Returns:

  • (Boolean)


128
129
130
# File 'lib/JRubyR/renjin.rb', line 128

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

- (Object) i(value)



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

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

- (Object) install__package(name)





403
404
405
406
407
408
# File 'lib/JRubyR/renjin.rb', line 403

def install__package(name)

  pm = PackageManager.new
  pm.load_package(name)

end

- (Object) LETTERS



172
173
174
# File 'lib/JRubyR/renjin.rb', line 172

def LETTERS
  eval("LETTERS")
end

- (Object) letters



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

def letters
  eval("letters")
end

- (Object) library(package)





414
415
416
417
418
419
420
421
422
# File 'lib/JRubyR/renjin.rb', line 414

def library(package)

  Dir.chdir(SciCom.cran_dir)
  filename = SciCom.cran_dir + "/#{package}.jar"

  require filename
  eval("library(#{package})")

end

- (Object) md(value)



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

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

- (Object) month__abb



180
181
182
# File 'lib/JRubyR/renjin.rb', line 180

def month__abb
  eval("month.abb")
end

- (Object) month__name



184
185
186
# File 'lib/JRubyR/renjin.rb', line 184

def month__name
  eval("month.name")
end

- (Boolean) na?(x)


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)


120
121
122
# File 'lib/JRubyR/renjin.rb', line 120

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

- (Boolean) nan?(x)



Returns:

  • (Boolean)


109
110
111
# File 'lib/JRubyR/renjin.rb', line 109

def nan?(x)
  is__nan(x)
end

- (Object) parse(*args)





249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/JRubyR/renjin.rb', line 249

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

- (Object) pi


R built-in constants




168
169
170
# File 'lib/JRubyR/renjin.rb', line 168

def pi
  eval("pi")
end

- (Object) pull(name)





368
369
370
# File 'lib/JRubyR/renjin.rb', line 368

def pull(name)
  eval(name)
end