Skip to content

Commit 883ef3b

Browse files
ndg63276Mark Williams
andauthored
LIMS-1501: Allow re-running downstream processing (#948)
* LIMS-1501: Early work on re-running downstream processing * LIMS-1501: Flesh out re-running downtream processing * LIMS-1501: Remove unnecessary ProcessingJobParameters * LIMS-1501: Enable fast_ep and some fast_dp * LIMS-1501: Trigger zocalo directly * LIMS-1501: Rename recipes for consistency * LIMS-1501: Rename file more appropriately --------- Co-authored-by: Mark Williams <mark.williams@diamond.ac.uk>
1 parent edfa884 commit 883ef3b

File tree

11 files changed

+321
-6
lines changed

11 files changed

+321
-6
lines changed

api/src/Page/Download.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ function __get_autoproc_attachments()
188188
array_push($args, $this->arg('FILENAME'));
189189
}
190190

191-
if ($this->has_arg('FILETYPE')) {
191+
if ($this->has_arg('filetype')) {
192192
$where .= ' AND appa.filetype =:' . (sizeof($args) + 1);
193-
array_push($args, $this->arg('FILETYPE'));
193+
array_push($args, $this->arg('filetype'));
194194
}
195195

196196
if ($this->has_arg('AUTOPROCPROGRAMID')) {

api/src/Page/Process.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Process extends Page
1111
public static $arg_list = array(
1212
'PROCESSINGJOBID' => '\d+',
1313
'DATACOLLECTIONID' => '\d+',
14+
'SCALINGID' => '\d+',
1415
'DISPLAYNAME' => '([\w\s\-])+',
1516
'COMMENTS' => '.*',
1617

@@ -45,6 +46,7 @@ class Process extends Page
4546
array('/sweeps', 'post', '_add_reprocessing_sweeps'),
4647

4748
array('/enqueue', 'post', '_enqueue'),
49+
array('/enqueue/downstream', 'post', '_enqueue_downstream'),
4850

4951
array('/pipelines', 'get', '_pipelines'),
5052
);
@@ -384,6 +386,36 @@ function _enqueue()
384386
$this->_output(new \stdClass);
385387
}
386388

389+
function _enqueue_downstream()
390+
{
391+
if (!$this->has_arg('DATACOLLECTIONID')) $this->_error('No data collection id specified');
392+
if (!$this->has_arg('SCALINGID')) $this->_error('No scaling id specified');
393+
if (!$this->has_arg('RECIPE')) $this->_error('No recipe specified');
394+
395+
$chk = $this->db->pq("SELECT dc.datacollectionid, aps.autoprocscalingid
396+
FROM datacollection dc
397+
INNER JOIN datacollectiongroup dcg ON dcg.datacollectiongroupid = dc.datacollectiongroupid
398+
INNER JOIN blsession s ON s.sessionid = dcg.sessionid
399+
INNER JOIN proposal p ON p.proposalid = s.proposalid
400+
INNER JOIN processingjob rp ON rp.datacollectionid = dc.datacollectionid
401+
INNER JOIN autoprocprogram app ON app.processingjobid = rp.processingjobid
402+
INNER JOIN autoproc ap ON ap.autoprocprogramid = app.autoprocprogramid
403+
INNER JOIN autoprocscaling aps ON aps.autoprocid = ap.autoprocid
404+
WHERE p.proposalid = :1 AND dc.datacollectionid = :2 AND aps.autoprocscalingid = :3",
405+
array($this->proposalid, $this->arg('DATACOLLECTIONID'), $this->arg('SCALINGID')));
406+
407+
if (!sizeof($chk)) $this->_error('No such data collection id or scaling id');
408+
409+
$parameters = array(
410+
'ispyb_dcid' => intval($this->arg('DATACOLLECTIONID')),
411+
'scaling_id' => intval($this->arg('SCALINGID')),
412+
);
413+
414+
$this->_submit_zocalo_recipe($this->arg('RECIPE'), $parameters);
415+
416+
$this->_output(new \stdClass);
417+
}
418+
387419
/*
388420
* Controller method for /process/pipelines
389421
* Returns list of processing pipelines that meet query parameters

api/src/Page/Processing.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,7 @@ private function _autoprocessing_query_builder($where, $group, $order = '') {
968968
apss.multiplicity,
969969
apss.meanioversigi as isigi,
970970
apss.resioversigi2 as resisigi,
971+
aps.autoprocscalingid,
971972
ap.spacegroup as sg,
972973
ap.refinedcell_a as cell_a,
973974
ap.refinedcell_b as cell_b,
@@ -1153,6 +1154,7 @@ private function _format_auto_processing_result($table_rows, $messages_result) {
11531154

11541155
$formatted_result[$row['AUTOPROCPROGRAMID']]['TYPE'] = $row['TYPE'];
11551156
$formatted_result[$row['AUTOPROCPROGRAMID']]['AID'] = $row['AUTOPROCPROGRAMID'];
1157+
$formatted_result[$row['AUTOPROCPROGRAMID']]['SCALINGID'] = $row['AUTOPROCSCALINGID'];
11561158
$formatted_result[$row['AUTOPROCPROGRAMID']]['MESSAGES'] = array_key_exists($row['AUTOPROCPROGRAMID'], $messages_result)
11571159
? $messages_result[$row['AUTOPROCPROGRAMID']]
11581160
: array();

api/src/Page/Sample.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,16 +1717,26 @@ function _proteins()
17171717
}
17181718

17191719

1720-
$tot = $this->db->pq("SELECT count(distinct pr.proteinid) as tot FROM protein pr INNER JOIN proposal p ON p.proposalid = pr.proposalid $join WHERE $where", $args);
1721-
$tot = intval($tot[0]['TOT']);
1722-
17231720
if ($this->has_arg('s')) {
17241721
$st = sizeof($args) + 1;
17251722
$where .= " AND (lower(pr.name) LIKE lower(CONCAT(CONCAT('%',:" . $st . "), '%')) OR lower(pr.acronym) LIKE lower(CONCAT(CONCAT('%',:" . ($st + 1) . "), '%')))";
17261723
for ($i = 0; $i < 2; $i++)
17271724
array_push($args, $this->arg('s'));
17281725
}
17291726

1727+
if ($this->has_arg('sid')) {
1728+
$where .= ' AND b.blsampleid=:' . (sizeof($args) + 1);
1729+
array_push($args, $this->arg('sid'));
1730+
$join .= ' LEFT JOIN diffractionplan dp ON dp.diffractionplanid = b.diffractionplanid';
1731+
$extc = 'dp.anomalousscatterer, ';
1732+
}
1733+
1734+
$tot = $this->db->pq("SELECT count(distinct pr.proteinid) as tot FROM protein pr
1735+
INNER JOIN proposal p ON p.proposalid = pr.proposalid
1736+
LEFT OUTER JOIN crystal cr ON cr.proteinid = pr.proteinid
1737+
LEFT OUTER JOIN blsample b ON b.crystalid = cr.crystalid
1738+
$join WHERE $where", $args);
1739+
$tot = intval($tot[0]['TOT']);
17301740

17311741
$start = 0;
17321742
$pp = $this->has_arg('per_page') ? $this->arg('per_page') : 15;

client/src/js/modules/dc/views/autointegration.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ define(['marionette',
88
'modules/dc/views/aiplots',
99
'modules/dc/views/autoprocattachments',
1010
'modules/dc/views/apmessages',
11+
'modules/dc/views/downstreamreprocess',
1112

1213
'views/log',
1314
'views/table',
@@ -16,6 +17,7 @@ define(['marionette',
1617
'templates/dc/dc_autoproc.html'], function(Marionette, Backbone, Backgrid, TabView,
1718
AutoProcAttachments, AutoIntegrations,
1819
RDPlotView, AIPlotsView, AutoProcAttachmentsView, APMessagesView,
20+
DownstreamView,
1921
LogView, TableView, table,
2022
utils, template) {
2123

@@ -30,6 +32,7 @@ define(['marionette',
3032
'click .rd': 'showRD',
3133
'click .plot': 'showPlots',
3234
'click a.apattach': 'showAttachments',
35+
'click a.downstream': 'downstream',
3336
'click .dll': utils.signHandler,
3437
},
3538

@@ -57,6 +60,11 @@ define(['marionette',
5760
this.listenTo(this.attachments, 'file:uploaded', this.showAttachments, this)
5861
},
5962

63+
downstream: function(e) {
64+
e.preventDefault()
65+
app.dialog.show(new DownstreamView({ model: this.getOption('templateHelpers').PARENT, scalingid: this.model.get('SCALINGID'), autoprocprogramid: this.model.get('AID'), type: this.model.get('TYPE')}))
66+
},
67+
6068
showLog: function(e) {
6169
e.preventDefault()
6270
var url = $(e.target).attr('href')
@@ -98,6 +106,7 @@ define(['marionette',
98106
DCID: dcId,
99107
APIURL: app.apiurl,
100108
PROPOSAL_TYPE: app.type,
109+
PARENT: this.options.parent,
101110
}
102111
}
103112
},
@@ -170,6 +179,7 @@ define(['marionette',
170179
collection: this.collection,
171180
id: this.getOption('id'),
172181
el: this.$el.find('.res'),
182+
parent: this.options.parent,
173183
}))
174184
}
175185

client/src/js/modules/dc/views/dc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ define(['marionette',
152152
this.ap = new DCAutoIntegrationView({
153153
id: this.model.get('ID'),
154154
dcPurgedProcessedData: this.model.get('PURGEDPROCESSEDDATA'),
155-
el: this.$el.find('div.autoproc')
155+
el: this.$el.find('div.autoproc'),
156+
parent: this.model
156157
})
157158
} else this.ap.$el.slideToggle()
158159
},
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
define(['backbone', 'marionette', 'views/dialog',
2+
'collections/datacollections',
3+
'collections/proteins',
4+
'collections/autoprocattachments',
5+
'models/datacollection',
6+
'modules/mc/views/dcdistl_downstream',
7+
'modules/samples/collections/pdbs',
8+
'utils/kvcollection',
9+
'templates/dc/downstream.html', 'templates/dc/downstream_dc.html'
10+
], function(Backbone, Marionette, DialogView,
11+
DataCollections, Proteins, AutoProcAttachments,
12+
DataCollection, DCDistlView,
13+
PDBs,
14+
KVCollection,
15+
template, dctemplate
16+
) {
17+
18+
19+
var IDDataCollection = DataCollection.extend({
20+
idAttribute: 'CID',
21+
})
22+
23+
var IDDataCollections = DataCollections.extend({
24+
model: IDDataCollection,
25+
})
26+
27+
var DCDistlViewLarge = DCDistlView.extend({
28+
template: dctemplate,
29+
intStatus: false,
30+
className: 'data_collection',
31+
32+
initialize: function(options) {
33+
DCDistlView.prototype.initialize.apply(this, arguments)
34+
},
35+
36+
onRender: function() {
37+
this.$el.find('ul').addClass('half')
38+
this.$el.find('li input[type="text"]').css('width', '25%')
39+
},
40+
41+
})
42+
43+
44+
var DCDistlsView = Marionette.CollectionView.extend({
45+
childView: DCDistlViewLarge,
46+
childViewOptions: function() {
47+
return {
48+
pipelines: this.getOption('pipelines'),
49+
parent: this.model,
50+
}
51+
}
52+
})
53+
54+
55+
var Pipelines = Backbone.Collection.extend(_.extend({
56+
keyAttribute: 'NAME',
57+
valueAttribute: 'VALUE',
58+
}, KVCollection))
59+
60+
61+
return ReprocessView = DialogView.extend({
62+
template: template,
63+
dialog: true,
64+
title: 'Rerun downstream processing',
65+
className: 'rp content',
66+
dOptions: {
67+
width: '1000px',
68+
},
69+
70+
regions: {
71+
dcr: '.dcs',
72+
},
73+
74+
ui: {
75+
pipeline: 'select[name=pipeline]',
76+
warning: '#warning',
77+
},
78+
79+
buttons: {
80+
Submit: 'submit',
81+
Close: 'closeDialog',
82+
},
83+
84+
disabledButtons: {
85+
Close: 'closeDialog',
86+
},
87+
88+
events: {
89+
'change @ui.pipeline': 'updatePipeline',
90+
},
91+
92+
templateHelpers: function() {
93+
return {
94+
VISIT: this.getOption('visit')
95+
}
96+
},
97+
98+
updatePipeline: function() {
99+
this.model.set('PIPELINE', this.ui.pipeline.val())
100+
this.model.set('PIPELINENAME', this.ui.pipeline.find('option:selected').text())
101+
var btns = this.buttons
102+
var warning = ''
103+
if (['MrBUMP', 'Dimple'].includes(this.model.get('PIPELINENAME')) && this.type.includes('autoPROC')) {
104+
warning = ' Cannot rerun ' + this.model.get('PIPELINENAME') + ' on ' + this.type + ' results'
105+
btns = this.disabledButtons
106+
}
107+
if (['MrBUMP', 'Big EP'].includes(this.model.get('PIPELINENAME')) && this.type.includes('fast_dp')) {
108+
warning = ' Cannot rerun ' + this.model.get('PIPELINENAME') + ' on ' + this.type + ' results'
109+
btns = this.disabledButtons
110+
}
111+
if (this.model.get('PIPELINENAME') === 'Dimple' && this.pdbs.length === 0) {
112+
warning = ' Cannot run Dimple as no PDBs defined'
113+
btns = this.disabledButtons
114+
}
115+
if (this.model.get('PIPELINENAME') === 'MrBUMP' && this.model.get('HASSEQ') === 'No') {
116+
warning = ' Cannot run MrBUMP as no sequence defined'
117+
btns = this.disabledButtons
118+
}
119+
if (this.model.get('PIPELINENAME') === 'Fast EP' && (!this.model.get('ANOMALOUSSCATTERER'))) {
120+
warning = ' Cannot run Fast EP as no anomalous scatterer defined'
121+
btns = this.disabledButtons
122+
}
123+
if (this.model.get('PIPELINENAME') === 'Big EP' && this.model.get('HASSEQ') === 'No') {
124+
warning = ' Cannot run Big EP as no sequence defined'
125+
btns = this.disabledButtons
126+
}
127+
if (this.model.get('PIPELINENAME') === 'Big EP' && (!this.model.get('ANOMALOUSSCATTERER'))) {
128+
warning = ' Cannot run Big EP as no anomalous scatterer defined'
129+
btns = this.disabledButtons
130+
}
131+
this.setButtons(btns)
132+
this.ui.warning.html(warning)
133+
},
134+
135+
submit: function(e) {
136+
e.preventDefault()
137+
138+
this._enqueue({ RECIPE: this.model.get('PIPELINE'), DATACOLLECTIONID: this.model.get('ID'), SCALINGID: this.scalingid })
139+
app.message({ message: 'Downstream processing job successfully submitted'})
140+
141+
},
142+
143+
144+
_enqueue: function(options) {
145+
Backbone.ajax({
146+
url: app.apiurl+'/process/enqueue/downstream',
147+
method: 'POST',
148+
data: {
149+
DATACOLLECTIONID: options.DATACOLLECTIONID,
150+
SCALINGID: options.SCALINGID,
151+
RECIPE: options.RECIPE
152+
},
153+
})
154+
},
155+
156+
157+
initialize: function(options) {
158+
this.proteins = new Proteins(null, { queryParams: { sid: options.model.get('BLSAMPLEID') } })
159+
this._ready = this.proteins.fetch()
160+
this._ready.done(this.doOnReady.bind(this))
161+
this.scalingid = options.scalingid
162+
this.type = options.type
163+
this.attachments = new AutoProcAttachments()
164+
this.attachments.queryParams = {
165+
AUTOPROCPROGRAMID: options.autoprocprogramid,
166+
filetype: 'Result',
167+
}
168+
this.attachments.fetch()
169+
},
170+
171+
onRender: function() {
172+
173+
this.pipelines = new Pipelines([
174+
{ NAME: 'Dimple', VALUE: 'trigger-dimple' },
175+
{ NAME: 'Fast EP', VALUE: 'trigger-fastep' },
176+
{ NAME: 'Big EP', VALUE: 'trigger-bigep' },
177+
{ NAME: 'MrBUMP', VALUE: 'trigger-mrbump' },
178+
])
179+
180+
this.ui.pipeline.html(this.pipelines.opts())
181+
},
182+
183+
doOnReady: function() {
184+
var protein = this.proteins.at(0)
185+
var self = this
186+
_.each(['ACRONYM','PROTEINID','HASSEQ','PDBS','ANOMALOUSSCATTERER'], function(k) {
187+
self.model.set(k, protein.get(k))
188+
})
189+
this.pdbs = new PDBs(null, { pid: this.model.get('PROTEINID') })
190+
this.pdbs.fetch().done(this.updatePipeline.bind(this))
191+
this.collection = new IDDataCollections()
192+
if (this.model) {
193+
var nm = new IDDataCollection(this.model.toJSON())
194+
nm.set('CID', this.collection.length+1)
195+
this.collection.add(nm)
196+
}
197+
this.distlview = new DCDistlsView({ collection: this.collection, pipelines: this.pipelines })
198+
this.dcr.show(this.distlview)
199+
}
200+
201+
202+
})
203+
204+
})

0 commit comments

Comments
 (0)