EdinburghGenomics / pyclarity-lims

Python interface to the GenoLogics LIMS server via its REST API.
MIT License
11 stars 4 forks source link

Pooling samples #40

Closed dbarrell closed 5 years ago

dbarrell commented 5 years ago

Hi all, (Edited from my original post, earlier today, because I was using the wrong data structure for StepPools.pooled_inputs) Not an issue for you, rather for me! I'm trying to pool 2 plates into 2 tubes. First I create the two pools, set up the step and add the Illumina indexes to the tubes, I think I'm all set here, so you can probably ignore this:

    pool1 = Container.create(lims, type=tube_ct)
    pool2 = Container.create(lims, type=tube_ct)
    pools = [pool1, pool2]

    step = Step.create(lims, protocol_step=protocol_step, inputs=artifacts,
                       container_type_name=tube_ct.name)

    process = Process(lims, id=step.actions.step.id)

    # Assign the correct Illumina UDI indexes
<snip>
...
        sample.artifact.reagent_labels = [label]
        sample.artifact.put()

The issue comes when I try and pool the plates. I create a data structure and try and assign this to step.pools.pooled_inputs, thus:

    output_pools = {}
    for idx, plate in enumerate(plates):
        input_arts = []
        plate.get(force=True)
        out_container = pools[idx]
        pool_name = out_container.name
        placement_dict = plate.get_placements()
        for placekey in placement_dict.keys():
            art = placement_dict[placekey]
            print 'Artifact:', art
            input_arts.append(art)
        art_tuple = tuple(input_arts)  # tuble of input arts to add to a tube
        output_pools[pool_name] = tuple((out_container, art_tuple))
        out_container.get(force=True)
        for art in input_arts:
            art.put()
        plate.put()

    step.pools.pooled_inputs = output_pools

    step.advance()

The error I get is:

    step.advance()
  File "/usr/local/lib/python2.7/dist-packages/pyclarity_lims/entities.py", line 843, in advance
    data=self.lims.tostring(ElementTree.ElementTree(self.root))
  File "/usr/local/lib/python2.7/dist-packages/pyclarity_lims/lims.py", line 172, in post
    return self.parse_response(r, accept_status_codes=[200, 201, 202])
  File "/usr/local/lib/python2.7/dist-packages/pyclarity_lims/lims.py", line 214, in parse_response
    self.validate_response(response, accept_status_codes)
  File "/usr/local/lib/python2.7/dist-packages/pyclarity_lims/lims.py", line 207, in validate_response
    raise requests.exceptions.HTTPError(message)
requests.exceptions.HTTPError: 400: Unpooled inputs exist

I think I've got the data structure correct for StepPools.pooled_inputs. I'm thinking it must be the caching of the artifacts. Can anyone see where I've gone wrong?

Thanks!

tcezard commented 5 years ago

I didn't have time to look into it but the first thing that comes to mind is that you should upload the pool before advancing the step

step.pools.pooled_inputs = output_pools
step.pools.put()
step.advance()
dbarrell commented 5 years ago

That certainly has got me a bit further, I now have the number of samples mentioned in Lab View, whereas there was a zero before. However, I still get requests.exceptions.HTTPError: 400: Unpooled inputs exist and upon clicking on the Work In Progress entry I'm still at the 'Samples Waiting for Pooling' stage. So close...

dbarrell commented 5 years ago

Note, I had to also use step.pools.get(force=True) else I get:

 requests.exceptions.HTTPError: 400: cvc-complex-type.3.2.2: Attribute 'uri' is not allowed to appear in element 'pool'.
dbarrell commented 5 years ago

It seems I don't actually upload the pooled_inputs:

print output_pools
step.pools.pooled_inputs = output_pools
step.pools.put()
print step.pools.pooled_inputs

The printed output_pools look like this:

{'27-8838': (Container(https://cegx-test.claritylims.com/api/v2/containers/27-8838),
 (Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A4PA1),
 Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A1PA1),
 Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A3PA1),
 Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A2PA1)
)),
 '27-8839': (Container(https://cegx-test.claritylims.com/api/v2/containers/27-8839),
 (Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A8PA1),
 Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A5PA1),
 Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A7PA1),
 Artifact(https://cegx-test.claritylims.com/api/v2/artifacts/SHE1725A6PA1))
)}

And when I print out the step.pools.pooled_inputs I get an empty dictionary:

{}
tcezard commented 5 years ago

I've had a deeper look and it seems that the current implementation won't support setting new pools from scratch. The pool is an Artifact not a container but when it is sent, it does not exist yet. I'll have to change the code to support this type of behaviour.

dbarrell commented 5 years ago

I see, thanks for looking into it. Maybe I can mock up the artifact in the meantime to make sure it exists beforehand?