def _run(self):
        artifacts = None
        # Get the output artifacts
        if self.source == 'input':
            artifacts = self.process.all_inputs(unique=True, resolve=True)
        elif self.source == 'output':
            artifacts = self.process.all_outputs(unique=True, resolve=True)
        elif self.source == 'submitted':
            artifacts = list(frozenset([s.artifact for a in self.process.all_inputs() for s in a.samples]))

        # Find the workflow stage
        s = self.stage_name if self.stage_name else None
        stage = get_workflow_stage(self.lims, self.workflow_name, s)
        if not stage:
            raise ValueError(
                'Stage specified by workflow: %s and stage: %s does not exist in %s' % (self.workflow_name, self.stage_name, self.baseuri)
            )
        # Route the artifacts
        self.lims.route_artifacts(artifacts, stage_uri=stage.uri)
    def _run(self):
        # Find the Discard plate workflow uri
        discard_plate_stage = get_workflow_stage(self.lims, workflow_name=discard_wf_name, stage_name=plate_discard_wf_stage_name)
        self.info('Found Stage %s uri: %s', plate_discard_wf_stage_name, discard_plate_stage.uri)

        # Fetch the artifacts associated with the step
        step_artifacts = self.process.all_inputs()
        self.lims.get_batch(step_artifacts)

        # Fetch the sample associated with these artifacts
        samples = [a.samples[0] for a in step_artifacts]
        self.lims.get_batch(samples)
        self.info('Found %d Samples in the step', len(samples))
        # Fetch the all the artifacts associated with these samples
        step_associated_artifacts = fetch_all_artifacts_for_samples(self.lims, samples)
        self.info('Found %d Analytes (derived samples)', len(step_associated_artifacts))
        # List all the containers and retrieve them
        containers = list(set([a.container for a in step_associated_artifacts]))
        batch_limit(self.lims, containers)
        self.info('Found %d containers', len(containers))

        # Filter the containers to keep the one that are valid
        valid_containers = [c for c in containers if is_valid_container(c)]
        self.info('Found %d valid containers to potentially discard', len(valid_containers))

        # Get all the artifacts in the valid containers and retrieve the one that were not retrieved already
        container_artifacts = set()
        for c in valid_containers:
            container_artifacts.update(set(c.placements.values()))

        non_step_atifacts = container_artifacts.difference(set(step_associated_artifacts))
        batch_limit(self.lims, list(non_step_atifacts))
        self.info(
            'Found %d others associated with the container but not associated with discarded samples',
            len(non_step_atifacts)
        )

        artifacts_to_route = []
        container_to_route = []
        for container in valid_containers:
            route_allowed = True
            self.info(
                'Test container %s, with %s artifacts',
                container.name,
                len(container.placements.values())
            )
            for artifact in list(container.placements.values()):
                if artifact in step_associated_artifacts or has_workflow_stage(artifact, sample_discard_wf_stage_name):
                    self.info(
                        'Container %s might route because artifact %s in step_associated_artifacts (%s) or has been discarded before (%s)',
                        container.name, artifact.name, artifact in step_associated_artifacts, has_workflow_stage(artifact, sample_discard_wf_stage_name)
                    )
                else:
                    # This container will have to wait
                    route_allowed = False
                    self.info(
                        "Container: %s won't route because artifact %s in step_associated_artifacts (%s) or has been discarded before (%s)",
                        container.name, artifact.name, artifact in step_associated_artifacts, has_workflow_stage(artifact, sample_discard_wf_stage_name)
                    )
            if route_allowed:
                artifacts_to_route.extend(list(container.placements.values()))
                container_to_route.append(container)
                self.info('Will route container: %s', container.name)
        self.info('Route %s containers with %s artifacts', len(container_to_route), len(artifacts_to_route))
        print('Route %s containers with %s artifacts' % (len(container_to_route), len(artifacts_to_route)))
        self.lims.route_artifacts(artifacts_to_route, stage_uri=discard_plate_stage.uri)