diff --git a/api/config_sample.php b/api/config_sample.php
index c84bb5f1e..97d9fc85d 100644
--- a/api/config_sample.php
+++ b/api/config_sample.php
@@ -395,6 +395,12 @@
'i04' => False,
);
+ # puck capacity of beamlines which take pucks, sample capacity of those which take samples
+ $bl_capacity = array(
+ "i03" => array("pucks" => 37, "samples" => 0),
+ "i04" => array("pucks" => 37, "samples" => 0),
+ );
+
# Dials server values
$dials_rest_url = "";
$dials_rest_jwt = "";
diff --git a/api/index.php b/api/index.php
index 3ee429c4e..60d180f74 100644
--- a/api/index.php
+++ b/api/index.php
@@ -73,7 +73,8 @@ function setupApplication($mode): Slim
$valid_components, $enabled_container_types, $synchweb_version, $redirects,
$shipping_service_app_url, $use_shipping_service_redirect, $use_shipping_service_redirect_incoming_shipments,
$dials_rest_url_rings, $closed_proposal_link, $ccp4_cloud_upload_url,
- $only_staff_can_assign, $industrial_prop_codes, $prop_codes_data_deleted, $container_types_with_parents;
+ $only_staff_can_assign, $industrial_prop_codes, $prop_codes_data_deleted, $container_types_with_parents,
+ $bl_capacity;
$app->contentType('application/json');
$options = $app->container['options'];
$app->response()->body(json_encode(array(
@@ -106,6 +107,7 @@ function setupApplication($mode): Slim
'container_types_with_parents' => $container_types_with_parents,
'industrial_prop_codes' => $industrial_prop_codes,
'prop_codes_data_deleted' => $prop_codes_data_deleted ?? array(),
+ 'bl_capacity' => $bl_capacity,
)));
});
return $app;
diff --git a/api/src/Controllers/AssignController.php b/api/src/Controllers/AssignController.php
index 4cc3f4f31..d5f959e81 100644
--- a/api/src/Controllers/AssignController.php
+++ b/api/src/Controllers/AssignController.php
@@ -11,7 +11,7 @@ class AssignController extends Page
{
private $assignData;
- public static $arg_list = array('visit' => '\w+\d+-\d+', 'cid' => '\d+', 'did' => '\d+', 'pos' => '\d+', 'bl' => '[\w\-]+');
+ public static $arg_list = array('visit' => '\w+\d+-\d+', 'cid' => '\d+', 'did' => '\d+', 'sid' => '\d+', 'pos' => '\d+', 'bl' => '[\w\-]+');
public static $dispatch = array(
array('/assign', 'get', 'assignContainer'),
@@ -32,15 +32,24 @@ function __construct(Slim $app, $db, $user, AssignData $assignData)
function assignContainer()
{
global $only_staff_can_assign;
- $cs = $this->assignData->getContainer($this->arg('visit'), $this->arg('cid'));
+ if ($this->has_arg('cid')) {
+ $cs = $this->assignData->getContainer($this->arg('visit'), $this->arg('cid'));
+ } else if ($this->has_arg('sid')) {
+ $cs = $this->assignData->getSample($this->arg('visit'), $this->arg('sid'));
+ } else {
+ $cs = array();
+ }
if (sizeof($cs) > 0)
{
$bl = $cs[0]['BEAMLINENAME'];
if (is_array($only_staff_can_assign) && array_key_exists($bl, $only_staff_can_assign) && $only_staff_can_assign[$bl] == true && !$this->staff) {
$this->_error("Only staff can assign containers on this beamline");
- } else {
+ } else if ($this->has_arg('cid')) {
$this->assignData->assignContainer($cs[0], $this->arg('pos'));
$this->_output(1);
+ } else if ($this->has_arg('sid')) {
+ $this->assignData->assignSample($cs[0], $this->arg('pos'));
+ $this->_output(1);
}
}
else
@@ -52,16 +61,25 @@ function assignContainer()
function unassignContainer()
{
global $only_staff_can_assign;
- $cs = $this->assignData->getContainer($this->arg('visit'), $this->arg('cid'));
+ if ($this->has_arg('cid')) {
+ $cs = $this->assignData->getContainer($this->arg('visit'), $this->arg('cid'));
+ } else if ($this->has_arg('sid')) {
+ $cs = $this->assignData->getSample($this->arg('visit'), $this->arg('sid'));
+ } else {
+ $cs = array();
+ }
if (sizeof($cs) > 0)
{
$bl = $cs[0]['BEAMLINENAME'];
if (is_array($only_staff_can_assign) && array_key_exists($bl, $only_staff_can_assign) && $only_staff_can_assign[$bl] == true && !$this->staff) {
$this->_error("Only staff can unassign containers on this beamline");
- } else {
+ } else if ($this->has_arg('cid')) {
$this->assignData->unassignContainer($cs[0]);
$this->_output(1);
+ } else if ($this->has_arg('sid')) {
+ $this->assignData->unassignSample($cs[0]);
+ $this->_output(1);
}
}
else
diff --git a/api/src/Downstream/Type/Dimple.php b/api/src/Downstream/Type/Dimple.php
index 932487436..b23330703 100644
--- a/api/src/Downstream/Type/Dimple.php
+++ b/api/src/Downstream/Type/Dimple.php
@@ -120,6 +120,8 @@ function results() {
$dat['PKLIST'] = $pklist;
}
+ $dat['ANODE_PEAKS'] = $this->_get_anode_peaks($this->process['PARAMETERS']['scaling_id']);
+
$results = new DownstreamResult($this);
$results->data = $dat;
@@ -165,4 +167,36 @@ function mapmodel($n = 0, $map = false) {
return $pdb['FILE'];
}
}
+
+ function _get_anode_peaks($scaling_id) {
+
+ $peaks = array();
+ $plot = array();
+
+ $blobs = $this->db->pq(
+ "SELECT mb.x, mb.y, mb.z, mb.height, mb.occupancy,
+ mb.nearestatomdistance, mb.nearestatomname, mb.nearestatomchainid,
+ mb.nearestatomresname, mb.nearestatomresseq
+ FROM mxmrrunblob mb
+ INNER JOIN mxmrrun m ON mb.mxmrrunid = m.mxmrrunid
+ WHERE mb.maptype='anomalous' and m.autoprocscalingid=:1
+ ORDER BY mb.height DESC
+ LIMIT 10",
+ array($scaling_id)
+ );
+
+ foreach ($blobs as $n => $blob) {
+ array_push($peaks, array(
+ number_format($blob['X'], 2),
+ number_format($blob['Y'], 2),
+ number_format($blob['Z'], 2),
+ number_format($blob['HEIGHT'], 2),
+ number_format($blob['OCCUPANCY'], 1),
+ $blob['NEARESTATOMDISTANCE'] . ' ' . $blob['NEARESTATOMNAME'] . '_' . $blob['NEARESTATOMCHAINID']
+ . ':' . $blob['NEARESTATOMRESNAME'] . $blob['NEARESTATOMRESSEQ'],
+ ));
+ array_push($plot, array($n+1, $blob['HEIGHT']));
+ }
+ return array('TABLE' => $peaks, 'PLOT' => $plot);
+ }
}
diff --git a/api/src/Model/Services/AssignData.php b/api/src/Model/Services/AssignData.php
index ed3e4bbaf..75c414903 100644
--- a/api/src/Model/Services/AssignData.php
+++ b/api/src/Model/Services/AssignData.php
@@ -27,6 +27,18 @@ function getContainer($visitId, $containerId)
AND c.containerid=:2", array($visitId, $containerId));
}
+ function getSample($visitId, $sampleId)
+ {
+ return $this->db->pq("SELECT b.blsampleid,b.name,d.dewarid,bl.beamlinename,c.containerid,c.code FROM blsample b
+ INNER JOIN container c ON c.containerid = b.containerid
+ INNER JOIN dewar d ON d.dewarid = c.dewarid
+ INNER JOIN shipping s ON s.shippingid = d.shippingid
+ INNER JOIN blsession bl ON bl.proposalid = s.proposalid
+ INNER JOIN proposal p ON s.proposalid = p.proposalid
+ WHERE CONCAT(p.proposalcode, p.proposalnumber, '-', bl.visit_number) LIKE :1
+ AND b.blsampleid=:2", array($visitId, $sampleId));
+ }
+
function assignContainer($container, $location)
{
$this->updateDewar($container['DEWARID'], 'processing');
@@ -36,11 +48,27 @@ function assignContainer($container, $location)
$this->updateDewarHistory($container['DEWARID'], 'processing', $container['BEAMLINENAME'], $container['CODE'] . ' => ' . $location);
}
+ function assignSample($sample, $location)
+ {
+ $this->updateSample($sample['BLSAMPLEID'], $location);
+
+ $this->updateDewar($sample['DEWARID'], 'processing');
+
+ $this->updateContainerAndHistory($sample['CONTAINERID'], 'processing', $sample['BEAMLINENAME'], null);
+
+ $this->updateDewarHistory($sample['DEWARID'], 'processing', $sample['BEAMLINENAME'], $sample['NAME'] . ' => ' . $location);
+ }
+
function unassignContainer($container)
{
$this->updateContainerAndHistory($container['CONTAINERID'], 'at facility', '', '');
}
+ function unassignSample($sample)
+ {
+ $this->updateSample($sample['BLSAMPLEID'], null);
+ }
+
function updateContainerAndHistory($containerId, $status, $beamlineName, $location)
{
$this->updateContainer($containerId, $status, $beamlineName, $location);
@@ -61,6 +89,12 @@ function updateContainer($containerId, $status, $beamlineName, $location)
WHERE containerid=:4", array($beamlineName, $location, $status, $containerId));
}
+ function updateSample($sampleId, $location)
+ {
+ $this->db->pq("UPDATE blsample SET isinsamplechanger=:1
+ WHERE blsampleid=:2", array($location, $sampleId));
+ }
+
function getDewar($dewarId, $proposalId, $visitId)
{
$where = "p.proposalid=:1";
diff --git a/api/src/Page/Sample.php b/api/src/Page/Sample.php
index ac87180d9..24b57298d 100644
--- a/api/src/Page/Sample.php
+++ b/api/src/Page/Sample.php
@@ -120,6 +120,8 @@ class Sample extends Page
'BEAMLINENAME' => '[\w\-]+',
'SOURCE' => '[\w\-]+',
+ 'assigned' => '[\w\-]+',
+ 'unassigned' => '[\w\-]+',
'queued' => '\d',
'UNQUEUE' => '\d',
'nodata' => '\d',
@@ -1145,6 +1147,16 @@ function _samples()
array_push($args, $sessionid);
}
+ if ($this->has_arg('assigned')) {
+ $where .= " AND d.dewarstatus LIKE 'processing' AND b.isinsamplechanger > 0 AND c.beamlinelocation LIKE :" . (sizeof($args) + 1);
+ array_push($args, $this->arg('assigned'));
+ }
+
+ if ($this->has_arg('unassigned')) {
+ $where .= " AND b.isinsamplechanger is null AND c.beamlinelocation=:" . (sizeof($args) + 1);
+ array_push($args, $this->arg('unassigned'));
+ }
+
// Search
if ($this->has_arg('s')) {
$st = sizeof($args) + 1;
@@ -1219,7 +1231,7 @@ function _samples()
, TO_CHAR(cq.createdtimestamp, 'DD-MM-YYYY HH24:MI') as queuedtimestamp, b.smiles
, $cseq $sseq string_agg(cpr.name) as componentnames, string_agg(cpr.density) as componentdensities
, string_agg(cpr.proteinid) as componentids, string_agg(cpr.acronym) as componentacronyms, string_agg(cpr.global) as componentglobals, string_agg(chc.abundance) as componentamounts, string_agg(ct.symbol) as componenttypesymbols, b.volume, pct.symbol,ROUND(cr.abundance,3) as abundance, TO_CHAR(b.recordtimestamp, 'DD-MM-YYYY') as recordtimestamp, dp.radiationsensitivity, dp.energy, dp.userpath, dp.strategyoption, dp.minimalresolution as minimumresolution
- , count(distinct dc.dataCollectionId) as dcc
+ , count(distinct dc.dataCollectionId) as dcc, b.isinsamplechanger
FROM blsample b
diff --git a/client/src/css/partials/_content.scss b/client/src/css/partials/_content.scss
index b1d6b8bd6..8eef90377 100644
--- a/client/src/css/partials/_content.scss
+++ b/client/src/css/partials/_content.scss
@@ -790,6 +790,10 @@ li:last-child .visit_users {
display: none;
overflow: auto;
+ .larger {
+ font-size: 14px;
+ }
+
.dcap {
padding: 1% 1% 0 1%;
@@ -895,6 +899,10 @@ li:last-child .visit_users {
}
}
+ &.align_center td {
+ text-align: center;
+ }
+
}
@@ -997,7 +1005,7 @@ li:last-child .visit_users {
height: auto;
}
- .plot_dimple {
+ .plot_dimple, .plot_anode {
width: 70%;
float: right;
diff --git a/client/src/js/config_sample.json b/client/src/js/config_sample.json
index cc71a60f8..2518bf926 100644
--- a/client/src/js/config_sample.json
+++ b/client/src/js/config_sample.json
@@ -6,12 +6,7 @@
"production": false,
"pucks": {
- "i02": 10,
- "i03": 23,
- "i04": 37,
- "i04-1": 9,
- "i24": 9,
- "i23": 4
+ "moved to": "config.php"
},
"_gsMajorAxisOrientation" : "Determines whether the major grid scan axis determines the orientation of the view",
diff --git a/client/src/js/modules/assign/views/assign.js b/client/src/js/modules/assign/views/assign.js
index 97cc77e8e..c613fd0c2 100644
--- a/client/src/js/modules/assign/views/assign.js
+++ b/client/src/js/modules/assign/views/assign.js
@@ -2,8 +2,10 @@ define(['marionette', 'backbone', 'views/pages',
'collections/shipments',
'collections/containers',
'collections/dewars',
+ 'collections/samples',
'models/shipment',
'models/dewar',
+ 'models/container',
'modules/assign/collections/pucknames',
'utils',
@@ -15,8 +17,10 @@ define(['marionette', 'backbone', 'views/pages',
Shipments,
Containers,
Dewars,
+ Samples,
Shipment,
Dewar,
+ Container,
PuckNames,
utils,
@@ -46,15 +50,13 @@ define(['marionette', 'backbone', 'views/pages',
'drop:unassign': 'unassignContainer',
},
- // possible circular reference
- onDestroy: function() {
- this.model.view = null
- },
-
-
// Assign Containers
assignContainer: function(e, options) {
console.log('confirm container on to', options.id, this.model)
+ if (options.id == this.model.get("SAMPLECHANGERLOCATION")) {
+ // already assigned in this location
+ return
+ }
staffOnly = false
const onlyStaffCanAssign = app.options.get('only_staff_can_assign') || {}
if (options.bl in onlyStaffCanAssign) {
@@ -63,6 +65,7 @@ define(['marionette', 'backbone', 'views/pages',
if (staffOnly && !app.staff) {
app.alert({ message: 'Only staff are able to assign containers on '+options.bl })
} else {
+ options.shipments = this.getOption('shipments')
utils.confirm({
title: 'Confirm Container Assignment',
content: 'Are you sure you want to assign "'+this.model.get('NAME')+'" to sample changer position '+options.id+'?',
@@ -153,9 +156,131 @@ define(['marionette', 'backbone', 'views/pages',
},
})
-
-
-
+
+
+ var SampleView = Marionette.CompositeView.extend({
+ template: _.template(' View Sample
<%-NAME%>
'),
+ className: function() { return 'container' + (this.getOption('assigned') ? ' assigned' : '') },
+
+ initialize: function(options) {
+ this.getOption('model').view = this
+ },
+
+ onRender: function() {
+ this.$el.draggable({
+ containment: '#drag_container',
+ stack: '#unassigned div',
+ revert: true
+ })
+ },
+
+ events: {
+ 'drop:assign': 'assignSample',
+ 'drop:unassign': 'unassignSample',
+ },
+
+ // Assign Samples
+ assignSample: function(e, options) {
+ console.log('confirm sample on to', options.id, this.model)
+ if (options.id == this.model.get("ISINSAMPLECHANGER")) {
+ // already assigned in this location
+ return
+ }
+ staffOnly = false
+ const onlyStaffCanAssign = app.options.get('only_staff_can_assign') || {}
+ if (options.bl in onlyStaffCanAssign) {
+ staffOnly = onlyStaffCanAssign[options.bl]
+ }
+ if (staffOnly && !app.staff) {
+ app.alert({ message: 'Only staff are able to assign samples on '+options.bl })
+ } else {
+ options.shipments = this.getOption('shipments')
+ utils.confirm({
+ title: 'Confirm Sample Assignment',
+ content: 'Are you sure you want to assign "'+this.model.get('NAME')+'" to sample changer position '+options.id+'?',
+ callback: this.doAssign.bind(this, options)
+ })
+ }
+ },
+
+ doAssign: function(options) {
+ console.log('dropped sample on to', options.id, this.model, options.assigned)
+ var assigned = options.assigned.where({ ISINSAMPLECHANGER: options.id.toString() })
+ _.each(assigned, function(c) {
+ c.view.doUnAssign.call(c.view,options)
+ })
+
+ Backbone.ajax({
+ url: app.apiurl+'/assign/assign',
+ data: { visit: options.visit, sid: this.model.get('BLSAMPLEID'), pos: options.id },
+ success: this.assignUpdateGUI.bind(this, options),
+ error: function(xhr, message, options) {
+ try {
+ json = JSON.parse(xhr.responseText)
+ app.alert({ message: json.message })
+ } catch {
+ app.alert({ message: 'Something went wrong assigning this sample.' })
+ }
+ },
+ })
+ },
+
+ assignUpdateGUI: function(options) {
+ this.trigger('remove:container', this.model)
+ this.model.set({ ISINSAMPLECHANGER: options.id.toString() })
+ options.assigned.add(this.model)
+ },
+
+ // Unassign Samples
+ unassignSample: function(e, options) {
+ console.log('unassign sample', this.model)
+ staffOnly = false
+ const onlyStaffCanAssign = app.options.get('only_staff_can_assign') || {}
+ if (options.bl in onlyStaffCanAssign) {
+ staffOnly = onlyStaffCanAssign[options.bl]
+ }
+ if (staffOnly && !app.staff) {
+ app.alert({ message: 'Only staff are able to unassign samples on '+options.bl })
+ } else {
+ utils.confirm({
+ title: 'Confirm Sample Unassignment',
+ content: 'Are you sure you want to unassign "'+this.model.get('NAME')+'" from sample changer position '+this.model.get('ISINSAMPLECHANGER')+'?',
+ callback: this.doUnAssign.bind(this, options)
+ })
+ }
+ },
+
+ doUnAssign: function(options) {
+ console.log('unassigning', this.model)
+ Backbone.ajax({
+ url: app.apiurl+'/assign/unassign',
+ data: { visit: options.visit, sid: this.model.get('BLSAMPLEID') },
+ success: this.unassignUpdateGUI.bind(this, options),
+ error: function(xhr, message, options) {
+ try {
+ json = JSON.parse(xhr.responseText)
+ app.alert({ message: json.message })
+ } catch {
+ app.alert({ message: 'Something went wrong unassigning this sample.' })
+ }
+ },
+ })
+ },
+
+ unassignUpdateGUI: function(options) {
+ this.model.set({ ISINSAMPLECHANGER: null })
+ this.trigger('remove:container', this.model)
+ var shipments = _.uniq(options.shipments.pluck('SHIPPINGID'))
+ if (shipments.indexOf(this.model.get('SHIPPINGID')) > -1) {
+ var s = options.shipments.findWhere({ SHIPPINGID: this.model.get('SHIPPINGID') })
+ var d = s.get('DEWARS').findWhere({ CONTAINERID: this.model.get('CONTAINERID') })
+ if (d) d.get('CONTAINERS').add(this.model)
+ console.log('add sample to dewar')
+ }
+ },
+ })
+
+
// List of Dewars in Shipment
var DewarView = Marionette.CompositeView.extend({
template: _.template(''),
@@ -165,8 +290,17 @@ define(['marionette', 'backbone', 'views/pages',
return classes
},
-
- childView: ContainerView,
+
+ getChildView: function(model) {
+ return this.options.pucks > 0 ? ContainerView : SampleView;
+ },
+
+ childViewOptions: function() {
+ return {
+ shipments: this.options.shipments,
+ }
+ },
+
childEvents: {
'remove:container': 'removeContainer',
},
@@ -213,6 +347,12 @@ define(['marionette', 'backbone', 'views/pages',
var ShipmentView = Marionette.CompositeView.extend({
template: _.template('<%-SHIPPINGNAME%>
'),
childView: DewarView,
+ childViewOptions: function() {
+ return {
+ pucks: this.getOption('pucks'),
+ shipments: this.getOption('shipments'),
+ }
+ },
className: 'shipment',
initialize: function(options) {
@@ -228,8 +368,11 @@ define(['marionette', 'backbone', 'views/pages',
template: _.template('<%-id%> '),
childView: ContainerView,
- childViewOptions: {
- assigned: true,
+ childViewOptions: function() {
+ return {
+ assigned: true,
+ shipments: this.getOption('shipments')
+ }
},
childViewContainer: '.ac',
@@ -296,6 +439,67 @@ define(['marionette', 'backbone', 'views/pages',
}
})
+
+ // Sample Changer Positions
+ var PositionSampleView = Marionette.CompositeView.extend({
+ className:'bl_puck',
+ template: _.template('<%-id%> '),
+
+ childView: SampleView,
+ childViewOptions: function() {
+ return {
+ assigned: true,
+ shipments: this.getOption('shipments')
+ }
+ },
+ childViewContainer: '.ac',
+
+ childEvents: {
+ 'remove:container': 'removeContainer',
+ },
+
+ ui: {
+ name: '.name',
+ },
+
+ removeContainer: function(child, model) {
+ console.log('remove sample position', model)
+ this.collection.remove(model)
+ this.render()
+ },
+
+ collectionEvents: {
+ 'change reset': 'render',
+ },
+
+ events: {
+ 'drop': 'handleDrop',
+ },
+
+ initialize: function(options) {
+ this.collection = new Containers()
+ this.assigned = options.assigned
+ this.bl = options.bl
+ this.listenTo(this.assigned, 'change sync reset add remove', this.updateCollection, this)
+ this.updateCollection()
+ },
+
+ updateCollection: function() {
+ this.collection.reset(this.assigned.findWhere({ ISINSAMPLECHANGER: this.model.get('id').toString() }))
+ },
+
+ onRender: function() {
+ this.$el.attr('id', 'blpos'+this.model.get('id'))
+ this.$el.droppable({
+ accept: '.container',
+ hoverClass: 'bl_puck_drag',
+ })
+ },
+
+ handleDrop: function(e, ui) {
+ ui.draggable.trigger('drop:assign', { id: this.model.get('id'), assigned: this.assigned, visit: this.getOption('visit'), bl: this.bl })
+ }
+ })
var SampleChangerView = Marionette.CollectionView.extend({
@@ -306,11 +510,24 @@ define(['marionette', 'backbone', 'views/pages',
assigned: this.getOption('assigned'),
visit: this.getOption('visit'),
bl: this.getOption('bl'),
- pucknames: this.getOption('pucknames')
+ pucknames: this.getOption('pucknames'),
+ shipments: this.getOption('shipments'),
}
}
})
+ var SampleChangerSampleView = Marionette.CollectionView.extend({
+ className: 'clearfix',
+ childView: PositionSampleView,
+ childViewOptions: function() {
+ return {
+ assigned: this.getOption('assigned'),
+ visit: this.getOption('visit'),
+ bl: this.getOption('bl'),
+ shipments: this.getOption('shipments'),
+ }
+ }
+ })
return Marionette.CompositeView.extend({
@@ -318,7 +535,17 @@ define(['marionette', 'backbone', 'views/pages',
className: 'content',
childView: ShipmentView,
childViewContainer: '#unassigned',
+ childViewOptions: function() {
+ return {
+ pucks: this.pucks,
+ shipments: this.collection,
+ }
+ },
+ ui: {
+ pcs: '.pcs',
+ },
+
events: {
'drop #unassigned': 'handleDrop',
},
@@ -330,7 +557,6 @@ define(['marionette', 'backbone', 'views/pages',
templateHelpers: function() {
return {
VISIT: this.getOption('visit').toJSON(),
- APP_TYPE: app.type,
}
},
@@ -340,51 +566,79 @@ define(['marionette', 'backbone', 'views/pages',
},
initialize: function(options) {
+ this.pucks = 10
+ this.samples = 0
+ const bl_capacity = app.options.get('bl_capacity') || {}
+ if (this.getOption('visit').get('BL') in bl_capacity) {
+ this.pucks = bl_capacity[this.getOption('visit').get('BL')]['pucks']
+ this.samples = bl_capacity[this.getOption('visit').get('BL')]['samples']
+ }
+
this.collection = new Shipments()
-
- this.assigned = new Containers(null, { queryParams: { assigned: 1, bl: this.getOption('visit').get('BL') }, state: { pageSize: 9999 } })
+
+ if (this.pucks > 0) {
+ this.assigned = new Containers(null, { queryParams: { assigned: 1, bl: this.getOption('visit').get('BL') }, state: { pageSize: 9999 } })
+ this.containers = new Containers(null, { queryParams: { unassigned: this.getOption('visit').get('BL') }, state: { pageSize: 30, currentPage: options.page } })
+ } else {
+ this.assigned = new Samples(null, { queryParams: { assigned: this.getOption('visit').get('BL') }, state: { pageSize: 9999 } })
+ this.containers = new Samples(null, { queryParams: { unassigned: this.getOption('visit').get('BL') }, state: { pageSize: 30, currentPage: options.page } })
+ }
this.assigned.fetch()
-
- this.containers = new Containers(null, { queryParams: { unassigned: this.getOption('visit').get('BL') }, state: { pageSize: 30, currentPage: options.page } })
- var self = this
- this.containers.fetch().done(function() {
- console.log(self.containers)
- })
+ this.containers.fetch()
+
this.listenTo(this.containers, 'sync', this.generateShipments, this)
this.paginator = new Pages({ collection: this.containers })
- this.pucknames = new PuckNames()
- this.pucknames.state.pageSize = 100
- this.pucknames.queryParams.bl = this.getOption('visit').get('BL')
- this.pucknames.fetch()
+ if (this.pucks > 0) {
+ this.pucknames = new PuckNames()
+ this.pucknames.state.pageSize = 100
+ this.pucknames.queryParams.bl = this.getOption('visit').get('BL')
+ this.pucknames.fetch()
+ }
this.bl = this.getOption('visit').get('BL')
},
-
+
generateShipments: function() {
console.log('generate shipments')
- var sids = _.uniq(this.containers.pluck('SHIPPINGID'))
- var shipments = []
+ let sids = _.uniq(this.containers.pluck('SHIPPINGID'))
+ let shipments = []
_.each(sids, function(sid) {
- var conts = new Containers(this.containers.where({ SHIPPINGID: sid }))
-
- var dids = _.uniq(conts.pluck('DEWARID'))
- var dewars = new Dewars()
- _.each(dids, function(did) {
- var d = conts.findWhere({ DEWARID: did })
- var dewar = new Dewar({
- DEWARID: did,
- CODE: d.get('DEWAR'),
- DEWARSTATUS: d.get('DEWARSTATUS'),
- CONTAINERS: new Containers(conts.where({ DEWARID: did }))
- })
- dewars.add(dewar)
- }, this)
+ let conts, items;
+
+ if (this.pucks > 0) {
+ conts = new Containers(this.containers.where({ SHIPPINGID: sid }))
+ let dids = _.uniq(conts.pluck('DEWARID'))
+ items = new Dewars()
+ _.each(dids, function(did) {
+ let d = conts.findWhere({ DEWARID: did })
+ let dewar = new Dewar({
+ DEWARID: did,
+ CODE: d.get('DEWAR'),
+ DEWARSTATUS: d.get('DEWARSTATUS'),
+ CONTAINERS: new Containers(conts.where({ DEWARID: did }))
+ })
+ items.add(dewar)
+ }, this)
+ } else {
+ conts = new Samples(this.containers.where({ SHIPPINGID: sid }))
+ let cids = _.uniq(conts.pluck('CONTAINERID'))
+ items = new Containers()
+ _.each(cids, function(cid) {
+ let c = conts.findWhere({ CONTAINERID: cid })
+ let container = new Container({
+ CONTAINERID: cid,
+ CODE: c.get('CONTAINER'),
+ CONTAINERS: new Samples(conts.where({ CONTAINERID: cid }))
+ })
+ items.add(container)
+ }, this)
+ }
- var shipment = new Shipment({
+ let shipment = new Shipment({
SHIPPINGID: sid,
SHIPPINGNAME: conts.at(0).get('SHIPMENT'),
- DEWARS: dewars,
+ DEWARS: items,
})
shipments.push(shipment)
}, this)
@@ -393,9 +647,10 @@ define(['marionette', 'backbone', 'views/pages',
// This means that there is no ability to unassign containers. Fix: add a dummy shipment here.
// Dragging a container to a shipment does not associate the container with that shipment - it will still be in the original shipment.
if (shipments.length == 0) {
- var unassignShipment = new Shipment({
+ let unassignText = this.pucks > 0 ? 'Drag a container here to unassign' : 'Drag a sample here to unassign'
+ let unassignShipment = new Shipment({
SHIPPINGID: 0,
- SHIPPINGNAME: 'Drag Container here to unassign',
+ SHIPPINGNAME: unassignText,
})
shipments.push(unassignShipment)
}
@@ -404,32 +659,48 @@ define(['marionette', 'backbone', 'views/pages',
onShow: function() {
- var pucks = 10
- if (this.getOption('visit').get('BL') in app.config.pucks) {
- pucks = app.config.pucks[this.getOption('visit').get('BL')]
+ var positions
+ if (this.pucks > 0) {
+ positions = new Backbone.Collection(_.map(_.range(1,this.pucks+1), function(i) { return { id: i } }))
+ this.scview = new SampleChangerView({
+ collection: positions,
+ assigned: this.assigned,
+ visit: this.getOption('visit').get('VISIT'),
+ bl: this.bl,
+ shipments: this.collection,
+ pucknames: this.pucknames,
+ })
+ } else {
+ positions = new Backbone.Collection(_.map(_.range(1,this.samples+1), function(i) { return { id: i } }))
+ this.scview = new SampleChangerSampleView({
+ collection: positions,
+ assigned: this.assigned,
+ visit: this.getOption('visit').get('VISIT'),
+ bl: this.bl,
+ shipments: this.collection,
+ })
}
- var positions = new Backbone.Collection(_.map(_.range(1,pucks+1), function(i) { return { id: i } }))
- this.scview = new SampleChangerView({
- collection: positions,
- assigned: this.assigned,
- visit: this.getOption('visit').get('VISIT'),
- bl: this.bl,
- shipments: this.collection,
- pucknames: this.pucknames,
- })
this.$el.find('#assigned').append(this.scview.render().$el)
this.$el.find('.page_wrap').append(this.paginator.render().$el)
-
+
this.$el.find('#unassigned').droppable({
accept: '.bl_puck .ac div',
hoverClass: 'unassigned_drag',
})
+
+ if (app.type == 'xpdf') {
+ this.ui.pcs.text('Puck')
+ } else if (this.pucks > 0) {
+ this.ui.pcs.text('Container')
+ } else {
+ this.ui.pcs.text('Sample')
+ }
},
onDestroy: function() {
if (this.scview) this.scview.destroy()
- this.pucknames.stop()
+ if (this.pucknames) this.pucknames.stop()
// hmm no destroy?
//if (this.paginator) this.paginator.destroy()
},
diff --git a/client/src/js/modules/dc/datacollections.js b/client/src/js/modules/dc/datacollections.js
index 52b9e1b60..b062b08f9 100644
--- a/client/src/js/modules/dc/datacollections.js
+++ b/client/src/js/modules/dc/datacollections.js
@@ -114,11 +114,18 @@ function(Marionette, Pages, DCListView,
IS_DCG: !(!this.getOption('params').dcg),
IS_PJ: !(!this.getOption('params').pjid),
IS_STAFF: app.staff,
+ CONTAINERS: this.containers,
IS_ARCHIVED: app.options.get('prop_codes_data_deleted').some(code => app.prop.includes(code)) ? "deleted" : "archived",
}
},
initialize: function(options) {
+ this.containers = 'Containers'
+ const bl_capacity = app.options.get('bl_capacity') || {}
+ if (this.model && this.model.get('BL') in bl_capacity && bl_capacity[this.model.get('BL')]['pucks'] === 0) {
+ this.containers = 'Samples'
+ }
+
if (this.model && this.model.get('ACTIVE') != "1") {
var vis = this.getOption('params').visit
if (vis) {
diff --git a/client/src/js/modules/dc/views/dimple.js b/client/src/js/modules/dc/views/dimple.js
index 02aadb01a..0c156229a 100644
--- a/client/src/js/modules/dc/views/dimple.js
+++ b/client/src/js/modules/dc/views/dimple.js
@@ -8,7 +8,9 @@ define([
ui: {
plot: '.plot_dimple',
+ plot_anode: '.plot_anode',
rstats: '.rstats',
+ rstats_div: '.rstats_div',
blob: '.blobs img',
blobs: '.blobs',
},
@@ -39,9 +41,10 @@ define([
if (app.mobile()) {
this.ui.plot.width(0.93*(this.options.holderWidth-14))
} else {
- this.ui.rstats.width(0.20*(this.options.holderWidth-14))
- this.ui.plot.width(0.47*(this.options.holderWidth-14))
+ this.ui.rstats.width(0.25*(this.options.holderWidth-14))
+ this.ui.plot.width(0.42*(this.options.holderWidth-14))
this.ui.plot.height(this.ui.plot.width()*0.41-80)
+ this.ui.rstats_div.height(this.ui.plot.width()*0.41-80)
}
this.ui.blobs.css('min-height', this.ui.plot.width()*0.41-80)
@@ -51,8 +54,18 @@ define([
var pl = $.extend({}, utils.default_plot, { series: { lines: { show: true }}})
$.plot(this.ui.plot, data, pl)
+ const anodePeaks = this.model.get('ANODE_PEAKS');
+ if (anodePeaks && anodePeaks.TABLE && anodePeaks.TABLE.length > 0) {
+ this.ui.plot_anode.width(0.42 * (this.options.holderWidth - 14))
+ this.ui.plot_anode.height(this.ui.plot.width() * 0.41 - 80)
+
+ var anode_data = [{ data: anodePeaks.PLOT, label: 'Peak Height (sig)' }]
+ var anode_pl = $.extend({}, utils.default_plot, { series: { lines: { show: true }}});
+ $.plot(this.ui.plot_anode, anode_data, anode_pl)
+ }
+
},
-
+
})
-})
\ No newline at end of file
+})
diff --git a/client/src/js/modules/dc/views/samplechanger.js b/client/src/js/modules/dc/views/samplechanger.js
index 2ab1e9fd3..a7072022d 100644
--- a/client/src/js/modules/dc/views/samplechanger.js
+++ b/client/src/js/modules/dc/views/samplechanger.js
@@ -59,8 +59,9 @@ define(['marionette', 'utils/canvas', 'utils',
this.listenTo(this.collection, 'change', this.drawStatus, this)
this.ready = this.collection.fetch()
- if (options.bl in app.config.pucks) {
- this.positions = app.config.pucks[options.bl]
+ const bl_capacity = app.options.get('bl_capacity') || {}
+ if (options.bl in bl_capacity) {
+ this.positions = bl_capacity[options.bl]['pucks']
} else this.positions = 10
this.sc = 16
diff --git a/client/src/js/modules/dc/views/samplechangerfull.js b/client/src/js/modules/dc/views/samplechangerfull.js
index 60a5b0907..ec156a7bc 100644
--- a/client/src/js/modules/dc/views/samplechangerfull.js
+++ b/client/src/js/modules/dc/views/samplechangerfull.js
@@ -21,8 +21,9 @@ define(['marionette',
},
onRender: function() {
- var bl = this.getOption('bl')
- var large = bl in app.config.pucks && app.config.pucks[bl] > 10
+ const bl = this.getOption('bl')
+ const bl_capacity = app.options.get('bl_capacity') || {}
+ const large = bl in bl_capacity && bl_capacity[bl]['pucks'] > 10
console.log('sc large', large)
if (!app.mobile() && !large) {
this.$el.find('.left').css('width', '25%')
@@ -46,4 +47,4 @@ define(['marionette',
-})
\ No newline at end of file
+})
diff --git a/client/src/js/modules/shipment/models/platetype.js b/client/src/js/modules/shipment/models/platetype.js
index 06396dec5..1f79bbe5e 100644
--- a/client/src/js/modules/shipment/models/platetype.js
+++ b/client/src/js/modules/shipment/models/platetype.js
@@ -47,8 +47,8 @@ define(['backbone'], function(Backbone) {
this.set('drop_widthpx', (this.get('well_width')-this.get('drop_pad')*2) / (this.get('drop_per_well_x') / this.get('drop_width')))
this.set('drop_heightpx', (this.get('well_height')-this.get('drop_pad')*2) / (this.get('drop_per_well_y') / this.get('drop_height')))
- this.set('drop_offset_x', this.get('drop_offset_x')*(this.get('well_width')-this.get('drop_pad')*2))
- this.set('drop_offset_y', this.get('drop_offset_y')*(this.get('well_height')-this.get('drop_pad')*2))
+ this.set('drop_offset_x_px', this.get('drop_offset_x')*(this.get('well_width')-this.get('drop_pad')*2))
+ this.set('drop_offset_y_px', this.get('drop_offset_y')*(this.get('well_height')-this.get('drop_pad')*2))
},
setGeometry: function(width, height, ofx, ofy) {
diff --git a/client/src/js/modules/shipment/views/containerplate.js b/client/src/js/modules/shipment/views/containerplate.js
index 87980a4c4..b01c6c898 100644
--- a/client/src/js/modules/shipment/views/containerplate.js
+++ b/client/src/js/modules/shipment/views/containerplate.js
@@ -924,7 +924,9 @@ define(['marionette',
doOnShow: function() {
this.ui.ins.html(this.inspections.opts())
- this.type = this.ctypes.findWhere({ name: this.model.get('CONTAINERTYPE') })
+ this.type = this.ctypes.find(m =>
+ m.get('name').toLowerCase() === this.model.get('CONTAINERTYPE').toLowerCase()
+ )
this.plateView = new PlateView({ collection: this.samples, type: this.type, showImageStatus: this.model.get('INSPECTIONS') > 0 })
this.listenTo(this.plateView, 'plate:select', this.resetZoom, this)
this.plate.show(this.plateView)
diff --git a/client/src/js/modules/shipment/views/plate.js b/client/src/js/modules/shipment/views/plate.js
index ca2013adb..a37c5a0d0 100644
--- a/client/src/js/modules/shipment/views/plate.js
+++ b/client/src/js/modules/shipment/views/plate.js
@@ -215,7 +215,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
} else this.ctx.strokeStyle = '#ddd'
- this.ctx.rect(this.pt.get('drop_offset_x')+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')), this.pt.get('drop_widthpx'), this.pt.get('drop_heightpx'))
+ this.ctx.rect(this.pt.get('drop_offset_x_px')+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y_px')+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')), this.pt.get('drop_widthpx'), this.pt.get('drop_heightpx'))
// Highlight Hovered Sample
@@ -319,7 +319,7 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
this.ctx.fillStyle = '#000'
this.ctx.font = "8px Arial"
this.ctx.lineWidth = 1
- this.ctx.fillText(sampleid,this.pt.get('drop_offset_x')+2+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y')+10+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')));
+ this.ctx.fillText(sampleid,this.pt.get('drop_offset_x_px')+2+this.pt.get('offset_x')+row*(this.pt.get('well_width')+this.pt.get('well_pad'))+(j*this.pt.get('drop_widthpx')+this.pt.get('drop_pad')), this.pt.get('drop_offset_y_px')+10+this.pt.get('offset_y')+col*(this.pt.get('well_height')+this.pt.get('well_pad'))+(k*this.pt.get('drop_heightpx')+this.pt.get('drop_pad')));
}
}
}
@@ -333,8 +333,8 @@ define(['marionette', 'backbone', 'utils', 'backbone-validation'], function(Mari
var x = Math.floor((cur[0] - this.pt.get('offset_x'))/(this.pt.get('well_width')+this.pt.get('well_pad')))
var y = Math.floor((cur[1] - this.pt.get('offset_y'))/(this.pt.get('well_height')+this.pt.get('well_pad')))
- var wox = cur[0] - this.pt.get('drop_offset_x') - this.pt.get('offset_x') - this.pt.get('drop_pad') - x*(this.pt.get('well_width')+this.pt.get('well_pad'))
- var woy = cur[1] - this.pt.get('drop_offset_y') - this.pt.get('offset_y') - this.pt.get('drop_pad') - y*(this.pt.get('well_height')+this.pt.get('well_pad'))
+ var wox = cur[0] - this.pt.get('drop_offset_x_px') - this.pt.get('offset_x') - this.pt.get('drop_pad') - x*(this.pt.get('well_width')+this.pt.get('well_pad'))
+ var woy = cur[1] - this.pt.get('drop_offset_y_px') - this.pt.get('offset_y') - this.pt.get('drop_pad') - y*(this.pt.get('well_height')+this.pt.get('well_pad'))
if (wox > 0 && wox < this.pt.get('drop_per_well_x')*this.pt.get('drop_widthpx') && woy > 0 && woy < this.pt.get('drop_per_well_y')*this.pt.get('drop_heightpx')) {
var dx = Math.floor(wox / this.pt.get('drop_widthpx'))
diff --git a/client/src/js/templates/assign/assign.html b/client/src/js/templates/assign/assign.html
index 4746eec06..7b7dabb6e 100644
--- a/client/src/js/templates/assign/assign.html
+++ b/client/src/js/templates/assign/assign.html
@@ -1,7 +1,7 @@
-<% if (APP_TYPE == 'xpdf') { %>Puck<% } else { %>Container<% } %> Allocation for <%-VISIT.VISIT%> on <%-VISIT.BL%> at <%-VISIT.ST%>
+ Allocation for <%-VISIT.VISIT%> on <%-VISIT.BL%> at <%-VISIT.ST%>
-This page allows you to allocate samples from ISPyB to the beamline sample changer. Drag and drop <% if (APP_TYPE == 'xpdf') { %>pucks<% } else { %>containers<% } %> on to the locations on the beamline. Shipments and Dewars can be expanded by clicking on their titles
-Uassign <% if (APP_TYPE == 'xpdf') { %>pucks<% } else { %>containers<% } %> by dragging them to any shipment listed under "Unassigned <% if (APP_TYPE == 'xpdf') { %>Pucks<% } else { %>Containers<% } %>". The <% if (APP_TYPE == 'xpdf') { %>puck<% } else { %>container<% } %> will still belong to its original shipment.
+This page allows you to allocate samples from ISPyB to the beamline sample changer. Drag and drop s on to the locations on the beamline. Shipments and Dewars can be expanded by clicking on their titles
+Uassign s by dragging them to any shipment listed under "Unassigned s". The will still belong to its original shipment.
Data Collections
@@ -10,13 +10,13 @@
<% if (APP_TYPE == 'xpdf') { %>Puck<% } else { %>Container<% } %> Allocation
-
Assigned <% if (APP_TYPE == 'xpdf') { %>Pucks<% } else { %>Containers<% } %>: Sample Changer
+
Assigned s: <%-VISIT.BL.toUpperCase()%> Sample Changer
-
-
Unassigned <% if (APP_TYPE == 'xpdf') { %>Pucks<% } else { %>Containers<% } %>
+
+
Unassigned s
diff --git a/client/src/js/templates/dc/dc_dimple.html b/client/src/js/templates/dc/dc_dimple.html
index e21f9414d..1fd80df41 100644
--- a/client/src/js/templates/dc/dc_dimple.html
+++ b/client/src/js/templates/dc/dc_dimple.html
@@ -12,23 +12,50 @@
-
- <% if (STATS.length) { %>
- <% _.each(STATS, function(r, i) { %>
+
+
+ <% if (STATS.length) { %>
+ <% _.each(STATS, function(r, i) { %>
+
+ <% _.each(r, function(j) { %>
+ | <%-j%> |
+ <% }) %>
+
+ <% }) %>
+ <% } else { %>
+
+ | Refinement Stats |
+
+
+ | No Stats Available |
+
+ <% } %>
+
+
+
+
+
+ <% if (ANODE_PEAKS && ANODE_PEAKS.TABLE && ANODE_PEAKS.TABLE.length) { %>
+
+
Top 10 Anode Peaks
+
+
+ | X |
+ Y |
+ Z |
+ Height (sig) |
+ SOF |
+ Nearest Atom |
+
+ <% _.each(ANODE_PEAKS.TABLE, function(r, i) { %>
<% _.each(r, function(j) { %>
| <%-j%> |
<% }) %>
<% }) %>
- <% } else { %>
-
- | Refinement Stats |
-
-
- | No Stats Available |
-
- <% } %>
-
-
+
+ <% } else { %>
+
No Anode peaks found
+ <% } %>
diff --git a/client/src/js/templates/dc/dclist.html b/client/src/js/templates/dc/dclist.html
index c5f7a1f69..3375820f4 100644
--- a/client/src/js/templates/dc/dclist.html
+++ b/client/src/js/templates/dc/dclist.html
@@ -22,7 +22,7 @@
<% } %>
-
Assign Containers
+
Assign <%-CONTAINERS%>
Summary
Auto Processing
Visit Stats
diff --git a/client/src/js/utils/xhrimage.js b/client/src/js/utils/xhrimage.js
index 63ca0244d..5fc90862d 100644
--- a/client/src/js/utils/xhrimage.js
+++ b/client/src/js/utils/xhrimage.js
@@ -33,7 +33,11 @@ define(['marionette'], function() {
xhr.onload = function(e) {
if (xhr.status == 0 || xhr.status != 200) {
- self.onerror(xhr.status, e)
+ if (typeof self.onerror === 'function') {
+ self.onerror(xhr.status, e)
+ } else {
+ console.error('Image load error:', xhr.status, e)
+ }
return
}