SHARE
TWEET

Create Reliability Variable

a guest Jul 10th, 2013 97 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #-------------------------------------------------------------------
  2. # OpenSHAPA API v 0.984
  3.  
  4. # Please read the function headers for information on how to use them.
  5.  
  6. # CHANGE LOG
  7. # 0.984 2/16/11 - Fixed a heap error bug in mutex, several bugs with editing
  8. #                 variable arguments.  Added functions for adding variable
  9. #                 arguments, and framework for generic print script.  Several
  10. #                 versions of incremental fixes.
  11. # 0.98 10/10/10 - Added function to get list of columns, fixed up the import
  12. #                 Macshapa function.  It should work for most files now.
  13. # 0.97 8/11/10 -  Added a function to check for valid codes in a variable,
  14. #                 and fixed a bug with check_rel.
  15. # 0.96 8/11/10 -  Added a function to check reliability between two columns
  16. #                 and print either to a file or to the console.
  17. # 0.95 7/22/10 -  Added a function to transfer columns between files and
  18. #                 added headers to functions that didn't have any.
  19. # 0.94 7/22/10 -  Fixed the save_db function so it works with opf files
  20. #                 and will detect if you are saving a csv file.
  21. # 0.93 7/20/10 -  Merged in function to read MacSHAPA Closed database
  22. #                 files into OpenSHAPA.
  23. # 0.92 6/29/10 -  Added function to delete columns
  24. # 0.91 6/25/10 -  Added load functions, fixed some issues with Mutex
  25. # =>              save still has some issues though; working out how to
  26. # =>              access the project variables from Ruby.
  27.  
  28. # Licensing information:
  29. #
  30. # Permission is hereby granted, free of charge, to any person obtaining a copy
  31. # of this software and associated documentation files (the "Software"), to deal
  32. # in the Software without restriction, including without limitation the rights
  33. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  34. # copies of the Software, and to permit persons to whom the Software is
  35. # furnished to do so, subject to the following conditions:
  36. #
  37. # The above copyright notice and this permission notice shall be included in
  38. # all copies or substantial portions of the Software.
  39. #
  40. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  41. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  42. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  43. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  44. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  45. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  46. # THE SOFTWARE.
  47. #-------------------------------------------------------------------
  48.  
  49. require 'java'
  50. require 'csv'
  51. require 'time'
  52. require 'date'
  53. #require 'ftools'
  54.  
  55. import 'org.openshapa.models.db.legacy.Database'
  56. import 'org.openshapa.models.db.legacy.DataColumn'
  57. import 'org.openshapa.models.db.legacy.MacshapaDatabase'
  58. import 'org.openshapa.models.db.legacy.MatrixVocabElement'
  59. import 'org.openshapa.models.db.legacy.Matrix'
  60. import 'org.openshapa.models.db.legacy.FloatDataValue'
  61. import 'org.openshapa.models.db.legacy.IntDataValue'
  62. import 'org.openshapa.models.db.legacy.TextStringDataValue'
  63. import 'org.openshapa.models.db.legacy.QuoteStringDataValue'
  64. import 'org.openshapa.models.db.legacy.UndefinedDataValue'
  65. import 'org.openshapa.models.db.legacy.NominalDataValue'
  66. import 'org.openshapa.models.db.legacy.PredDataValue'
  67. import 'org.openshapa.models.db.legacy.Predicate'
  68. import 'org.openshapa.models.db.legacy.PredicateVocabElement'
  69. import 'org.openshapa.models.db.legacy.FloatFormalArg'
  70. import 'org.openshapa.models.db.legacy.IntFormalArg'
  71. import 'org.openshapa.models.db.legacy.NominalFormalArg'
  72. import 'org.openshapa.models.db.legacy.PredFormalArg'
  73. import 'org.openshapa.models.db.legacy.QuoteStringFormalArg'
  74. import 'org.openshapa.models.db.legacy.UnTypedFormalArg'
  75. import 'org.openshapa.models.db.legacy.DBElement'
  76. import 'org.openshapa.models.db.legacy.TimeStamp'
  77. import 'org.openshapa.models.db.legacy.DataCell'
  78. import 'org.openshapa.models.db.legacy.SystemErrorException'
  79. import 'org.openshapa.models.project.Project'
  80. import 'org.openshapa.controllers.SaveC'
  81. import 'org.openshapa.controllers.OpenC'
  82. import 'org.openshapa.controllers.project.ProjectController'
  83. include_class(['java.lang.Object', 'java.awt.event.ActionListener', 'javax.swing.JFrame','javax.swing.JLabel','javax.swing.JComboBox','javax.swing.JButton','javax.swing.JPanel','javax.swing.JTable','javax.swing.JTextField', 'java.awt.GridBagLayout', 'java.awt.GridBagConstraints'])
  84.  
  85. class Cell
  86.  
  87.    attr_accessor :ordinal, :onset, :offset, :arglist, :argvals
  88.  
  89.  
  90.    #-------------------------------------------------------------------
  91.    # Note: This method is not for general use, it is used only when creating
  92.    #       this variable from the database in the getVariable method.
  93.    #
  94.    # Method name: set_args
  95.    # Function: sets up methods that can be used to reference the arguments in
  96.    #           the cell.
  97.    # Arguments:
  98.    # => argvals (required): Values of the arguments being created
  99.    # => arglist (required): Names of the arguments being created
  100.    #-------------------------------------------------------------------
  101.  
  102.    def set_args(argvals, arglist)
  103.       @arglist = arglist
  104.       @argvals = argvals
  105.       i = 0
  106.       if argvals == ""
  107.          @argvals = Array.new
  108.          arglist.each do |arg|
  109.             @argvals << nil
  110.          end
  111.       end
  112.       arglist.each do |arg|
  113.  
  114.          if @argvals[i].nil?
  115.             @argvals[i] = ""
  116.          end
  117.          #Tricky magic part where we are defining var names on the fly.  Escaped quotes turn everything to strings.
  118.          #Handle this later by allowing numbers to be numbers but keeping strings.
  119.  
  120.          instance_eval "def #{arg}; return argvals[#{i}]; end"
  121.          i += 1
  122.       end
  123.    end
  124.  
  125.  
  126.    def change_arg_name(i, new_name)
  127.       instance_eval "def #{new_name}; return argvals[#{i}]; end"
  128.    end
  129.  
  130.    #-------------------------------------------------------------------
  131.    # Method name: change_arg
  132.    # Function: Changes the value of an argument in a cell.
  133.    # Arguments:
  134.    # => arg (required): Name of the argument to be changed
  135.    # => val (required): Value to change the argument to
  136.    # Returns:
  137.    # => None
  138.    # Usage:
  139.    #       trial = getVariable("trial")
  140.    #       trial.cells[0].change_arg("onset", 1000)
  141.    #       setVariable("trial",trial)
  142.    #-------------------------------------------------------------------
  143.  
  144.    def change_arg(arg, val)
  145.       if arg == "onset"
  146.          @onset = val
  147.       elsif arg == "offset"
  148.          @offset = val
  149.       elsif arg == "ordinal"
  150.          @ordinal = val
  151.       else
  152.          for i in 0..arglist.length-1
  153.             if arglist[i] == arg and not arg.nil?
  154.                argvals[i] = val.to_s
  155.             end
  156.          end
  157.       end
  158.    end
  159.  
  160.    #-------------------------------------------------------------------
  161.    # Method name: print_all
  162.    # Function: Dumps all of the arguments in the cell to a string.
  163.    # Arguments:
  164.    # => p (optional): The seperator used between the arguments.  Defaults to tab (\t)
  165.    # Returns:
  166.    # => A string of the arguments starting with ordinal/onset/offset then argument.
  167.    # Usage:
  168.    #       trial = getVariable("trial")
  169.    #       print trial.cells[0].print_all()
  170.    #-------------------------------------------------------------------
  171.  
  172.    def print_all(*p)
  173.       if p.empty?
  174.          p << "\t"
  175.       end
  176.       print @ordinal.to_s + p[0] + @onset.to_s + p[0] + @offset.to_s + p[0]
  177.       @arglist.each do |arg|
  178.          t = eval "self.#{arg}"
  179.          if t == nil
  180.             v = ""
  181.          else
  182.             v = t
  183.          end
  184.          print v + p[0]
  185.       end
  186.    end
  187. end
  188.  
  189. #-------------------------------------------------------------------
  190. # Class name: Variable
  191. # Function: This is the Ruby container for OpenSHAPA variables.
  192. #-------------------------------------------------------------------
  193.  
  194. class Variable
  195.  
  196.    attr_accessor :name, :type, :cells, :arglist, :old_args
  197.  
  198.    #-------------------------------------------------------------------
  199.    # NOTE: This function is not for general use.
  200.    #
  201.    # Method name: set_cells
  202.    # Function: Creates the cell object in the Variable object.
  203.    # Arguments:
  204.    # => newcells (required): Array of cells coming from the database via getVariable
  205.    # => arglist (required): Array of the names of the arguments from the database
  206.    #-------------------------------------------------------------------
  207.  
  208.    def set_cells(newcells, arglist)
  209.       @cells = Array.new
  210.       @arglist = Array.new
  211.       arglist.each do |arg|
  212.          # Regex to delete any character not a-z,0-9,or _
  213.          if ["0","1","2","3","4","5","6","7","8","9"].include?(arg[1].chr)
  214.             arg = "_" + arg
  215.          end
  216.          @arglist << arg.gsub(/(\W)+/,"").downcase
  217.       end
  218.       if !newcells.nil?
  219.          newcells.each do |cell|
  220.             c = Cell.new
  221.             c.onset = cell[0]
  222.             c.offset = cell[1]
  223.             c.set_args(cell[2],@arglist)
  224.             c.ordinal = cell[3]
  225.             @cells << c
  226.          end
  227.       end
  228.    end
  229.  
  230.    #-------------------------------------------------------------------
  231.    # Method name: make_new_cell
  232.    # Function: Creates a new, blank cell at the end of this variable's cell array
  233.    # Arguments:
  234.    # => None
  235.    # Returns:
  236.    # => Reference to the cell that was just created.  Modify the cell using this reference.
  237.    # Usage:
  238.    #       trial = getVariable("trial")
  239.    #       new_cell = trial.make_new_cell()
  240.    #       new_cell.change_arg("onset", 1000)
  241.    #       setVariable("trial", trial)
  242.    #-------------------------------------------------------------------
  243.    def make_new_cell()
  244.       c = Cell.new
  245.       c.onset = 0
  246.       c.offset = 0
  247.       c.ordinal = 0
  248.       c.set_args("", @arglist)
  249.       @cells << c
  250.       return c
  251.    end
  252.  
  253.    def sort_cells()
  254.       cells.sort! { |a,b| a.onset <=> b.onset }
  255.    end
  256.  
  257.  
  258.    #-------------------------------------------------------------------
  259.    # Method name: change_arg_name
  260.    # Function: Creates a new, blank cell at the end of this variable's cell array
  261.    # Arguments:
  262.    # => old_name: the name of the argument you want to change
  263.    # => new_name: the name you want to change old_name to
  264.    # Returns:
  265.    # => nothing.
  266.    # Usage:
  267.    #       trial = getVariable("trial")
  268.    #
  269.    #-------------------------------------------------------------------
  270.    def change_arg_name(old_name, new_name)
  271.       i = @old_args.index("<"+old_name+">")
  272.       @old_args[i] = "<"+new_name+">"
  273.       if ["0","1","2","3","4","5","6","7","8","9"].include?(old_name[1].chr)
  274.             old_name = "_" + old_name
  275.       end
  276.       old_name = old_name.gsub(/(\W)+/,"").downcase
  277.  
  278.       i = @arglist.index(old_name)
  279.       @arglist[i] = new_name
  280.       for cell in @cells
  281.         cell.change_arg_name(i, new_name)
  282.       end
  283.  
  284.    end
  285. end
  286.  
  287. #-------------------------------------------------------------------
  288. # Method name: getVariable
  289. # Function: getVariable retrieves a variable from the database and puts it into a Ruby object.
  290. # Arguments:
  291. # => name (required): The OpenSHAPA name of the variable being retrieved
  292. # Returns:
  293. # => A Ruby object representation of the variable inside OpenSHAPA.
  294. # Usage:
  295. #       trial = getVariable("trial")
  296. #-------------------------------------------------------------------
  297.  
  298. def getVariable(name)
  299.    index = -1
  300.  
  301.    # Find the internal database index of the column we are looking for.
  302.    $db.get_col_order_vector.each do |col_index|
  303.       if name == $db.get_data_column(col_index).get_name
  304.          index = col_index
  305.       end
  306.    end
  307.  
  308.    #puts "Got column index."
  309.    #puts index
  310.  
  311.  
  312.    dc = $db.get_data_column(index)
  313.    mve = $db.get_matrix_ve(dc.get_its_mve_id)
  314.  
  315.    # Convert each cell into an array and store in an array of arrays
  316.    cells = Array.new
  317.    arg_names = Array.new
  318.  
  319.    if dc.get_its_mve_type == MatrixVocabElement::MatrixType::MATRIX
  320.       for i in (0 .. (mve.get_num_formal_args - 1))
  321.          fa = mve.get_formal_arg_copy(i)
  322.          arg_names << fa.get_farg_name
  323.       end
  324.    end
  325.  
  326.    for i in (1 .. dc.get_num_cells)
  327.       cell = dc.get_db.get_cell(dc.get_id, i)
  328.       c = Array.new
  329.       c << cell.get_onset.get_time
  330.       c << cell.get_offset.get_time
  331.       c << cell.get_val.to_escaped_string.tr_s("(", "").tr_s(")", "").split(",")
  332.       c << i
  333.       cells << c
  334.    end
  335.  
  336.  
  337.    v = Variable.new
  338.    v.name = name
  339.    v.old_args = arg_names
  340.    #v.type = dc.get_its_mve_type
  341.    v.set_cells(cells, arg_names)
  342.  
  343.  
  344.    return v
  345. end
  346.  
  347. #-------------------------------------------------------------------
  348. # Method name: setVariable
  349. # Function: setVariable will overwrite a variable in the database with the same name as the name argument.
  350. #           If no variable with the same name exists, it will create a new variable.
  351. # Arguments:
  352. # => name (optional): The name of the variable being created
  353. # => var  (required): The Ruby container of the variable to be put into the database.  This is the return value of
  354. #         createNewVariable or getVariable that has been modified.
  355. # Usage:
  356. #       trial = getVariable("trial")
  357. #       ** Do some modification to trial
  358. #       setVariable("trial", trial)
  359. #-------------------------------------------------------------------
  360.  
  361. def setVariable(name, var)
  362.  
  363.    # Since this code was already written for three separate values,
  364.    # I'm just splitting it back up for now.
  365.  
  366.    arg_names = var.old_args
  367.    cells = Array.new
  368.    var.cells.each do |cell|
  369.       c = Array.new
  370.       c << cell.onset
  371.       c << cell.offset
  372.       c << Array.new
  373.       var.arglist.each do |arg|
  374.          t = eval "cell.#{arg}"
  375.          c[2] << t.to_s()
  376.       end
  377.       cells << c
  378.    end
  379.  
  380.    # If the column already exists, delete it and build a new one.
  381.    # If it doesn't, just add a new one.
  382.    if not $db.col_name_in_use(name)
  383.       col = DataColumn.new($db, name, MatrixVocabElement::MatrixType::MATRIX)
  384.       $db.add_column(col)
  385.    else
  386.       oldcol = $db.get_column(name)
  387.       numcells = oldcol.get_num_cells
  388.       numcells.downto(1) do |i|
  389.          $db.remove_cell($db.get_cell(oldcol.get_id, i).get_id)
  390.       end
  391.       #$db.remove_column(oldcol.get_id)
  392.  
  393.       #col = DataColumn.new($db, name, MatrixVocabElement::MatrixType::MATRIX)
  394.       #$db.add_column(col)
  395.    end
  396.    # Check if matrix already defined
  397.    col = $db.get_column(name)
  398.    mve0 = $db.get_matrix_ve(col.its_mve_id)
  399.    if mve0.get_num_formal_args() == 1
  400.       # Setup structure of matrix column
  401.       mve0 = MatrixVocabElement.new(mve0)
  402.  
  403.       mve0.delete_formal_arg(0)
  404.       arg_names.each do |arg|
  405.          farg = NominalFormalArg.new($db, arg)
  406.          mve0.append_formal_arg(farg)
  407.       end
  408.  
  409.       $db.replace_matrix_ve(mve0)
  410.    end
  411.    col = $db.get_column(name)
  412.    mve0 = $db.get_matrix_ve(col.its_mve_id)
  413.    matID0 = mve0.get_id()
  414.    cells.each do |cell|
  415.        #print "writing cell"
  416.       c = DataCell.new($db, col.get_id, matID0)
  417.       mat = Matrix.new($db, matID0)
  418.  
  419.       if cell[0].to_i > 0
  420.          c.onset = TimeStamp.new(1000, cell[0].to_i)
  421.       end
  422.       if cell[1].to_i > 0
  423.          c.offset = TimeStamp.new(1000, cell[1].to_i)
  424.       end
  425.  
  426.       narg = 0
  427.       cell[2].each do |dv|
  428.          argid = mve0.get_formal_arg(narg).get_id()
  429.          if dv == "" or dv == nil
  430.             a = arg_names[narg]
  431.             fdv = NominalDataValue.new($db, argid)
  432.             fdv.clearValue()
  433.          else
  434.             fdv = NominalDataValue.new($db, argid, dv)
  435.          end
  436.  
  437.          mat.replaceArg(narg,fdv)
  438.          narg += 1
  439.       end
  440.       c.set_val(mat)
  441.       $db.append_cell(c)
  442.    end
  443. end
  444.  
  445. #-------------------------------------------------------------------
  446. # Method name: make_rel
  447. # Function: This function will create a reliability column that is a copy
  448. #           of another column in the database, copying every nth cell and
  449. #           carrying over some of the arguments from the original, if wanted.
  450. # Arguments:
  451. # => relname (required): The name of the reliability column to be created.
  452. # => var_to_copy (required): The name of the variable in the database you
  453. #                   wish to copy.
  454. # => multiple_to_keep: The number of cells to skip.  For every other cell, use 2.
  455. # => *args_to_keep: Comma separated strings for the arguments you want to keep
  456. #             between cells.  For example, "onset", "trialnum", "block" would keep
  457. #             those three arguments in the new cells that are created.
  458. # Returns:
  459. # => A Ruby object representation of the rel column inside OpenSHAPA.
  460. # Usage:
  461. #       rel_trial = make_rel("rel.trial", "trial", 2, "onset", "trialnum", "unit")
  462. #-------------------------------------------------------------------
  463.  
  464. def make_rel(relname, var_to_copy, multiple_to_keep, *args_to_keep)
  465.    # Get the primary variable from the DB
  466.    var_to_copy = getVariable(var_to_copy)
  467.  
  468.    # Clip down cells to fit multiple to keep
  469.    for i in 0..var_to_copy.cells.length-1
  470.       if multiple_to_keep == 0
  471.          var_to_copy.cells[i] = nil
  472.       elsif var_to_copy.cells[i].ordinal % multiple_to_keep != 0
  473.          var_to_copy.cells[i] = nil
  474.       else
  475.          var_to_copy.cells[i].ordinal = var_to_copy.cells[i].ordinal / multiple_to_keep
  476.       end
  477.    end
  478.    # Clear out the nil cells
  479.    var_to_copy.cells.compact!
  480.  
  481.    var_to_copy.cells.each do |cell|
  482.       if !args_to_keep.include?("onset")
  483.          cell.onset = 0
  484.       end
  485.       if !args_to_keep.include?("offset")
  486.          cell.offset = 0
  487.       end
  488.       cell.arglist.each do |arg|
  489.          if !args_to_keep.include?(arg)
  490.             cell.change_arg(arg,"")
  491.          end
  492.       end
  493.    end
  494.    setVariable(relname, var_to_copy)
  495.    return var_to_copy
  496. end
  497.  
  498. #-------------------------------------------------------------------
  499. # Method name: createNewVariable
  500. # Function: Creates a brand new blank variable with argument *args and name name.
  501. # Arguments:
  502. # => name (required): The OpenSHAPA name of the variable being retrieved
  503. # => *args: (optional): List of arguments that the variable will contain.  Onset, Offset, and
  504. #               ordinal are created by default.
  505. # Returns:
  506. # => A Ruby object representation of the variable inside OpenSHAPA.
  507. # Usage:
  508. #       trial = createNewVariable("trial", "trialnum", "unit")
  509. #       blank_cell = trial.make_new_cell()
  510. #       setVariable(trial)
  511. #-------------------------------------------------------------------
  512.  
  513. def createNewVariable(name, *args)
  514.    v = Variable.new
  515.  
  516.    v.name = name
  517.  
  518.    if args[0].class == Array
  519.       args = args[0]
  520.    end
  521.  
  522.    # Set the argument names in arg_names and set the database internal style with <argname> in old_args
  523.    arg_names = Array.new
  524.    old_args = Array.new
  525.    for arg in args
  526.       arg_names << arg
  527.       old_args << "<" + arg.to_s + ">"
  528.    end
  529.    c = Array.new
  530.    v.old_args = old_args
  531.    v.set_cells(nil, arg_names)
  532.  
  533.    # Return reference to this variable for the user
  534.    return v
  535. end
  536.  
  537. #-----------------------------------------------------------------
  538. # EXPERIMENTAL METHODS FOR FUTURE RELEASE
  539. #-----------------------------------------------------------------
  540.  
  541. #-----------------------------------------------------------#
  542. # make_duration_rel: Makes a duration based reliability column
  543. # based on John's method.  It will create two new columns, one
  544. # that contains a cell with a number for that block, and another
  545. # blank column for the free coding within that block.
  546. #-----------------------------------------------------------#
  547.  
  548. #-------------------------------------------------------------------
  549. # Method name: makeDurationBlockRel
  550. # Function: Makes a duration based reliability column
  551. # based on John's method.  It will create two new columns, one
  552. # that contains a cell with a number for that block, and another
  553. # blank column for the free coding within that block.
  554. # Arguments:
  555. # => relname (required): The name of the rel column to be made.
  556. # => var_to_copy (required): The name of the variable being copied.
  557. # => binding (required): The name of the variable to bind the copy to.
  558. # => block_dur (required): How long (in seconds) should the blocks be?
  559. # => skip_blocks (required): How many blocks of block_dur should we skip between
  560. #     each coding block?
  561. #
  562. # # Returns:
  563. # => Nothing.  Variables are written to the database.
  564. # #-------------------------------------------------------------------
  565. def makeDurationBlockRel(relname, var_to_copy, binding, block_dur, skip_blocks)
  566.    block_var = createNewVariable(relname + "_blocks", "block_num")
  567.    rel_var = make_rel(relname, var_to_copy, 0)
  568.  
  569.    var_to_copy = getVariable(var_to_copy)
  570.    binding = getVariable(binding)
  571.  
  572.  
  573.    block_dur = block_dur * 1000 # Convert to milliseconds
  574.    block_num = 1
  575.    for bindcell in binding.cells
  576.       cell_dur = bindcell.offset - bindcell.onset
  577.       if cell_dur <= block_dur
  578.          cell = block_var.make_new_cell()
  579.          cell.change_arg("block_num", block_num.to_s)
  580.          cell.change_arg("onset", bindcell.onset)
  581.          cell.change_arg("offset", bindcell.offset)
  582.          block_num += 1
  583.       else
  584.          num_possible_blocks = cell_dur / block_dur  #Integer division
  585.          if num_possible_blocks > 0
  586.             for i in 0..num_possible_blocks
  587.                if i % skip_blocks == 0
  588.                   cell = block_var.make_new_cell()
  589.                   cell.change_arg("block_num", block_num.to_s)
  590.                   cell.change_arg("onset", bindcell.onset + i * block_dur)
  591.                   if bindcell.onset + (i + 1) * block_dur <= bindcell.offset
  592.                      cell.change_arg("offset", bindcell.onset + (i + 1) * block_dur)
  593.                   else
  594.                      cell.change_arg("offset", bindcell.offset)
  595.                   end
  596.                   block_num += 1
  597.                end
  598.             end
  599.          end
  600.       end
  601.    end
  602.    setVariable(relname + "_blocks", block_var)
  603. end
  604.  
  605. #-------------------------------------------------------------------
  606. # Method name: add_args_to_var
  607. # Function: Add new arguments to any variable
  608. # Arguments:
  609. # => var (required): The variable to add args to.  This can be a name or a variable object.
  610. # => *args (required): A list of the arguments to add to var (can be any number of args)
  611. #
  612. # Returns:
  613. # => The new Ruby representation of the variable.  Write it back to the database
  614. # to save it.
  615. #
  616. # Example:
  617. # test = add_args_to_var("test", "arg1", "arg2", "arg3")
  618. # setVariable("test",test)
  619. # -------------------------------------------------------------------
  620. def add_args_to_var(var, *args)
  621.    if var.class == "".class
  622.       var = getVariable(var)
  623.    end
  624.  
  625.    var_new = createNewVariable(var.name, var.arglist + args)
  626.  
  627.    for cell in var.cells
  628.       new_cell = var_new.make_new_cell()
  629.       new_cell.change_arg("onset", cell.onset)
  630.       new_cell.change_arg("offset", cell.offset)
  631.       for arg in var.arglist
  632.          v = eval "cell.#{arg}"
  633.          new_cell.change_arg(arg, v)
  634.       end
  635.    end
  636.  
  637.    return var_new
  638. end
  639.  
  640. #-------------------------------------------------------------------
  641. # Method name: create_mutually_exclusive
  642. # Function: Create a new column from two others, mixing their cells together
  643. #  such that the new variable has all of the arguments of both other variables
  644. #  and a new cell for each overlap and mixture of the two cells.  Mixing two
  645. #  variables together.
  646. # Arguments:
  647. # => name (required): The name of the new variable.
  648. # => var1name (required): Name of the first variable to be mutexed.
  649. # => var2name (required): Name of the second variable to be mutexed.
  650. #
  651. # Returns:
  652. # => The new Ruby representation of the variable.  Write it back to the database
  653. # to save it.
  654. #
  655. # Example:
  656. # test = create_mutually_exclusive("test", "var1", "var2")
  657. # setVariable("test",test)
  658. # -------------------------------------------------------------------
  659. def create_mutually_exclusive(name, var1name, var2name)
  660.    if var1name.class == "".class
  661.       var1 = getVariable(var1name)
  662.    end
  663.    if var2name.class == "".class
  664.       var2 = getVariable(var2name)
  665.    end
  666.  
  667.    var1_argprefix = var1.name.gsub(/(\W)+/,"").downcase + "_"
  668.    var2_argprefix = var2.name.gsub(/(\W)+/,"").downcase + "_"
  669.    puts var2_argprefix
  670.  
  671.    var1_argprefix.gsub(".", "")
  672.    var2_argprefix.gsub(".","")
  673.  
  674.    v1arglist = var1.arglist.map { |arg| var1_argprefix + arg }
  675.    v2arglist = var2.arglist.map { |arg| var2_argprefix + arg }
  676.  
  677.    puts v1arglist, v2arglist
  678.    args = Array.new
  679.    args << (var1_argprefix + "ordinal")
  680.    args += v1arglist
  681.  
  682.    args << (var2_argprefix + "ordinal")
  683.    args += v2arglist
  684.  
  685.    puts "Creating mutex var", var1.arglist
  686.    mutex = createNewVariable(name, args)
  687.    puts "Mutex var created"
  688.  
  689.    # Now we have to go thru var1 and var2 and modify the argument names
  690.  
  691.    usedV1Cells = Array.new
  692.    usedV2Cells = Array.new
  693.    for i in 0..var1.cells.length - 1
  694.       v1cell = var1.cells[i]
  695.       prev_over = false
  696.       within = false
  697.       next_over = false
  698.  
  699.       # Figure out the cell relations
  700.       for v2cell in var2.cells
  701.          if v1cell.onset > v2cell.onset and v1cell.onset < v2cell.offset \
  702.             and v1cell.offset > v2cell.offset
  703.             prev_over = v2cell
  704.          elsif v2cell.onset >= v1cell.onset and v2cell.onset <= v1cell.offset \
  705.             and v2cell.offset <= v1cell.offset and v2cell.offset >= v1cell.onset
  706.             if within == false
  707.                within = Array.new
  708.             end
  709.             within << v2cell
  710.          elsif v1cell.offset > v2cell.onset and v1cell.offset < v2cell.offset \
  711.             and v1cell.onset < v2cell.onset
  712.             next_over = v2cell
  713.          end
  714.       end
  715.       v1_new_onset = v1cell.onset
  716.       v1_new_offset = 0
  717.  
  718.       puts "Finding and adding previous crossover cells"
  719.       # Create the prev cells
  720.       if prev_over != false
  721.          # Make the cell that overlaps the beginning of this one
  722.  
  723.          # This is the overlap cell
  724.          cell2 = mutex.make_new_cell()
  725.          cell2.change_arg("onset", v1cell.onset)
  726.          cell2.change_arg("offset", prev_over.offset)
  727.          for arg in mutex.arglist
  728.             v = nil
  729.             if arg.index(var2_argprefix) == 0
  730.  
  731.                a = arg.gsub(var2_argprefix, "")
  732.                puts "Argname:" + arg
  733.                v = eval "prev_over.#{a}"
  734.             elsif arg.index(var1_argprefix) == 0
  735.  
  736.                a = arg.gsub(var1_argprefix, "")
  737.                puts "Argname:" + arg
  738.                v = eval "v1cell.#{a}"
  739.             end
  740.             cell2.change_arg(arg, v)
  741.          end
  742.  
  743.          # cell3 = mutex.make_new_cell()
  744.          # cell3.change_arg("onset", v1cell.offset)
  745.          # cell3.change_arg("offset", prev_over.offset)
  746.          v1_new_onset = prev_over.offset + 1
  747.  
  748.          printf("PREV V1:on=%d off=%d, cell1:on=%d off=%d\n", \
  749.                 v1cell.onset, v1cell.offset, cell2.onset, cell2.offset)
  750.  
  751.          # printf("PREV V1:on=%d off=%d, cell1:on=%d off=%d, cell2:on=%d off=%d\n", \
  752.          #         v1cell.onset, v1cell.offset, cell1.onset, cell1.offset, cell2.onset, cell2.offset)
  753.  
  754.          usedV2Cells << prev_over
  755.       end
  756.  
  757.       puts "Finding and adding cells within cells"
  758.       if within != false
  759.          # Make cells for each cell within the main cell
  760.          for wcell in within
  761.  
  762.             cell1 = mutex.make_new_cell()
  763.             cell1.change_arg("onset", wcell.onset)
  764.             cell1.change_arg("offset", wcell.offset)
  765.             for arg in mutex.arglist
  766.                v = nil
  767.                if arg.index(var2_argprefix) == 0
  768.                   a = arg.gsub(var2_argprefix, "")
  769.                   v = eval "wcell.#{a}"
  770.                elsif arg.index(var1_argprefix) == 0
  771.                a = arg.gsub(var1_argprefix, "")
  772.                   v = eval "v1cell.#{a}"
  773.                end
  774.                cell1.change_arg(arg, v)
  775.             end
  776.  
  777.             printf("WITHIN V2:on=%d off=%d, cell1:on=%d off=%d, new:on=%d, off=:%d\n", \
  778.                    v1cell.onset, v1cell.offset, cell1.onset, cell1.offset, wcell.onset, wcell.offset)
  779.  
  780.             usedV2Cells << wcell
  781.             usedV1Cells << v1cell
  782.          end
  783.       end
  784.  
  785.       puts "Finding and adding next crossing cells for onset V1: onset=" + v1cell.onset.to_s + " off=" + v1cell.offset.to_s
  786.       if next_over != false
  787.          # Make cells for cell overlapping end
  788.          cell1 = mutex.make_new_cell()
  789.          cell1.change_arg("onset", next_over.onset)
  790.          cell1.change_arg("offset", v1cell.offset)
  791.          for arg in mutex.arglist
  792.             v = nil
  793.             if arg.index(var2_argprefix) == 0
  794.                a = arg.gsub(var2_argprefix, "")
  795.                v = eval "next_over.#{a}"
  796.             elsif arg.index(var1_argprefix) == 0
  797.                a = arg.gsub(var1_argprefix, "")
  798.                v = eval "v1cell.#{a}"
  799.             end
  800.             puts arg, v
  801.             cell1.change_arg(arg, v)
  802.          end
  803.  
  804.          # cell2 = mutex.make_new_cell()
  805.          #       cell2.change_arg("onset", v1cell.offset)
  806.          #       cell2.change_arg("offset", next_over.offset)
  807.  
  808.          v1_new_onset = next_over.onset + 1
  809.  
  810.          usedV2Cells << next_over
  811.  
  812.          # printf("NEXT V1:on=%d off=%d, cell1:on=%d off=%d, cell2:on=%d off=%d\n", \
  813.          #        v1cell.onset, v1cell.offset, cell1.onset, cell1.offset, cell2.onset, cell2.offset)
  814.          printf("NEXT V1:on=%d off=%d, cell1:on=%d off=%d\n", \
  815.                 v1cell.onset, v1cell.offset, cell1.onset, cell1.offset)
  816.       end
  817.       if prev_over != false or within != false or next_over != false
  818.          usedV1Cells << v1cell
  819.       end
  820.    end
  821.  
  822.    puts "Adding V2 within cells"
  823.    # Now add in the v1 cells that are within v2 cells
  824.    for i in 0..var2.cells.length - 1
  825.       within = Array.new
  826.       v2cell = var2.cells[i]
  827.  
  828.       for v1cell in var1.cells
  829.          if v1cell.onset >= v2cell.onset and v1cell.onset <= v2cell.offset \
  830.             and v1cell.offset <= v2cell.offset and v1cell.offset >= v2cell.onset \
  831.             and not (v1cell.onset == v2cell.onset and v1cell.offset == v2cell.offset)
  832.             within << v1cell
  833.          end
  834.       end
  835.  
  836.       if within.length > 0
  837.          # Make cells for each cell within the main cell
  838.          for wcell in within
  839.  
  840.             cell1 = mutex.make_new_cell()
  841.             cell1.change_arg("onset", wcell.onset)
  842.             cell1.change_arg("offset", wcell.offset)
  843.             for arg in mutex.arglist
  844.                v = nil
  845.                if arg.index(var1_argprefix) == 0
  846.  
  847.                   a = arg.gsub(var1_argprefix, "")
  848.                   v = eval "wcell.#{a}"
  849.                elsif arg.index(var2_argprefix) == 0
  850.  
  851.                   a = arg.gsub(var2_argprefix, "")
  852.                   v = eval "v2cell.#{a}"
  853.                end
  854.                cell1.change_arg(arg, v)
  855.             end
  856.  
  857.             printf("WITHIN V2:on=%d off=%d, cell1:on=%d off=%d, new:on=%d, off=:%d\n", \
  858.                    v1cell.onset, v1cell.offset, cell1.onset, cell1.offset, wcell.onset, wcell.offset)
  859.  
  860.             usedV1Cells << wcell
  861.             usedV2Cells << v2cell
  862.          end
  863.       end
  864.  
  865.    end
  866.  
  867.    puts "Erasing dupes."
  868.    # Erase dupes
  869.    usedV1Cells.uniq!
  870.    usedV2Cells.uniq!
  871.  
  872.    for c in usedV2Cells
  873.       var2.cells.delete(c)
  874.    end
  875.    for c in usedV1Cells
  876.       var1.cells.delete(c)
  877.    end
  878.    for c in var1.cells
  879.       cell = mutex.make_new_cell()
  880.       cell.change_arg("onset", c.onset)
  881.       cell.change_arg("offset", c.offset)
  882.       for arg in mutex.arglist
  883.          if arg.index(var1_argprefix) == 0
  884.  
  885.             puts "C:",arg, v, c.arglist
  886.  
  887.             a = arg.gsub(var1_argprefix, "")
  888.             v = eval "c.#{a}"
  889.             cell.change_arg(arg, v)
  890.          end
  891.       end
  892.    end
  893.    for c in var2.cells
  894.       cell = mutex.make_new_cell()
  895.       cell.change_arg("onset", c.onset)
  896.       cell.change_arg("offset", c.offset)
  897.       for arg in mutex.arglist
  898.          if arg.index(var2_argprefix) == 0
  899.  
  900.             puts arg, v, c.arglist
  901.  
  902.             a = arg.gsub(var2_argprefix, "")
  903.             v = eval "c.#{a}"
  904.             cell.change_arg(arg, v)
  905.          end
  906.       end
  907.    end
  908.  
  909.    # Now we sort the cells in mutex so we can
  910.    # search thru what we have and add in blocks
  911.    mutex.sort_cells()
  912.  
  913.    # Calculate and add cells for gaps in v1
  914.    var1 = getVariable(var1name)
  915.  
  916.  
  917.    for v1cell in var1.cells
  918.       dirty = false
  919.       for i in 0...mutex.cells.length-1
  920.          if dirty == true
  921.             mutex.sort_cells()
  922.             dirty = false
  923.          end
  924.          mcell_cur = mutex.cells[i]
  925.          mcell_next = mutex.cells[i+1]
  926.          # puts "V1:" + v1cell.onset.to_s + " " + v1cell.offset.to_s
  927.          # puts mcell_cur.onset.to_s + " " + mcell_cur.offset.to_s \
  928.          #     + "/" + mcell_next.onset.to_s + " " + mcell_next.offset.to_s
  929.  
  930.          v1range = (v1cell.onset..v1cell.offset)
  931.          if v1range.include?(mcell_cur.onset) and \
  932.             v1range.include?(mcell_cur.offset) and \
  933.             v1range.include?(mcell_next.onset) and \
  934.             v1range.include?(mcell_next.offset)
  935.  
  936.             if mcell_cur.offset + 1 < mcell_next.onset - 1
  937.                cell = mutex.make_new_cell()
  938.                cell.change_arg("onset", mcell_cur.offset + 1)
  939.                cell.change_arg("offset", mcell_next.onset - 1)
  940.                for arg in mutex.arglist
  941.                   a = arg.gsub(var1_argprefix, "")
  942.                   if arg.index(var1_argprefix) == 0
  943.  
  944.                      puts "ONE SIDE +1-1:", arg, v, cell.onset, cell.offset
  945.                      v = eval "v1cell.#{a}"
  946.                      cell.change_arg(arg, v)
  947.                      dirty = true
  948.                   end
  949.                end
  950.             end
  951.          elsif v1range.include?(mcell_cur.onset) and \
  952.             v1range.include?(mcell_cur.offset) and \
  953.             mcell_next.onset - 1 > mcell_cur.offset
  954.  
  955.             if mcell_cur.onset == v1cell.onset
  956.                if mcell_cur.offset + 1 < v1cell.offset
  957.                   cell = mutex.make_new_cell()
  958.                   cell.change_arg("onset", mcell_cur.offset + 1)
  959.                   cell.change_arg("offset", v1cell.offset)
  960.                   for arg in mutex.arglist
  961.                      a = arg.gsub(var1_argprefix, "")
  962.                      if arg.index(var1_argprefix) == 0
  963.  
  964.                         puts "ONE SIDE ==on:" , arg, v, v1cell.arglist, cell.onset, cell.offset
  965.                         v = eval "v1cell.#{a}"
  966.                         cell.change_arg(arg, v)
  967.                         dirty = true
  968.                      end
  969.                   end
  970.                end
  971.                # elsif mcell_cur.offset == v1cell.offset
  972.                #           if v1cell.onset < mcell_cur.onset - 1
  973.                #             cell = mutex.make_new_cell()
  974.                #             cell.change_arg("onset", v1cell.onset)
  975.                #             cell.change_arg("offset", mcell_cur.onset - 1)
  976.                #             for arg in mutex.arglist
  977.                #               a = arg.gsub(var1_argprefix, "")
  978.                #               if arg.include?(var1_argprefix)
  979.                #                 v = eval "v1cell.#{a}"
  980.                #                 puts "ONE SIDE ==off:", arg, v, v1cell.onset, v1cell.offset, cell.onset, cell.offset, mcell_cur.onset, mcell_cur.offset
  981.                #                 cell.change_arg(arg, v)
  982.                #                 dirty = true
  983.                #               end
  984.                #             end
  985.                #           end
  986.             end
  987.          end
  988.       end
  989.    end
  990.  
  991.    mutex.sort_cells()
  992.    var2 = getVariable(var2name)
  993.  
  994.    for v2cell in var2.cells
  995.       dirty = false
  996.       for i in 0...mutex.cells.length-1
  997.          if dirty == true
  998.             mutex.sort_cells()
  999.             dirty = false
  1000.          end
  1001.          mcell_cur = mutex.cells[i]
  1002.          mcell_next = mutex.cells[i+1]
  1003.          # puts "V2:" + v2cell.onset.to_s + " " + v2cell.offset.to_s
  1004.          # puts mcell_cur.onset.to_s + " " + mcell_cur.offset.to_s \
  1005.          #     + "/" + mcell_next.onset.to_s + " " + mcell_next.offset.to_s
  1006.  
  1007.          v2range = (v2cell.onset..v2cell.offset)
  1008.          if v2range.include?(mcell_cur.onset) and \
  1009.             v2range.include?(mcell_cur.offset) and \
  1010.             v2range.include?(mcell_next.onset) and \
  1011.             v2range.include?(mcell_next.offset)
  1012.  
  1013.             if mcell_cur.offset + 1 < mcell_next.onset - 1
  1014.                cell = mutex.make_new_cell()
  1015.                cell.change_arg("onset", mcell_cur.offset + 1)
  1016.                cell.change_arg("offset", mcell_next.onset - 1)
  1017.                for arg in mutex.arglist
  1018.                   a = arg.gsub(var2_argprefix, "")
  1019.                   if arg.index(var2_argprefix) == 0
  1020.  
  1021.                      v = eval "v2cell.#{a}"
  1022.                      puts "V2 Single:", arg, v, v2cell.arglist, cell.onset, cell.offset
  1023.                      cell.change_arg(arg, v)
  1024.                      dirty = true
  1025.                   end
  1026.                end
  1027.             end
  1028.          elsif v2range.include?(mcell_cur.onset) and \
  1029.             v2range.include?(mcell_cur.offset) and \
  1030.             mcell_next.onset - 1 > mcell_cur.offset
  1031.  
  1032.             if mcell_cur.onset == v2cell.onset
  1033.                if mcell_cur.offset + 1 < v2cell.offset
  1034.                   cell = mutex.make_new_cell()
  1035.                   cell.change_arg("onset", mcell_cur.offset + 1)
  1036.                   cell.change_arg("offset", v2cell.offset)
  1037.                   for arg in mutex.arglist
  1038.                      a = arg.gsub(var2_argprefix, "")
  1039.                      if arg.index(var2_argprefix) == 0
  1040.  
  1041.                         v = eval "v2cell.#{a}"
  1042.                         puts "V2 Single:",arg, v, v2cell.arglist, cell.onset, cell.offset
  1043.                         cell.change_arg(arg, v)
  1044.                         dirty = true
  1045.                      end
  1046.                   end
  1047.                end
  1048.             end
  1049.             if mcell_next.offset == v2cell.offset
  1050.                if v2cell.onset < mcell_next.onset - 1
  1051.  
  1052.  
  1053.                   cell = mutex.make_new_cell()
  1054.                   cell.change_arg("onset", v2cell.onset)
  1055.                   cell.change_arg("offset", mcell_next.onset - 1)
  1056.                   for arg in mutex.arglist
  1057.                      a = arg.gsub(var2_argprefix, "")
  1058.                      if arg.index(var2_argprefix) == 0
  1059.  
  1060.                         v = eval "v2cell.#{a}"
  1061.                         puts "V2 Single:", arg, v, v2cell.arglist, cell.onset, cell.offset
  1062.                         cell.change_arg(arg, v)
  1063.                         dirty = true
  1064.                      end
  1065.                   end
  1066.                end
  1067.             end
  1068.          end
  1069.       end
  1070.    end
  1071.  
  1072.    mutex.sort_cells()
  1073.  
  1074.    puts "MUTEX FINISHED"
  1075.  
  1076.    return mutex
  1077.  
  1078.    # Have it write ordinals in at end
  1079.    # Have it put ordinals of original cells in
  1080.    # Have it have two arguments to name the prefixes for the arguments
  1081.    #
  1082. end
  1083.  
  1084. #-------------------------------------------------------------------
  1085. # Method name: load_db
  1086. # Function: Loads a new database from a file.  DOES NOT ALTER THE GUI.
  1087. # Arguments:
  1088. # => filename (required): The FULL PATH to the saved OpenSHAPA file.
  1089. #
  1090. # Returns:
  1091. # => db: The database of the opened project.  Set to $db to use other
  1092. #     functions with it.
  1093. # => pj: The project data of the opened project.  Set to $pj to use other
  1094. #     functions with it.
  1095. #
  1096. # Example:
  1097. # $db,$pj = load_db("/Users/username/Desktop/test.opf")
  1098. # -------------------------------------------------------------------
  1099.  
  1100. def load_db(filename)
  1101.    # Packages needed for opening and saving projects and databases.
  1102.  
  1103.  
  1104.    #
  1105.    # ****************************************************************************
  1106.    # *** Check to make sure filename below is the absolute path to a project. ***
  1107.    # ****************************************************************************
  1108.    #
  1109.    #
  1110.    # Main body of example script:
  1111.    #
  1112.    puts "Opening Project: "
  1113.  
  1114.    # Create the controller that holds all the logic for opening projects and
  1115.    # databases.
  1116.    open_c = OpenC.new
  1117.  
  1118.    #
  1119.    # Opens a project and associated database (i.e. either compressed or
  1120.    # uncompressed .shapa files). If you want to just open a standalone database
  1121.    # (i.e .odb or .csv file) call open_c.open_database("filename") instead. These
  1122.    # methods do *NOT* open the project within the OpenSHAPA UI.
  1123.    #
  1124.    db = nil
  1125.    proj = nil
  1126.    if filename.include?(".csv")
  1127.       open_c.open_database(filename)
  1128.    else
  1129.       open_c.open_project(filename)
  1130.       # Get the project that was opened (if you want).
  1131.       proj = open_c.get_project
  1132.    end
  1133.  
  1134.    # Get the database that was opened.
  1135.    db = open_c.get_database
  1136.  
  1137.  
  1138.    # If the open went well - query the database, do calculations or whatever
  1139.    unless db.nil?
  1140.       # This just prints the number of columns in the database.
  1141.       puts "Opened a project with '" + db.get_columns.length.to_s + "' columns!"
  1142.    else
  1143.       puts "Unable to open the project '" + filename + "'"
  1144.    end
  1145.  
  1146.    puts filename + " has been loaded."
  1147.  
  1148.    return db, proj
  1149. end
  1150.  
  1151.  
  1152. #-------------------------------------------------------------------
  1153. # Method name: save_db
  1154. # Function: Saves the current $db and $pj variables to filename.  If
  1155. #     filename ends with .csv, it saves a .csv file.  Otherwise it saves
  1156. #     it as a .opf.
  1157. # Arguments:
  1158. # => filename (required): The FULL PATH to where the OpenSHAPA file should
  1159. #        be saved.
  1160. #
  1161. # Returns:
  1162. # => Nothing.
  1163. #
  1164. # Example:
  1165. # save_db("/Users/username/Desktop/test.opf")
  1166. # -------------------------------------------------------------------
  1167. def save_db(filename)
  1168.    #
  1169.    # Main body of example script:
  1170.    #
  1171.    puts "Saving Database: " + filename
  1172.  
  1173.    # Create the controller that holds all the logic for opening projects and
  1174.    # databases.
  1175.    save_c = SaveC.new
  1176.  
  1177.    #
  1178.    # Saves a database (i.e. a .odb or .csv file). If you want to save a project
  1179.    # call save_project("project file", project, database) instead.
  1180.    # These methods do *NOT* alter the OpenSHAPA UI.
  1181.    #
  1182.    if filename.include?('.csv')
  1183.       save_c.save_database(filename, $db)
  1184.    else
  1185.       #if $pj == nil or $pj.getDatabaseFileName == nil
  1186.          $pj = Project.new()
  1187.          $pj.setDatabaseFileName("db")
  1188.          dbname = filename[filename.rindex("/")+1..filename.length]
  1189.          $pj.setProjectName(dbname)
  1190.       #end
  1191.       save_file = java.io.File.new(filename)
  1192.       save_c.save_project(save_file, $pj, $db)
  1193.    end
  1194.  
  1195.    puts "Save successful."
  1196.  
  1197. end
  1198.  
  1199. def delete_column(colname)
  1200.    col = $db.get_column(colname)
  1201.    numcells = col.get_num_cells
  1202.    numcells.downto(1) do |i|
  1203.       $db.remove_cell($db.get_cell(col.get_id, i).get_id)
  1204.    end
  1205.    $db.remove_column(col.get_id)
  1206. end
  1207.  
  1208.  
  1209. #-------------------------------------------------------------------
  1210. # Method name: load_macshapa_db
  1211. # Function: Opens an old, closed database format MacSHAPA file and loads
  1212. #     it into the current open database.
  1213. #
  1214. #     WARNING: This will only read in
  1215. #     matrix and string variables.  Predicates are not yet supported.
  1216. #     Queries will not be read in.  Times are translated to milliseconds
  1217. #     for compatibility with OpenSHAPA.
  1218. # Arguments:
  1219. # => filename (required): The FULL PATH to the saved MacSHAPA file.
  1220. # => write_to_gui (required): Whether the MacSHAPA file should be read into
  1221. #        the database currently open in the GUI or whether it should just be
  1222. #        read into the Ruby interface.  After this script is run $db and $pj
  1223. #        are now the MacSHAPA file.
  1224. #
  1225. # Returns:
  1226. # => db: The database of the opened project.
  1227. # => pj: The project data of the opened project.
  1228. #
  1229. # Example:
  1230. # $db,$pj = load_db("/Users/username/Desktop/test.opf")
  1231. # -------------------------------------------------------------------
  1232. def load_macshapa_db(filename, write_to_gui)
  1233.  
  1234.  
  1235.    # Create a new DB for us to use so we don't touch the GUI... some of these
  1236.    # files can be huge.
  1237.    # Since I don't know how to make a whole new project, lets just load a blank file.
  1238.    if not write_to_gui
  1239.       #$db,$pj = load_db("/Users/j4lingeman/Desktop/blank.opf")
  1240.       $db = MacshapaDatabase.new(1000)
  1241.       $pj = Project.new()
  1242.    end
  1243.  
  1244.  
  1245.  
  1246.    f = File.open(filename, 'r')
  1247.  
  1248.    # Read and split file by lines.  '\r' is used because that is the default
  1249.    # format for OS9 files.
  1250.    file = f.gets
  1251.    lines = file.split(/\r/)
  1252.  
  1253.    # Find the variable names in the file and use these to create and set up
  1254.    # our columns.
  1255.    predIndex = lines.index("***Predicates***")
  1256.    varIndex = lines.index("***Variables***")
  1257.    spreadIndex = lines.index("***SpreadPane***")
  1258.    predIndex += 2
  1259.  
  1260.    variables = Hash.new
  1261.    varIdent = Array.new
  1262.  
  1263.    while predIndex < varIndex
  1264.       l = lines[predIndex].split(/ /)[5]
  1265.       varname = l[0..l.index("(") - 1]
  1266.       if varname != "###QueryVar###" and varname != "div" and varname != "qnotes"
  1267.          variables[varname] = l[l.index("(")+1..l.length-2].split(/,/)
  1268.          varIdent << l
  1269.       end
  1270.       predIndex += 1
  1271.    end
  1272.  
  1273.    # Create the columns for the variables
  1274.    variables.each do |key, value|
  1275.       # Create column
  1276.       if !$db.col_name_in_use(key)
  1277.          col = DataColumn.new($db, key, MatrixVocabElement::MatrixType::MATRIX)
  1278.          $db.add_column(col)
  1279.       end
  1280.  
  1281.       mve0 = $db.get_vocab_element(key)
  1282.       if mve0.get_num_formal_args() == 1
  1283.          # Setup structure of matrix column
  1284.          mve0 = MatrixVocabElement.new(mve0)
  1285.          mve0.delete_formal_arg(0)
  1286.          value.each { |v|
  1287.             # Strip out the ordinal, onset, and offset.  These will be handled on a
  1288.             # cell by cell basis.
  1289.             if v != "<ord>" and v != "<onset>" and v != "<offset>"
  1290.                #puts v
  1291.                farg = NominalFormalArg.new($db, v)
  1292.                mve0.append_formal_arg(farg)
  1293.             end
  1294.          }
  1295.          $db.replace_matrix_ve(mve0)
  1296.       end
  1297.    end
  1298.  
  1299.    # Search for where in the file the var's cells are, create them, then move
  1300.    # on to the next variable.
  1301.    varSection = lines[varIndex..spreadIndex]
  1302.  
  1303.    varIdent.each do |id|
  1304.       col = $db.get_column(id[0..id.index("(")-1])
  1305.       mve = $db.get_matrix_ve(col.its_mve_id)
  1306.       matid = mve.get_id()
  1307.  
  1308.       # Search the variable section for the above id
  1309.       varSection.each do |l|
  1310.          line = l.split(/[\t\s]/)
  1311.          if line[2] == id
  1312.             #puts varname
  1313.             start = varSection.index(l) + 1
  1314.  
  1315.             stringCol = false
  1316.  
  1317.             if varSection[start - 2].index("strID") != nil
  1318.                stringCol = true
  1319.             end
  1320.  
  1321.             #Found it!  Now build the cells
  1322.             while varSection[start] != "0"
  1323.                varSection[start]
  1324.                if stringCol == false
  1325.                   cellData = varSection[start].split(/[\t]/)
  1326.                   cellData[cellData.length - 1] = cellData[cellData.length-1][cellData[cellData.length-1].index("(")..cellData[cellData.length-1].length]
  1327.  
  1328.                else
  1329.                   cellData = varSection[start].split(/[\t]/)
  1330.                end
  1331.  
  1332.                # Init cell to null
  1333.                cell = DataCell.new($db, col.get_id, mve.get_id)
  1334.                mat = Matrix.new($db, matid)
  1335.  
  1336.                # Convert onset/offset from 60 ticks/sec to milliseconds
  1337.                onset = cellData[0].to_i / 60.0 * 1000
  1338.                offset = cellData[1].to_i / 60.0 * 1000
  1339.  
  1340.                # Set onset/offset of cell
  1341.                cell.onset = TimeStamp.new(1000, onset.round)
  1342.                cell.offset = TimeStamp.new(1000, offset.round)
  1343.  
  1344.                # Split up cell data
  1345.                data = cellData[cellData.length - 1]
  1346.                if stringCol == false
  1347.                   data = data[1..data.length-2]
  1348.                   data = data.gsub(/[() ]*/, "")
  1349.                   data = data.split(/,/)
  1350.                elsif data != nil #Then this is a string var
  1351.                   data = data.strip()
  1352.                   if data.split(" ").length > 1
  1353.                       data = data[data.index(" ")..data.length] # Remove the char count
  1354.                       data = data.gsub("/", " or ")
  1355.                       data = data.gsub(/[^\w ]*/, "")
  1356.                       data = data.gsub(/  /," ")
  1357.                   else
  1358.                       data = ""
  1359.                   end
  1360.                else
  1361.                   data = Array.new
  1362.                   data << nil
  1363.                end
  1364.  
  1365.                # Cycle thru cell data arguments and fill them into the cell matrix
  1366.                narg = 0
  1367.                data.each do |d|
  1368.                   fargid = mve.get_formal_arg(narg).get_id()
  1369.                   d = d.strip()
  1370.                   if d == "" or d == nil or d.index("<") != nil
  1371.                      fdv = NominalDataValue.new($db, fargid)
  1372.                      fdv.clearValue()
  1373.                   else
  1374.                      d = d.strip()
  1375.                      fdv = NominalDataValue.new($db, fargid, d)
  1376.                   end
  1377.                   mat.replaceArg(narg,fdv)
  1378.                   narg += 1
  1379.                end
  1380.  
  1381.                # Put cell into database
  1382.                cell.set_val(mat)
  1383.                $db.append_cell(cell)
  1384.                start += 1
  1385.             end
  1386.          end
  1387.       end
  1388.    end
  1389.  
  1390.    f.close()
  1391.  
  1392.    return $db, $pj
  1393. end
  1394.  
  1395. #-------------------------------------------------------------------
  1396. # Method name: transfer_columns
  1397. # Function: Transfers columns between databases.  If db1 or db2 are set
  1398. #     to the empty string "", then that database is the current database
  1399. #     in $db (usually the GUI's database).  So if you want to transfer a
  1400. #     column into the GUI, set db2 to "".  If you want to tranfer a column
  1401. #     from the GUI into a file, set db1 to "".  Setting remove to true will
  1402. #     DELETE THE COLUMNS YOU ARE TRANSFERRING FROM DB1.  Be careful!
  1403. # Arguments:
  1404. # => db1 (required): The FULL PATH to the saved OpenSHAPA file or set to
  1405. #     "" to use the currently opened database. Columns are transferred FROM here.
  1406. # => db2 (required): The FULL PATH to the saved OpenSHAPA file or set to
  1407. #     "" to use the currently opened database.  Columns are tranferred TO here.
  1408. # => remove (required): Set to true to delete columns in DB1 as they are moved to
  1409. #     db2.  Set to false to leave them intact.
  1410. # => varnames (requires at least 1): You can specify as many var names as you like
  1411. #     that will be retrieved from db1.  These should be the string names of the
  1412. #     variables.
  1413. #
  1414. # Returns:
  1415. # => Nothing.  Saves the files in place or modifies the GUI
  1416. #
  1417. # Example:
  1418. #  transfer_columns("/Users/username/Desktop/test.opf","",true,"idchange")
  1419. #  The above example will transfer the column "idchange" from test.opf to the GUI
  1420. #  and leave test.opf intact with no modifications.
  1421. # -------------------------------------------------------------------
  1422. def transfer_columns(db1, db2, remove, *varnames)
  1423.    puts "Transfering the following columns from " + db1 + " to " + db2 + ":"
  1424.    puts varnames
  1425.  
  1426.    if remove
  1427.       puts "WARNING: These columns will be deleted from " + db1
  1428.    end
  1429.  
  1430.    if db1 == ""
  1431.       from_db = $db
  1432.       from_pj = $pj
  1433.    else
  1434.       from_db, from_pj = load_db(db1)
  1435.    end
  1436.  
  1437.    if db2 == ""
  1438.       to_db = $db
  1439.       to_pj = $pj
  1440.    else
  1441.       to_db, to_pj = load_db(db2)
  1442.    end
  1443.  
  1444.    # Get from DB1
  1445.    $db, $pj = from_db, from_pj
  1446.    vars_to_trans = Array.new
  1447.    for v in varnames
  1448.       vars_to_trans << getVariable(v)
  1449.    end
  1450.  
  1451.    # Transfer to DB2
  1452.    $db, $pj = to_db, to_pj
  1453.    for i in 0...vars_to_trans.length
  1454.       setVariable(varnames[i],vars_to_trans[i])
  1455.    end
  1456.    if db2 != ""
  1457.       puts "Saving " + db2
  1458.       save_db(db2)
  1459.    end
  1460.  
  1461.    # Removing columns should be the last thing we do in case anything goes wrong
  1462.    # We don't want to lose a column for any reason.
  1463.    if remove
  1464.       $db, $pj = from_db, from_pj
  1465.       if remove
  1466.          for v in varnames
  1467.             delete_column(v)
  1468.          end
  1469.       end
  1470.       if db1 != ""
  1471.          puts "Saving " + db1
  1472.          save_db(db1)
  1473.       end
  1474.    end
  1475.  
  1476.    puts "Columns transferred successfully."
  1477. end
  1478.  
  1479.  
  1480. #-------------------------------------------------------------------
  1481. # Method name: check_rel
  1482. # Function: Do a quick, in OpenSHAPA, check of reliability errors.
  1483. # Arguments:
  1484. # => main_col (required): Either the string name or the Ruby column from getVariable
  1485. #     of the primary column to compare against.
  1486. # => rel_col (required): Either the string name or the Ruby column from getVariable
  1487. #     of the reliability column to compare to the primary column.
  1488. # => match_arg (required): The string of the argument to use to match the relability
  1489. #     cells to the primary cells.  This must be a unique identifier between the cells.
  1490. # => time_tolerance (required): The amount of slack you allow, in milliseconds, for
  1491. #     difference between onset and offset before it is considered an error.  Set to 0
  1492. #     for no difference allowed and to a very large number for infinite distance allowed.
  1493. # => dump_file (optional): The full string path to dump the relability output to.  This
  1494. #     can be used for multi-file dumps or just to keep a log.  You can also give it a Ruby
  1495. #     File object if a file is already started.
  1496. #
  1497. # Returns:
  1498. # => Nothing but the console and file output.
  1499. #
  1500. # Example:
  1501. #  check_rel("trial", "rel.trial", "trialnum", 100, "/Users/motoruser/Desktop/Relcheck.txt")
  1502. #   or
  1503. #  check_rel("trial", "rel.trial", "trialnum", 100)
  1504. # -------------------------------------------------------------------
  1505. def check_rel(main_col, rel_col, match_arg, time_tolerance, *dump_file)
  1506.    # Make the match_arg conform to the method format that is used
  1507.    if ["0","1","2","3","4","5","6","7","8","9"].include?(match_arg[0].chr)
  1508.       match_arg = match_arg[1..match_arg.length]
  1509.    end
  1510.    match_arg = match_arg.gsub(/(\W)+/,"").downcase
  1511.  
  1512.    # Set up our method variables
  1513.    dump_file = dump_file[0]
  1514.    if main_col.class == "".class
  1515.       main_col = getVariable(main_col)
  1516.    end
  1517.    if rel_col.class == "".class
  1518.       rel_col = getVariable(rel_col)
  1519.    end
  1520.  
  1521.    printing = false
  1522.    if dump_file != nil
  1523.       if dump_file.class == "".class
  1524.          dump_file = open(dump_file,'a')
  1525.       end
  1526.       printing = true
  1527.    end
  1528.  
  1529.    # Define interal function for printing errors
  1530.    def print_err(m_cell, r_cell, arg, dump_file, main_col, rel_col)
  1531.       main_val = eval "m_cell.#{arg}"
  1532.       rel_val = eval "r_cell.#{arg}"
  1533.       err_str = "ERROR in " + main_col.name + " at Ordinal " + m_cell.ordinal.to_s + ", rel ordinal " + r_cell.ordinal.to_s + " in argument " + arg + ": " + main_val.to_s + ", " + rel_val.to_s + "\n"
  1534.       if dump_file != nil
  1535.          dump_file.write(err_str)
  1536.       end
  1537.       print err_str
  1538.    end
  1539.  
  1540.    # Build error array
  1541.    errors = Hash.new
  1542.    for arg in main_col.arglist
  1543.       errors[arg] = 0
  1544.    end
  1545.    errors["onset"] = 0
  1546.    errors["offset"] = 0
  1547.  
  1548.    # Now check the cells
  1549.    for mc in main_col.cells
  1550.       main_bind = eval "mc.#{match_arg}"
  1551.       for rc in rel_col.cells
  1552.          rel_bind = eval "rc.#{match_arg}"
  1553.          if main_bind == rel_bind
  1554.             # Then check these cells match, check them for errors
  1555.            if (mc.onset - rc.onset).abs >= time_tolerance
  1556.               print_err(mc, rc, "onset", dump_file, main_col, rel_col)
  1557.               errors["onset"] = errors["onset"] + 1
  1558.            end
  1559.            if (mc.offset - rc.offset).abs >= time_tolerance
  1560.               print_err(mc, rc, "offset", dump_file, main_col, rel_col)
  1561.               errors["offset"] = errors["offset"] + 1
  1562.            end
  1563.  
  1564.             for arg in main_col.arglist
  1565.                  main_val = eval "mc.#{arg}"
  1566.                  rel_val = eval "rc.#{arg}"
  1567.                  if main_val != rel_val
  1568.                     print_err(mc, rc, arg, dump_file, main_col, rel_col)
  1569.                     errors[arg] = errors[arg] + 1
  1570.                  end
  1571.             end
  1572.          end
  1573.       end
  1574.    end
  1575.  
  1576.    for arg, errs in errors
  1577.       str = "Total errors for " + arg + ": " + errs.to_s + ", Agreement:" + "%.2f" % (100 * (1.0 - (errs / rel_col.cells.length.to_f))) + "%\n"
  1578.       print str
  1579.       if dump_file != nil
  1580.          dump_file.write(str)
  1581.          dump_file.flush()
  1582.       end
  1583.    end
  1584. end
  1585.  
  1586. #-------------------------------------------------------------------
  1587. # Method name: check_valid_codes
  1588. # Function: Do a quick, in OpenSHAPA, check of valid codes.
  1589. # Arguments:
  1590. # => val (required): The variable that the codes belong to.
  1591. # => dump_file (required): The full path of the file to dump output to.
  1592. #     Use "" to not dump to a file.  You may also pass a Ruby File object.
  1593. # => arg_code_pairs (required): A list of the argument names and valid codes
  1594. #     in the following format: "argument_name", ["y","n"], "argument2", ["j","k","m"]
  1595. # Returns:
  1596. # => Nothing but the console and file output.
  1597. #
  1598. # Example:
  1599. #  check_valid_codes("trial", "", "hand", ["l","r","b","n"], "turn", ["l","r"], "unit", [1,2,3])
  1600. # -------------------------------------------------------------------
  1601.  
  1602. def check_valid_codes(var, dump_file, *arg_code_pairs)
  1603.    if var.class == "".class
  1604.       var = getVariable(var)
  1605.    end
  1606.  
  1607.    if dump_file != ""
  1608.       if dump_file.class == "".class
  1609.          dump_file = open(dump_file, 'a')
  1610.       end
  1611.    end
  1612.  
  1613.    # Make the argument/code hash
  1614.    arg_code = Hash.new
  1615.    for i in 0...arg_code_pairs.length
  1616.       if i % 2 == 0
  1617.          if arg_code_pairs[i].class != "".class
  1618.             puts 'FATAL ERROR in argument/valid code array.  Exiting.  Please check to make sure it is in the format "argumentname", ["valid","codes"]'
  1619.             exit
  1620.          end
  1621.          arg = arg_code_pairs[i]
  1622.          if ["0","1","2","3","4","5","6","7","8","9"].include?(arg[1].chr)
  1623.             arg = arg[1..arg.length]
  1624.          end
  1625.          arg = arg.gsub(/(\W )+/,"").downcase
  1626.  
  1627.          arg_code[arg] = arg_code_pairs[i+1]
  1628.       end
  1629.    end
  1630.  
  1631.    errors = false
  1632.    for cell in var.cells
  1633.       for arg, code in arg_code
  1634.          val = eval "cell.#{arg}"
  1635.          if not code.include?(val)
  1636.             errors = true
  1637.             str = "Code ERROR: Var: " + var.name + "\tOrdinal: " + cell.ordinal.to_s + "\tArg: " + arg + "\tVal: " + val + "\n"
  1638.             print str
  1639.             if dump_file != ""
  1640.                dump_file.write(str)
  1641.             end
  1642.          end
  1643.       end
  1644.    end
  1645.    if not errors
  1646.       puts "No errors found."
  1647.    end
  1648. end
  1649.  
  1650.  
  1651. def getColumnList()
  1652.    col_list = Array.new
  1653.    $db.get_col_order_vector.each do |col_index|
  1654.       col_list << $db.get_data_column(col_index).get_name
  1655.    end
  1656.  
  1657.    return col_list
  1658. end
  1659.  
  1660. def printAllNested(file)
  1661.     columns = getColumnList()
  1662.     columns.sort! # This is just so everything is the same across runs, regardless of column order
  1663.     # Scan each column, getting a list of how many cells the cells of that
  1664.     # contain and how much time the cells of that column fill
  1665.  
  1666.     times = Hash.new
  1667.  
  1668.     for outer_col in columns
  1669.         collected_time = 0
  1670.         for cell in outer_col.cells
  1671.             collected_time += cell.offset - cell.onset
  1672.         end
  1673.         times[outer_col.name] = collected_time
  1674.     end
  1675.  
  1676.     # Now, we want to loop over the columns in the order of the amount of data
  1677.     # that they take up.
  1678.  
  1679. end
  1680.  
  1681. def printCell(cell, file)
  1682.  
  1683. end
  1684.  
  1685. # This requires a column where the first cell in the column is the onset
  1686. # of the sync point, where 0 turns to 1 in the video.  If you just want to
  1687. # match the first motion point with the first frame of video, then leave
  1688. # this argument blank.
  1689. def importDataSource(file, *sync_column)
  1690.  
  1691.  
  1692. end
  1693.  
  1694.  
  1695. #-----------------------------------------------------------------
  1696. # USER EDITABLE SECTION: Use this section between begin and end
  1697. # to make your scripts.
  1698. #-----------------------------------------------------------------
  1699.  
  1700.  
  1701. begin
  1702.    
  1703.     #This line creates the Reliability variable "etrel", defines the variable that
  1704.     #it is being based on "et", defines that you want to have the reliability coder
  1705.     #score 100% of what the primary coder did (2 would create 50%), and the onset
  1706.     #and offset from the primary column have been transferred to the reliability column.
  1707.     make_rel("etrel", "et", 1, "onset", "offset")
  1708.    
  1709.     puts "Create RelPick Column DONE"
  1710.  
  1711. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top