Exemplo n.º 1
0
class Sample(Entity):
    "Customer's sample to be analyzed; associated with a project."

    _URI = 'samples'
    _PREFIX = 'smp'

    name = StringDescriptor('name')
    date_received = StringDescriptor('date-received')
    date_completed = StringDescriptor('date-completed')
    project = EntityDescriptor('project', Project)
    submitter = EntityDescriptor('submitter', Researcher)
    # artifact: defined below
    udf = UdfDictionaryDescriptor()
    udt = UdtDictionaryDescriptor()
    notes = EntityListDescriptor('note', Note)
    files = EntityListDescriptor(nsmap('file:file'), File)
    externalids = ExternalidListDescriptor()
    # biosource XXX

    @classmethod
    def create(cls, lims, container, position, **kwargs):
        """Create an instance of Sample from attributes then post it to the LIMS

        Udfs can be sent in with the kwarg `udfs`. It should be a dictionary-like.
        """
        if not isinstance(container, Container):
            raise TypeError('%s is not of type Container' % container)
        udfs = kwargs.pop("udfs", None)
        instance = super(Sample, cls)._create(lims,
                                              creation_tag='samplecreation',
                                              **kwargs)

        location = ElementTree.SubElement(instance.root, 'location')
        ElementTree.SubElement(location, 'container', dict(uri=container.uri))
        position_element = ElementTree.SubElement(location, 'value')
        position_element.text = position

        # NOTE: This is a quick fix. I assume that it must be possible to initialize samples
        # with UDFs
        for key, value in udfs.items():
            attrib = {
                "name": key,
                "xmlns:udf": "http://genologics.com/ri/userdefined",
            }
            udf = ElementTree.SubElement(instance.root,
                                         'udf:field',
                                         attrib=attrib)
            udf.text = value

        data = lims.tostring(ElementTree.ElementTree(instance.root))
        instance.root = lims.post(uri=lims.get_uri(cls._URI), data=data)
        instance._uri = instance.root.attrib['uri']
        return instance
Exemplo n.º 2
0
class ProcessTypeProcessOutput(object):

    instance = None
    name = None
    root = None
    tag = ''

    artifact_type = StringDescriptor('artifact-type')
    display_name = StringDescriptor('display-name')
    output_generation_type = StringDescriptor('output-generation-type')
    variability_type = StringDescriptor('variability-type')
    number_of_outputs = IntegerDescriptor('number-of-outputs')
    output_name = StringDescriptor('output-name')
    field_definitions = EntityListDescriptor('field-definition', Udfconfig)

    def __init__(self, pt_instance, node):
        self.instance = pt_instance
        self.root = node
        self.lims = pt_instance.lims

    def __repr__(self):
        return "{0}({1})".format(self.__class__.__name__, self.output_name)

    def get(self):
        pass
class Sample(Entity):
    "Customer's sample to be analyzed; associated with a project."

    _URI = 'samples'
    _TAG = 'sample'
    _PREFIX = 'smp'

    name = StringDescriptor('name')
    date_received = StringDescriptor('date-received')
    date_completed = StringDescriptor('date-completed')
    project = EntityDescriptor('project', Project)
    submitter = EntityDescriptor('submitter', Researcher)
    # artifact: defined below
    udf = UdfDictionaryDescriptor()
    udt = UdtDictionaryDescriptor()
    notes = EntityListDescriptor('note', Note)
    files = EntityListDescriptor(nsmap('file:file'), File)
    externalids = ExternalidListDescriptor()
    # biosource XXX
    control_type = EntityDescriptor('control-type', Controltype)

    @classmethod
    def create(cls, lims, container, position, udfs=None, **kwargs):
        """Create an instance of Sample from attributes then post it to the LIMS"""
        if udfs is None:
            udfs = {}
        if not isinstance(container, Container):
            raise TypeError('%s is not of type Container' % container)
        instance = super(Sample, cls)._create(lims,
                                              creation_tag='samplecreation',
                                              udfs=udfs,
                                              **kwargs)

        location = ElementTree.SubElement(instance.root, 'location')
        ElementTree.SubElement(location, 'container', dict(uri=container.uri))
        position_element = ElementTree.SubElement(location, 'value')
        position_element.text = position
        data = lims.tostring(ElementTree.ElementTree(instance.root))
        instance.root = lims.post(uri=lims.get_uri(cls._URI), data=data)
        instance._uri = instance.root.attrib['uri']
        return instance
Exemplo n.º 4
0
class Project(Entity):
    "Project concerning a number of samples; associated with a researcher."

    _URI = 'projects'
    _PREFIX = 'prj'

    name = StringDescriptor('name')
    open_date = StringDescriptor('open-date')
    close_date = StringDescriptor('close-date')
    invoice_date = StringDescriptor('invoice-date')
    researcher = EntityDescriptor('researcher', Researcher)
    udf = UdfDictionaryDescriptor()
    udt = UdtDictionaryDescriptor()
    files = EntityListDescriptor(nsmap('file:file'), File)
    externalids = ExternalidListDescriptor()
Exemplo n.º 5
0
class Processtype(Entity):
    _TAG = 'process-type'
    _URI = 'processtypes'
    _PREFIX = 'ptp'

    def __init__(self, lims, uri=None, id=None, _create_new=False):
        super(Processtype, self).__init__(lims, uri, id, _create_new)
        self.parameters = ProcessTypeParametersDescriptor(self)

    name = StringAttributeDescriptor('name')
    field_definition = EntityListDescriptor('field-definition', Udfconfig)
    process_inputs = ProcessTypeProcessInputDescriptor()
    process_outputs = ProcessTypeProcessOutputDescriptor()
    process_type_attribute = NamedStringDescriptor('process-type-attribute')

    @property
    def process_input(self):
        return self.process_inputs[0]
Exemplo n.º 6
0
class ProcessTypeParameter(object):

    instance = None
    name = None
    root = None
    tag = 'parameter'

    string = StringDescriptor('string')
    run_program_per_event = StringDescriptor('run-program-per-event')
    channel = StringDescriptor('channel')
    invocation_type = StringDescriptor('invocation-type')
    file = EntityListDescriptor(nsmap('file:file'), File)

    def __init__(self, pt_instance, node):
        self.instance = pt_instance
        self.root = node
        self.name = self.root.attrib['name']

    def get(self):
        pass
Exemplo n.º 7
0
class Artifact(Entity):
    "Any process input or output; analyte or file."

    _URI = 'artifacts'
    _TAG = 'artifact'
    _PREFIX = 'art'

    name = StringDescriptor('name')
    type = StringDescriptor('type')
    output_type = StringDescriptor('output-type')
    parent_process = EntityDescriptor('parent-process', Process)
    volume = StringDescriptor('volume')
    concentration = StringDescriptor('concentration')
    qc_flag = StringDescriptor('qc-flag')
    location = LocationDescriptor('location')
    working_flag = BooleanDescriptor('working-flag')
    samples = EntityListDescriptor('sample', Sample)
    udf = UdfDictionaryDescriptor()
    files = EntityListDescriptor(nsmap('file:file'), File)
    reagent_labels = ReagentLabelList()

    # artifact_flags XXX
    # artifact_groups XXX

    def input_artifact_list(self):
        """Returns the input artifact ids of the parrent process."""
        input_artifact_list = []
        try:
            for tuple in self.parent_process.input_output_maps:
                if tuple[1]['limsid'] == self.id:
                    input_artifact_list.append(tuple[0]['uri'])  # ['limsid'])
        except:
            pass
        return input_artifact_list

    def get_state(self):
        "Parse out the state value from the URI."
        parts = urlparse(self.uri)
        params = parse_qs(parts.query)
        try:
            return params['state'][0]
        except (KeyError, IndexError):
            return None

    @property
    def container(self):
        "The container where the artifact is located, or None"
        try:
            return self.location[0]
        except:
            return None

    def stateless(self):
        "returns the artefact independently of it's state"
        parts = urlparse(self.uri)
        if 'state' in parts[4]:
            stateless_uri = urlunparse(
                [parts[0], parts[1], parts[2], parts[3], '', ''])
            return Artifact(self.lims, uri=stateless_uri)
        else:
            return self

    # XXX set_state ?
    state = property(get_state)
    stateless = property(stateless)

    def _get_workflow_stages_and_statuses(self):
        self.get()
        result = []
        rootnode = self.root.find('workflow-stages')
        for node in rootnode.findall('workflow-stage'):
            result.append((Stage(self.lims, uri=node.attrib['uri']),
                           node.attrib['status'], node.attrib['name']))
        return result

    workflow_stages_and_statuses = property(_get_workflow_stages_and_statuses)
Exemplo n.º 8
0
class Process(Entity):
    "Process (instance of Processtype) executed producing ouputs from inputs."

    _URI = 'processes'
    _PREFIX = 'prc'

    type = EntityDescriptor('type', Processtype)
    date_run = StringDescriptor('date-run')
    technician = EntityDescriptor('technician', Researcher)
    protocol_name = StringDescriptor('protocol-name')
    input_output_maps = InputOutputMapList()
    udf = UdfDictionaryDescriptor()
    udt = UdtDictionaryDescriptor()
    files = EntityListDescriptor(nsmap('file:file'), File)
    process_parameter = StringDescriptor('process-parameter')
    instrument = EntityDescriptor('instrument', Instrument)

    # process_parameters XXX

    def outputs_per_input(self,
                          inart,
                          ResultFile=False,
                          SharedResultFile=False,
                          Analyte=False):
        """Getting all the output artifacts related to a particual input artifact"""

        inouts = [
            io for io in self.input_output_maps if io[0]['limsid'] == inart
        ]
        if ResultFile:
            inouts = [
                io for io in inouts if io[1]['output-type'] == 'ResultFile'
            ]
        elif SharedResultFile:
            inouts = [
                io for io in inouts
                if io[1]['output-type'] == 'SharedResultFile'
            ]
        elif Analyte:
            inouts = [io for io in inouts if io[1]['output-type'] == 'Analyte']
        outs = [io[1]['uri'] for io in inouts]
        return outs

    def input_per_sample(self, sample):
        """gettiung all the input artifacts dereved from the specifyed sample"""
        ins_all = self.all_inputs()
        ins = []
        for inp in ins_all:
            for samp in inp.samples:
                if samp.name == sample and inp not in ins:
                    ins.append(inp)
        return ins

    def all_inputs(self, unique=True, resolve=False):
        """Retrieving all input artifacts from input_output_maps
        if unique is true, no duplicates are returned.
        """
        # if the process has no input, that is not standard and we want to know about it
        try:
            ids = [io[0]['limsid'] for io in self.input_output_maps]
        except TypeError:
            logger.error("Process ", self, " has no input artifacts")
            raise TypeError
        if unique:
            ids = list(frozenset(ids))
        if resolve:
            return self.lims.get_batch(
                [Artifact(self.lims, id=id) for id in ids if id is not None])
        else:
            return [Artifact(self.lims, id=id) for id in ids if id is not None]

    def all_outputs(self, unique=True, resolve=False):
        """Retrieving all output artifacts from input_output_maps
        if unique is true, no duplicates are returned.
        """
        # Given how ids is structured, io[1] might be None : some process don't have an output.
        ids = [
            io[1]['limsid'] for io in self.input_output_maps
            if io[1] is not None
        ]
        if unique:
            ids = list(frozenset(ids))
        if resolve:
            return self.lims.get_batch(
                [Artifact(self.lims, id=id) for id in ids if id is not None])
        else:
            return [Artifact(self.lims, id=id) for id in ids if id is not None]

    def shared_result_files(self):
        """Retreve all resultfiles of output-generation-type PerAllInputs."""
        artifacts = self.all_outputs(unique=True)
        return [a for a in artifacts if a.output_type == 'SharedResultFile']

    def result_files(self):
        """Retreve all resultfiles of output-generation-type perInput."""
        artifacts = self.all_outputs(unique=True)
        return [a for a in artifacts if a.output_type == 'ResultFile']

    def analytes(self):
        """Retreving the output Analytes of the process, if existing. 
        If the process is not producing any output analytes, the input 
        analytes are returned. Input/Output is returned as a information string.
        Makes aggregate processes and normal processes look the same."""
        info = 'Output'
        artifacts = self.all_outputs(unique=True)
        analytes = [a for a in artifacts if a.type == 'Analyte']
        if len(analytes) == 0:
            artifacts = self.all_inputs(unique=True)
            analytes = [a for a in artifacts if a.type == 'Analyte']
            info = 'Input'
        return analytes, info

    def parent_processes(self):
        """Retrieving all parent processes through the input artifacts"""
        return [i_a.parent_process for i_a in self.all_inputs(unique=True)]

    def output_containers(self):
        """Retrieve all unique output containers"""
        cs = []
        for o_a in self.all_outputs(unique=True):
            if o_a.container:
                cs.append(o_a.container)
        return list(frozenset(cs))

    @property
    def step(self):
        """Retrive the Step coresponding to this process. They share the same id"""
        return Step(self.lims, id=self.id)