docs: def copy(self):
          """
          Make a copy of this runnable.
  
          @return: Copy of this runnable.
          @rtype: lems.sim.runnable.Runnable
          """
          if self.debug: print("Coping....."+self.id)
          r = Runnable(self.id, self.component, self.parent)
          copies = dict()
  
          # Copy simulation time parameters
          r.time_step = self.time_step
          r.time_completed = self.time_completed
          r.time_total = self.time_total
  
          # Plasticity and state stack (?)
          r.plastic = self.plastic
          r.state_stack = Stack()
          
          # Copy variables (GG - Faster using the add_* methods?)
          for v in self.instance_variables:
              r.instance_variables.append(v)
              r.__dict__[v] = self.__dict__[v]
              r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']
          
          for v in self.derived_variables:
              r.derived_variables.append(v)
              r.__dict__[v] = self.__dict__[v]
              r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']
          
          # Copy array elements
          for child in self.array:
              child_copy = child.copy()
              child_copy.parent = r
              r.array.append(child_copy)
              copies[child.uid] = child_copy
              
          # Copy attachment def
          for att in self.attachments:
              atn = self.attachments[att]
              r.attachments[att] = atn
              r.__dict__[atn] = []
  
          # Copy children
          for uid in self.uchildren:
              child = self.uchildren[uid]
              child_copy = child.copy()
              child_copy.parent = r
              copies[child.uid] = child_copy
              
              r.add_child(child_copy.id, child_copy)
  
              # For typerefs
              try:
                  idx = [k for k in self.__dict__ if self.__dict__[k] == child][0]
                  r.__dict__[idx] = child_copy
              except:
                  pass
  
              # For groups and attachments:
              try:
                  idx = [k for k in self.__dict__ if child in self.__dict__[k]][0]
                  if idx not in r.__dict__:
                      r.__dict__[idx] = []
                  r.__dict__[idx].append(child_copy)
  
              except:
                  pass
                 
          # Copy event ports
          for port in self.event_in_ports:
              r.event_in_ports.append(port)
              r.event_in_counters[port] = 0
  
          for port in self.event_out_ports:
              r.event_out_ports.append(port)
              r.event_out_callbacks[port] = self.event_out_callbacks[port]
          
          for ec in r.component.structure.event_connections:
              if self.debug: print("--- Fixing event_connection: %s in %s"%(ec.toxml(), id(r)))
              
              source = r.parent.resolve_path(ec.from_)
              target = r.parent.resolve_path(ec.to)
              
              if ec.receiver:
                  # Will throw error...
                  receiver_template = self.build_runnable(ec.receiver, target)                                
                  #receiver = copy.deepcopy(receiver_template)
                  receiver = receiver_template.copy()
                  receiver.id = "{0}__{1}__".format(component.id,
                                                    receiver_template.id)
  
                  if ec.receiver_container:
                      target.add_attachment(receiver, ec.receiver_container)
                  target.add_child(receiver_template.id, receiver)
                  target = receiver
              else:
                  source = r.resolve_path(ec.from_)
                  target = r.resolve_path(ec.to)
  
              source_port = ec.source_port
              target_port = ec.target_port
  
              if not source_port:
                  if len(source.event_out_ports) == 1:
                      source_port = source.event_out_ports[0]
                  else:
                      raise SimBuildError(("No source event port "
                                           "uniquely identifiable"
                                           " in '{0}'").format(source.id))
              if not target_port:
                  if len(target.event_in_ports) == 1:
                      target_port = target.event_in_ports[0]
                  else:
                      raise SimBuildError(("No destination event port "
                                           "uniquely identifiable "
                                           "in '{0}'").format(target))
               
              if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
              source.register_event_out_callback(\
                  source_port, lambda: target.inc_event_in(target_port))
              
          
              
  
          # Copy methods
          if getattr(self, "update_kinetic_scheme", None): r.update_kinetic_scheme = self.update_kinetic_scheme
          if getattr(self, "run_startup_event_handlers", None): r.run_startup_event_handlers = self.run_startup_event_handlers
          if getattr(self, "run_preprocessing_event_handlers", None): r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
          if getattr(self, "run_postprocessing_event_handlers", None): r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers
          
          if getattr(self, "update_state_variables", None): r.update_state_variables = self.update_state_variables
          if getattr(self, "update_derived_variables", None): r.update_derived_variables = self.update_derived_variables
          #r.update_shadow_variables = self.update_shadow_variables
          if getattr(self, "update_derived_parameters", None): r.update_derived_parameters = self.update_derived_parameters
  
          for rn in self.regimes:
              r.add_regime(self.regimes[rn])
          r.current_regime = self.current_regime
  
          # Copy groups
          for gn in self.groups:
              g = self.__dict__[gn]
              for c in g:
                  if c.uid in copies:
                      r.add_child_to_group(gn, copies[c.uid])
                  else:
                      c2 = c.copy()
                      c2.parent = r
                      copies[c.uid] = c2
                      r.add_child_to_group(gn, c2)
                      
  
          # Copy remaining runnable references.
          for k in self.__dict__:
              if k == 'parent':
                  continue
              c = self.__dict__[k]
              if isinstance(c, Runnable):
                  if c.uid in copies:
                      r.__dict__[k] = copies[c.uid]
                  else:
                      c2 = c.copy()
                      c2.parent = r
                      copies[c.uid] = c2
                      r.__dict__[k] = c2
             
          # Copy text fields
          for k in self.__dict__:          
              if not k in r.__dict__:
                  c = self.__dict__[k]
                  if self.debug: print("Adding remaining field: %s = %s"%(k,c))
                  r.__dict__[k] = c
                  
          if self.debug:
              print('########################################')
              keys = list(self.__dict__.keys())
              keys.sort()
              print(len(keys))
              for k in keys:
                  print(k, self.__dict__[k])
              print('----------------------------------------')
              keys = list(r.__dict__.keys())
              keys.sort()
              print(len(keys))
              for k in keys:
                  print(k, r.__dict__[k])
              print('########################################')
              print('')
              print('')
              print('')
              print('')
              
          if self.debug: print("Finished coping..."+self.id)
          
          return r