lib/catissue/domain/abstract_specimen.rb
def derive(opts=Hash::EMPTY_HASH)
      # add defaults
      add_defaults if specimen_class.nil?
      # copy the option hash
      opts = opts.dup
      # standardize the requirement param, if any
      rqmt = opts.delete(:requirement)
      opts[:specimen_requirement] ||= rqmt if rqmt
      # the default specimen parameters
      unless opts.has_key?(:specimen_requirement) then
        opts[:specimen_class] ||= self.specimen_class ||= infer_specimen_class
        opts[:specimen_type] ||= self.specimen_type
      end
      unless Class === opts[:specimen_class] then
        opts[:specimen_class] = infer_class(opts)
      end
      count = opts.delete(:count)
      count ||= 1
      aliquot_flag = false
      if count > 1 and opts[:specimen_class] == self.class and opts[:specimen_type] == self.specimen_type then
        # aliquots share the specimen_characteristics
        child_chr = opts[:specimen_characteristics] ||= specimen_characteristics
        aliquot_flag = child_chr == specimen_characteristics
      end
      # set aliquot parameters if necessary
      if aliquot_flag then set_aliquot_parameters(opts, count) end
      # make the derived specimens
      count == 1 ? create_derived(opts) : Array.new(count) { create_derived(opts) }
    end
def derive(opts=Hash::EMPTY_HASH)
      # add defaults
      add_defaults if specimen_class.nil?
      # copy the option hash
      opts = opts.dup
      # standardize the requirement param, if any
      rqmt = opts.delete(:requirement)
      opts[:specimen_requirement] ||= rqmt if rqmt
      # the default specimen parameters
      unless opts.has_key?(:specimen_requirement) then
        opts[:specimen_class] ||= self.specimen_class ||= infer_specimen_class
        opts[:specimen_type] ||= self.specimen_type
      end
      unless Class === opts[:specimen_class] then
        opts[:specimen_class] = infer_class(opts)
      end
      count = opts.delete(:count)
      count ||= 1
      aliquot_flag = false
      if count > 1 and opts[:specimen_class] == self.class and opts[:specimen_type] == self.specimen_type then
        # aliquots share the specimen_characteristics
        child_chr = opts[:specimen_characteristics] ||= specimen_characteristics
        aliquot_flag = child_chr == specimen_characteristics
      end
      # set aliquot parameters if necessary
      if aliquot_flag then set_aliquot_parameters(opts, count) end
      # make the derived specimens
      count == 1 ? create_derived(opts) : Array.new(count) { create_derived(opts) }
    end
Derives a new specimen from this specimen. The options are described in
 {Specimen.create_specimen}, with one addition:
 * +:count+(+Integer+) - the optional number of specimens to derive

 If the +:count+ option is greater than one and the +:specimen_class+,
 +:specimen_type+ and +:specimen_characteristics+ options are not set to values
 which differ from the respective values for this Specimen, then the specimen is
 aliquoted, otherwise the derived specimens are created independently, e.g.:
   spc = Specimen.create_specimen(:specimen_class => :tissue, :specimen_type => :frozen)
   spc.derive(:count => 1) #=> not aliquoted
   spc.derive(:count => 2) #=> aliquoted
   spc.derive(:specimen_type => 'Frozen Specimen') #=> two aliquots

 The default derived _initial_quantity_ is the parent specimen _available_quantity_
 divided by _count_ for aliquots, zero otherwise. If the child _specimen_class_
 is the same as this Specimen class, then this parent Specimen's _available_quantity_
 is decremented by the child _initial_quantity_, e.g.:
   spc.available_quantity #=> 4
   spc.derive(:initial_quantity => 1)
   spc.available_quantity #=> 3
   spc.derive(:count => 2, :specimen_type => 'Frozen Tissue')
   spc.derive(:count => 2) #=> two aliquots with quantity 1 each
   spc.available_quantity #=> 0

 The default derived specimen label is _label_+_+_n_, where _label_ is this specimen's
 label and _n_ is this specimen's child count after including the new derived specimen,
 e.g. +3090_3+ for the third child in the parent specimen with label +3090+.

 @param [{Symbol => Object}, nil] opts the attribute => value hash
 @return [AbstractSpecimen, <AbstractSpecimen>] the new derived specimen if the +:count+ option
   is missing or one, otherwise an Array of _count_ derived specimens
 @raise [Jinx::ValidationError] if an aliquoted parent available quantity is not greater than zero
   or the derived specimen quantities exceed the parent available quantity