Module: Krill::OperationList

Defined in:
lib/krill/operation_list.rb,
lib/krill/operation_list_table.rb,
lib/krill/operation_list_input_table.rb

Instance Method Summary collapse

Instance Method Details

#add_static_inputs(name, sample_name, container_name) ⇒ Object



260
261
262
263
264
265
266
267
268
269
# File 'lib/krill/operation_list.rb', line 260

def add_static_inputs(name, sample_name, container_name)
  each do |op|
    sample = Sample.find_by(name: sample_name)
    container = ObjectType.find_by(name: container_name)
    op.add_input(name, sample, container)
    op.input(name).set item: sample.in(container.name).first
  end

  self
end

#cleanup_input_tableObject

Collects inputs from custom_input and saves in operation.temporary hash



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/krill/operation_list_input_table.rb', line 40

def cleanup_input_table
  temp_op = first
  messages = []
  each do |op|
    vhash = op.temporary[:validation]
    op.temporary[:temporary_keys].each do |temp_key|
      # Parse key
      _uid, key = temp_key.to_s.split('__')
      key = key.to_sym
      val = temp_op.temporary[temp_key]

      # Input validation
      vblock = vhash[key] if vhash
      valid = true
      valid = vblock.call(op, val) if vblock
      unless valid
        msghash = op.temporary[:validation_messages] || {}
        msgblock = msghash[key]
        validation_message = msgblock.call(op, key, val) if msgblock
        validation_message ||= "Input invalid: operation_id: #{op.id}, key: #{key}, value: #{val}"
        messages << validation_message
      end

      op.temporary[key.to_sym] = val
      temp_op.temporary.delete(temp_key)
    end
    op.temporary.delete(:temporary_keys)
    op.temporary.delete(:uid)
    op.temporary.delete(:validation)
    op.temporary.delete(:validation_messages)
  end
  messages
end

#collect(&block) ⇒ Object



34
35
36
37
38
39
# File 'lib/krill/operation_list.rb', line 34

def collect(&block)
  ops = super(&block)
  ops.extend(OperationList)
  ops.protocol = @protocol
  ops
end

#collection(name, role, opts = {}) ⇒ Object

Add column with input/output Collection ids

Parameters:

  • name (String)

    Input/Output name

  • role (String)

    ("input", "output")

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • checkable (Hash)

    a customizable set of options

See Also:



82
83
84
85
86
87
88
89
# File 'lib/krill/operation_list_table.rb', line 82

def collection(name, role, opts = {})
  entries = running.collect do |op|
    property op, :child_item_id, name, role, opts[:checkable]
  end
  heading = opts[:heading] || "#{name} Collection ID (#{role})"
  @table.add_column(heading, entries)
  self
end

#collection_column(fv) ⇒ Object



213
214
215
# File 'lib/krill/operation_list.rb', line 213

def collection_column(fv)
  fv.name + ' Collection ID'
end

#column(name, role, opts = {}) ⇒ Object

Add column with input/output column (if part of a Collection)

Parameters:

  • name (String)

    Input/Output name

  • role (String)

    ("input", "output")

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • checkable (Hash)

    a customizable set of options

See Also:



114
115
116
117
118
119
# File 'lib/krill/operation_list_table.rb', line 114

def column(name, role, opts = {})
  @table.add_column(opts[:heading] || "#{name} Column (#{role})", running.collect do |op|
    property op, :column, name, role, opts[:checkable]
  end)
  self
end

#column_column(fv) ⇒ Object



221
222
223
# File 'lib/krill/operation_list.rb', line 221

def column_column(fv)
  fv.name + ' Column'
end

#custom_column(opts = { heading: 'Custom Column', checkable: false }, &block) ⇒ Object

Add column with custom content

Parameters:

  • opts (Hash) (defaults to: { heading: 'Custom Column', checkable: false })
  • heading (Hash)

    a customizable set of options

  • checkable (Hash)

    a customizable set of options



125
126
127
128
129
130
131
132
# File 'lib/krill/operation_list_table.rb', line 125

def custom_column(opts = { heading: 'Custom Column', checkable: false }, &block)
  entries = running.collect(&block).collect do |x|
    opts[:checkable] ? { content: x, check: true } : x
  end
  @table.add_column(opts[:heading], entries)

  self
end

#custom_input(key, opts = { heading: 'Custom Input', checkable: false, type: 'string', style_block: nil }, &default_block) ⇒ Object

Appends a column to an OperationsList table which accepts user input. Used in conjunction with show_with_input_table. Consider using get instead, unless you have a specific reason to use this method



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/krill/operation_list_input_table.rb', line 10

def custom_input(key, opts = { heading: 'Custom Input', checkable: false, type: 'string', style_block: nil }, &default_block)
  each.with_index do |op, i|
    op.temporary[:uid] = i
  end
  temp_op = first
  default_values = map do |op|
    default_block.call(op)
  end
  entries = zip(default_values).map do |op, d|
    # Save a list of temporary keys to be deleted later
    new_key = _create_temp_key(key, op)
    temporary_keys = op.temporary[:temporary_keys] || []
    temporary_keys.push(new_key)
    op.temporary[:temporary_keys] = temporary_keys
    o = {
      type: opts[:type],
      operation_id: temp_op.id,
      key: new_key,
      default: d
    }
    style = opts[:style_block].call(op) if opts[:style_block]
    o.merge!(style) if style
    o
  end
  @table.add_column(opts[:heading], entries)

  self
end

#end_tableObject

Finish building a table

See Also:



28
29
30
# File 'lib/krill/operation_list_table.rb', line 28

def end_table
  @table
end

#erroredArray

Select Operations with status "error"

Returns:



78
79
80
# File 'lib/krill/operation_list.rb', line 78

def errored
  select(&:error?)
end

#get(key, opts) ⇒ Object

Append a column to the OperationList Table that accepts user input

Parameters:

  • key ("String")

    the name of the key where the input data will be stored

  • opts (Hash)

    Additional options

  • type (Hash)

    a customizable set of options

  • default (Hash)

    a customizable set of options



252
253
254
255
256
257
# File 'lib/krill/operation_list_table.rb', line 252

def get(key, opts)
  @table.add_column(opts[:heading] || key.to_s, running.collect do |op|
    { type: opts[:type] || 'number', operation_id: op.id, key: key, default: opts[:default] || 0 }
  end)
  self
end

#group_by(&block) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/krill/operation_list.rb', line 62

def group_by(&block)
  grouped_ops = super(&block)
  grouped_ops = grouped_ops.map do |key, ops|
    ops.extend(OperationList)
    ops.protocol = @protocol
    [key, ops]
  end.to_h
  grouped_ops
end

#input_collection(name, opts = {}) ⇒ Object

Add column with list of input collection by the given input name

Input by the given name is either a part or a collection

Parameters:

  • name (String)

    the name of the input to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



187
188
189
# File 'lib/krill/operation_list_table.rb', line 187

def input_collection(name, opts = {})
  collection name, 'input', opts
end

#input_column(name, opts = {}) ⇒ Object

Add column with list of input column indicies by the given input name

Input by the given name is a part

Parameters:

  • name (String)

    the name of the input to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



231
232
233
# File 'lib/krill/operation_list_table.rb', line 231

def input_column(name, opts = {})
  column name, 'input', opts
end

#input_item(name, opts = {}) ⇒ Object

Add column with list of input items by the given input name

Parameters:

  • name (String)

    the name of the input to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



146
147
148
# File 'lib/krill/operation_list_table.rb', line 146

def input_item(name, opts = {})
  item name, 'input', opts
end

#input_row(name, opts = {}) ⇒ Object

Add column with list of input row indices by the given input name

Input by the given name is a part

Parameters:

  • name (String)

    the name of the input to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



209
210
211
# File 'lib/krill/operation_list_table.rb', line 209

def input_row(name, opts = {})
  row name, 'input', opts
end

#input_sample(name, opts = {}) ⇒ Object

Add column with list of input samples by the given input name

Parameters:

  • name (String)

    the name of the input to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



166
167
168
# File 'lib/krill/operation_list_table.rb', line 166

def input_sample(name, opts = {})
  sample name, 'input', opts
end

#io_table(role = 'input') ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/krill/operation_list.rb', line 225

def io_table(role = 'input')
  t = Table.new

  each_with_index do |op, _i|
    values = op.field_values.select { |fv| fv.role == role }
    values.each do |fv|
      if fv.part?
        unless t.has_column? fv.name
          t.column(fv.name,               fv.name)
           .column(collection_column(fv), collection_column(fv))
           .column(row_column(fv),        row_column(fv))
           .column(column_column(fv),     column_column(fv))
        end
        t.set(fv.name,               fv.child_sample ? fv.child_sample.name : 'NO SAMPLE')
         .set(collection_column(fv), fv.child_item_id || 'NO COLLECTION')
         .set(row_column(fv),        fv.row)
         .set(column_column(fv),     fv.column)
      elsif fv.value
        t.column(fv.name, fv.name)
        t.set(fv.name, fv.value)
      else
        unless t.has_column? fv.name
          t.column(fv.name,         fv.name)
           .column(item_column(fv), item_column(fv))
        end
        t.set(fv.name,         fv.child_sample ? fv.child_sample.name : 'NO SAMPLE')
         .set(item_column(fv), fv.child_item_id || 'NO ITEM')
      end
    end
    t.append
  end

  t
end

#item(name, role, opts = {}) ⇒ Object

Add column with input/output Item ids

Parameters:

  • name (String)

    Input/Output name

  • role (String)

    ("input", "output")

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • checkable (Hash)

    a customizable set of options

See Also:



52
53
54
55
56
57
# File 'lib/krill/operation_list_table.rb', line 52

def item(name, role, opts = {})
  @table.add_column(opts[:heading] || "#{name} Item ID (#{role})", running.collect do |op|
                                                                     property op, :item_link, name, role, opts[:checkable]
                                                                   end)
  self
end

#item_column(fv) ⇒ Object



209
210
211
# File 'lib/krill/operation_list.rb', line 209

def item_column(fv)
  fv.name + ' Item ID'
end

#make(custom_opts = {}) ⇒ Array

Produce items for Operations

Parameters:

  • custom_opts (Hash) (defaults to: {})

Options Hash (custom_opts):

  • :errored (Bool)

    Include Operations with status "error"

  • :role (String)

    "input" or "output"

  • :only (Array<String>)

    Make only outputs of provided names

Returns:



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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/krill/operation_list.rb', line 138

def make(custom_opts = {})

  opts = { errored: false, role: 'output', only: [] }.merge custom_opts

  @output_collections = {}
  ops = select { |op| opts[:errored] || op.status != 'error' }

  ops.each_with_index do |op, i|

    op.field_values.select { |fv| fv.role == opts[:role] && (opts[:only].blank? || opts[:only].member?(fv.name)) }.each do |fv|

      if fv.part?

        rows = fv.object_type.rows || 1
        columns = fv.object_type.columns || 12

        size = rows * columns

        unless @output_collections[fv.name]
          @output_collections[fv.name] = (0..(ops.length - 1) / size).collect do |_c|
            fv.make_collection
          end
        end

        fv.make_part(@output_collections[fv.name][i / size], (i % size) / columns, (i % size) % columns)

      elsif fv.object_type && fv.collection?

        fv.make_collection

      else

        fv.make

      end # if

    end # select/each

  end # each

  self

end

#map(&block) ⇒ Object



41
42
43
44
45
46
# File 'lib/krill/operation_list.rb', line 41

def map(&block)
  ops = super(&block)
  ops.extend(OperationList)
  ops.protocol = @protocol
  ops
end

#operation_id(opts = { heading: 'Operation ID', checkable: false }) ⇒ Object



134
135
136
137
138
# File 'lib/krill/operation_list_table.rb', line 134

def operation_id(opts = { heading: 'Operation ID', checkable: false })
  @table.add_column(opts[:heading], running.collect(&:id))

  self
end

#output_collection(name, opts = {}) ⇒ Object

Add column with list of ouput collection by the given ouput name

Output by the given name is either a part or a collection

Parameters:

  • name (String)

    the name of the ouput to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



198
199
200
# File 'lib/krill/operation_list_table.rb', line 198

def output_collection(name, opts = {})
  collection name, 'output', opts
end

#output_collectionsArray<Collection>

Return collections produced

Examples:

Find stripwells made for PCR

operations.output_collections["PCR"]

Returns:



126
127
128
129
# File 'lib/krill/operation_list.rb', line 126

def output_collections
  @output_collections ||= {}
  @output_collections
end

#output_column(name, opts = {}) ⇒ Object

Add column with list of output row indicies by the given output name

Output by the given name is a part

Parameters:

  • name (String)

    the name of the output to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



242
243
244
# File 'lib/krill/operation_list_table.rb', line 242

def output_column(name, opts = {})
  column name, 'output', opts
end

#output_item(name, opts = {}) ⇒ Object

Add column with list of output items by the given output name

Parameters:

  • name (String)

    the name of the output to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



156
157
158
# File 'lib/krill/operation_list_table.rb', line 156

def output_item(name, opts = {})
  item name, 'output', opts
end

#output_row(name, opts = {}) ⇒ Object

Add column with list of output row indicies by the given output name

Output by the given name is a part

Parameters:

  • name (String)

    the name of the output to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



220
221
222
# File 'lib/krill/operation_list_table.rb', line 220

def output_row(name, opts = {})
  row name, 'output', opts
end

#output_sample(name, opts = {}) ⇒ Object

Add column with list of ouput samples by the given ouput name

Parameters:

  • name (String)

    the name of the ouput to display

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • clickable (Hash)

    a customizable set of options



176
177
178
# File 'lib/krill/operation_list_table.rb', line 176

def output_sample(name, opts = {})
  sample name, 'output', opts
end

#property(op, method_name, name, role, checkable) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/krill/operation_list_table.rb', line 32

def property(op, method_name, name, role, checkable)

  fv = op.get_field_value name, role

  if checkable
    fv ? { content: fv.send(method_name), check: true } : '?'
  else
    fv ? fv.send(method_name) : '?'
  end

end

#protocol=(p) ⇒ Object



30
31
32
# File 'lib/krill/operation_list.rb', line 30

def protocol=(p)
  @protocol = p
end

#reject(&block) ⇒ Object



55
56
57
58
59
60
# File 'lib/krill/operation_list.rb', line 55

def reject(&block)
  ops = super(&block)
  ops.extend(OperationList)
  ops.protocol = @protocol
  ops
end

#result(key, opts = {}) ⇒ Object



259
260
261
262
263
264
# File 'lib/krill/operation_list_table.rb', line 259

def result(key, opts = {})
  @table.add_column(opts[:heading] || key.to_s, running.collect do |op|
    { content: op.temporary[key], check: opts[:checkable] }
  end)
  self
end

#retrieve(opts = {}) ⇒ Array

Get all items. Error out any operations for which items could not be retrieved. Show item retrieval instructions (unless verbose is false)

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :interactive (Bool)

    Show Krill slides

  • :method (String) — default: "boxes"

    Show boxes slide

  • :only (Array<String>)

    Retrieve only inputs of provided names

Returns:



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/krill/operation_list.rb', line 90

def retrieve(opts = {})
  opts = { interactive: true, method: 'boxes', only: [] }.merge opts

  items = []

  each_with_index do |op, _i|
    op_items = []
    op.inputs.select { |fv| opts[:only].empty? || opts[:only].include?(fv.name) }.each do |input|
      input.retrieve unless input.child_item || input.value
      if input.child_item_id
        op_items << input.child_item
      elsif !input.value
        op.status = 'error'
        op.save
        sname = input.child_sample ? input.child_sample.name : '-'
        oname = input.child_item ? input.child_item.object_type.name : '-'
        op.associate 'input error', "Could not find input #{input.name}: #{sname} / #{oname}"
      end
    end
    items += op_items unless op.error?
  end

  if block_given?
    @protocol.take items.uniq, opts, &Proc.new
  else
    @protocol.take items.uniq, opts
  end

  self

end

#row(name, role, opts = {}) ⇒ Object

Add column with input/output row (if part of a Collection)

Parameters:

  • name (String)

    Input/Output name

  • role (String)

    ("input", "output")

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • checkable (Hash)

    a customizable set of options

See Also:



99
100
101
102
103
104
# File 'lib/krill/operation_list_table.rb', line 99

def row(name, role, opts = {})
  @table.add_column(opts[:heading] || "#{name} Row (#{role})", running.collect do |op|
    property op, :row, name, role, opts[:checkable]
  end)
  self
end

#row_column(fv) ⇒ Object



217
218
219
# File 'lib/krill/operation_list.rb', line 217

def row_column(fv)
  fv.name + ' Row'
end

#runningObject



72
73
74
# File 'lib/krill/operation_list.rb', line 72

def running
  reject(&:error?)
end

#sample(name, role, opts = {}) ⇒ Object

Add column with input/output Sample ids

Parameters:

  • name (String)

    Input/Output name

  • role (String)

    ("input", "output")

  • opts (Hash) (defaults to: {})
  • heading (Hash)

    a customizable set of options

  • checkable (Hash)

    a customizable set of options

See Also:



67
68
69
70
71
72
# File 'lib/krill/operation_list_table.rb', line 67

def sample(name, role, opts = {})
  @table.add_column(opts[:heading] || "#{name} Sample ID (#{role})", running.collect do |op|
                                                                       property op, :child_sample_id, name, role, opts[:checkable]
                                                                     end)
  self
end

#select(&block) ⇒ Object



48
49
50
51
52
53
# File 'lib/krill/operation_list.rb', line 48

def select(&block)
  ops = super(&block)
  ops.extend(OperationList)
  ops.protocol = @protocol
  ops
end

#start_table(_opts = { errored: false }) ⇒ Array

Begin building a table from Krill::OperationList

Examples:

Make a table for pipetting primers into a stripwell for PCR

table operations.start_table
  .output_collection("Fragment", heading: "Stripwell")
  .custom_column(heading: "Well") { |op| op.output("Fragment").column + 1 }
  .input_item(FWD, heading: "Forward Primer, 2.5 µL", checkable: true)
  .input_item(REV, heading: "Reverse Primer, 2.5 µL", checkable: true)
.end_table

Parameters:

  • opts (Hash)

    a customizable set of options

Returns:



21
22
23
24
# File 'lib/krill/operation_list_table.rb', line 21

def start_table(_opts = { errored: false })
  @table = Table.new
  self
end

#store(opts = { interactive: true, method: 'boxes', errored: false, io: 'all' }) ⇒ Array

Return all inputs and outputs to their locations

Parameters:

  • opts (Hash) (defaults to: { interactive: true, method: 'boxes', errored: false, io: 'all' })

Options Hash (opts):

  • :interactive (Bool)

    Show Krill slides

  • :method (String) — default: "boxes"

    Show boxes slide

  • :errored (Bool)

    Store Operations with status "error"

  • :io (String) — default: "all", "input", "output"

    Store inputs, outputs, or both

Returns:



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/krill/operation_list.rb', line 189

def store(opts = { interactive: true, method: 'boxes', errored: false, io: 'all' })

  items = []

  select { |op| opts[:errored] || op.status != 'error' }.each_with_index do |op, _i|
    op.field_values.select { |fv| fv.field_type.sample? && (opts[:io] == 'all' || fv.role == opts[:io]) }.each do |input|
      items << input.child_item if input.child_item.location != 'deleted'
    end
  end

  if block_given?
    @protocol.release items.uniq, opts, &Proc.new
  else
    @protocol.release items.uniq, opts
  end

  self

end

#validate(key, &validation_block) ⇒ Object

Tags an input key for validation, by calling a validation block for each operation

Examples:

(validate :some_key to have input value between 1 and 10)

operations.start_table
  .custom_input(:some_key, heading: "Input", type: "number") { |op| 1 }
  .validate(:some_key) { |op, inputted_value| inputted_value.between?(1,10) }
  .end_Table


82
83
84
85
86
87
88
89
# File 'lib/krill/operation_list_input_table.rb', line 82

def validate(key, &validation_block)
  each do |op|
    validation = op.temporary[:validation] || {}
    validation[key] = validation_block
    op.temporary[:validation] = validation
  end
  self
end

#validation_message(key, &message_block) ⇒ Object

Sends message for valid and invalid inputs based on validation

Examples:

(validate :some_key to have input value between 1 and 10)

operations.start_table
  .custom_input(:some_key, heading: "Input", type: "number") { |op| 1 }
  .validate(:some_key) { |op, inputted_value| inputted_value.between?(1,10) }
  .validation_message(:some_key) { |op, key, val|
    "Operation id #{op.id} with key #{key} had incorrect value #{val}" + \
    "Value should be between 1 and 10."
    }
  .end_Table


102
103
104
105
106
107
108
109
# File 'lib/krill/operation_list_input_table.rb', line 102

def validation_message(key, &message_block)
  each do |op|
    message_hash = op.temporary[:validation_messages] || {}
    message_hash[key] = message_block
    op.temporary[:validation_messages] = message_hash
  end
  self
end