Skip to content

Commit

Permalink
Merge pre-release/2025-R1.1 into master (#899)
Browse files Browse the repository at this point in the history
* LIMS-1540 - Remove references to summary pages/DB (#860)

* LIMS-1564 - Remove unused dependencies (#868)

* LIMS-1066: Autofill UDC visit on dispatch form (#881)

* LIMS-1528: Fix sorting on old summary page (#883)

* LIMS-1554: Add 'State' column to proposals list page (#865)

---------

Co-authored-by: Guilherme Francisco <[email protected]>
Co-authored-by: Mark Williams <[email protected]>
  • Loading branch information
3 people authored Jan 24, 2025
1 parent 3684b32 commit 4a10c81
Show file tree
Hide file tree
Showing 66 changed files with 443 additions and 22,743 deletions.
7 changes: 2 additions & 5 deletions api/config_sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
$isb = array('user' => 'user', 'pass' => 'pass', 'db' => 'localhost/ispyb');
$dbtype = 'mysql';

# Summary Database credentials
######### DELETE if not using connection.
$summarydbconfig = array('user' => 'user', 'pass' => 'pass', 'db' => 'localhost/ispyb');
$ifsummary = true;

# Encoded JWT key, used to sign and check validaty of jwt tokens
# - Create one of these using /api/authenticate/key
# This can be changed to invalidate all currently active tokens
Expand Down Expand Up @@ -302,6 +297,8 @@
# Beamlines on which to scale the gridplot to 1024
$scale_grid = array('i24');

# URL for instructions for closed proposals
$closed_proposal_link = '';

# These map proposal types to their proposalcode
# - If these are not defined for a proposal type, the api then uses bl_types below
Expand Down
13 changes: 3 additions & 10 deletions api/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ function setupApplication($mode): Slim
global $motd, $authentication_type, $cas_url, $cas_sso, $sso_url, $package_description,
$facility_courier_countries, $facility_courier_countries_nde, $facility_courier_countries_link,
$dhl_enable, $scale_grid, $scale_grid_end_date, $preset_proposal, $timezone,
$valid_components, $enabled_container_types, $ifsummary, $synchweb_version, $redirects,
$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;
$dials_rest_url_rings, $closed_proposal_link;
$app->contentType('application/json');
$options = $app->container['options'];
$app->response()->body(json_encode(array(
Expand All @@ -92,10 +92,10 @@ function setupApplication($mode): Slim
'timezone' => $timezone,
'valid_components' => $valid_components,
'enabled_container_types' => $enabled_container_types,
'ifsummary' => $ifsummary,
'synchweb_version' => $synchweb_version,
'shipping_service_app_url' => $use_shipping_service_redirect || $use_shipping_service_redirect_incoming_shipments ? $shipping_service_app_url : null,
'shipping_service_app_url_incoming' => $use_shipping_service_redirect_incoming_shipments ? $shipping_service_app_url : null,
'closed_proposal_link' => $closed_proposal_link,
'dials_rest_url_rings' => $dials_rest_url_rings,
'redirects' => $redirects
)));
Expand All @@ -112,13 +112,6 @@ function setupDependencyInjectionContainer($app)
return $db;
});

$app->container->singleton('dbsummary', function () use ($app): DatabaseParent {
$dbFactory = new DatabaseFactory(new DatabaseConnectionFactory());
$db = $dbFactory->get("summary");
$db->set_app($app);
return $db;
});

$app->container->singleton('authData', function () use ($app) {
return new AuthenticationData($app->container['db']);
});
Expand Down
11 changes: 0 additions & 11 deletions api/src/Database/DatabaseConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class DatabaseConnectionFactory
public function get($databaseType)
{
global $isb;
global $summarydbconfig;

if (!$databaseType) {
error_log('Database type variable, dbtype, is not specified in config.php - defaulting to MySql.');
Expand All @@ -25,16 +24,6 @@ public function get($databaseType)
$conn = new \mysqli($host, $isb['user'], $isb['pass'], $dbn, $port);
$conn->set_charset("utf8mb4");
}
elseif ($databaseType == 'PureMySQL') {
$port = array_key_exists('port', $summarydbconfig) ? $summarydbconfig['port'] : null;
if (!$port) {
$port = ini_get("mysqli.default_port");
}
list($host, $dbn) = explode('/', $summarydbconfig['db']);
$conn = new \mysqli($host, $summarydbconfig['user'], $summarydbconfig['pass'], $dbn, $port);
$conn->set_charset("utf8mb4");
}


if ($conn == null) {
Utils::returnError("Database Configuration Error", "Database connection for type '$databaseType' does not exist.");
Expand Down
1 change: 0 additions & 1 deletion api/src/Database/DatabaseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class DatabaseFactory
// Key is lower case representation of class name.
public $database_types = array(
'mysql' => ["dbClassName" =>'MySQL', "dataConnectionName" => 'MySQL'],
'summary' => ["dbClassName" =>'PureMySQL', "dataConnectionName" => 'PureMySQL']
);

function __construct($databaseConnectionFactory)
Expand Down
205 changes: 204 additions & 1 deletion api/src/Page/Processing.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class Processing extends Page {
public static $dispatch = array(
array('/:id', 'get', '_results'),
array('/visit/:visit', 'get', '_results_for_visit'),
array('/status', 'post', '_statuses'),

array('/messages/status', 'post', '_ap_message_status'),
Expand All @@ -34,7 +35,15 @@ class Processing extends Page {
'map' => '\d+',
'n' => '\d+',
'sampleGroupId' => '\d+',
'resultCount' => '\d+'
'resultCount' => '\d+',
'pipeline' => '[\w\s\+]+',
'spacegroup' => '(\w|\s|\-|\/)+',
'resolution' => '[\d\.]+',
'completeness' => '[\d\.]+',
'anomcompleteness' => '[\d\.]+',
'rmeas' => '[\d\.]+',
'cchalf' => '[\d\.]+',
'ccanom' => '[\d\.]+',
);

/**
Expand All @@ -47,6 +56,8 @@ class Processing extends Page {
0 => 3,
);

const EVTOA = 12398.4198;

function _map_status($status) {
foreach ($this->status_mapping as $state => $value) {
if ($status == $state) {
Expand Down Expand Up @@ -238,6 +249,198 @@ function _statuses() {
$this->_output($out);
}

function _results_for_visit() {
if (!($this->has_arg('visit'))) {
$this->_error('No visit specified');
}
$pattern = '/([A-z]+)(\d+)-(\d+)/';
preg_match($pattern, $this->arg('visit'), $matches);
if (!sizeof($matches))
$this->_error('No such visit');

$info = $this->db->pq("SELECT s.sessionid FROM blsession s INNER JOIN proposal p ON (p.proposalid = s.proposalid) WHERE p.proposalcode=:1 AND p.proposalnumber=:2 AND s.visit_number=:3", array($matches[1], $matches[2], $matches[3]));

if (!sizeof($info)) {
$this->_error('No such visit');
}

$args = array($info[0]['SESSIONID']);

$where = 'dc.sessionid=:1 AND dc.overlap = 0 AND dc.axisrange > 0 AND dc.numberOfImages > 150 AND app.processingstatus = 1';

if ($this->has_arg('pipeline')) {
$st = sizeof($args);
$where .= " AND app.processingprograms = :" . ($st + 1);
array_push($args, $this->arg('pipeline'));
}

if ($this->has_arg('spacegroup')) {
$st = sizeof($args);
$where .= " AND REPLACE(ap.spacegroup,' ','') = :" . ($st + 1);
array_push($args, $this->arg('spacegroup'));
}

if ($this->has_arg('resolution')) {
$st = sizeof($args);
$where .= " AND apssover.resolutionlimithigh <= :" . ($st + 1);
array_push($args, $this->arg('resolution'));
}

if ($this->has_arg('completeness')) {
$st = sizeof($args);
$where .= " AND apssover.completeness >= :" . ($st + 1);
array_push($args, $this->arg('completeness'));
}

if ($this->has_arg('anomcompleteness')) {
$st = sizeof($args);
$where .= " AND apssover.anomalousCompleteness >= :" . ($st + 1);
array_push($args, $this->arg('anomcompleteness'));
}

if ($this->has_arg('rmeas')) {
$st = sizeof($args);
$where .= " AND apssinner.rmeasalliplusiminus <= :" . ($st + 1);
array_push($args, $this->arg('rmeas'));
}

if ($this->has_arg('cchalf')) {
$st = sizeof($args);
$where .= " AND apssouter.cchalf >= :" . ($st + 1);
array_push($args, $this->arg('cchalf'));
}

if ($this->has_arg('ccanom')) {
$st = sizeof($args);
$where .= " AND apssinner.ccanomalous >= :" . ($st + 1);
array_push($args, $this->arg('ccanom'));
}

if ($this->has_arg('s')) {
$st = sizeof($args);
$where .= " AND (CONCAT(dc.imageprefix,'_',dc.datacollectionnumber) LIKE CONCAT('%',:" . ($st + 1) . ",'%') OR smp.name LIKE CONCAT('%',:" . ($st + 2) . ",'%'))";
array_push($args, $this->arg('s'));
array_push($args, $this->arg('s'));
}

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

if ($this->has_arg('page')) {
$pg = $this->arg('page') - 1;
$start = $pg * $pp;
}

$order = 'id DESC';

if ($this->has_arg('sort_by')) {
$cols = array(
'PREFIX' => 'prefix', 'SAMPLE' => 'sample',
'ENERGY' => 'energy', 'RESOLUTION' => 'resolution', 'CELL' => 'cell_a',
'RES' => 'overallrhigh', 'INNERRMEAS' => 'innerrmeas',
'COMPLETENESS' => 'overallcompleteness', 'ANOMCOMPLETENESS' => 'anomoverallcompleteness',
'INNERCCANOM' => 'innerccanom', 'OUTERCCHALF' => 'outercchalf',
'SG' => 'sg', 'PIPELINE' => 'pipeline'
);
$dir = $this->has_arg('order') ? ($this->arg('order') == 'asc' ? 'ASC' : 'DESC') : 'ASC';
if (array_key_exists($this->arg('sort_by'), $cols))
$order = $cols[$this->arg('sort_by')] . ' ' . $dir;
}

$jobs = $this->db->pq(
"SELECT dc.datacollectionid as id,
CONCAT(dc.imageprefix, '_', dc.datacollectionnumber) as prefix,
".self::EVTOA."/dc.wavelength as energy,
dc.resolution,
smp.name as sample,
smp.blsampleid,
app.processingprograms as pipeline,
app.autoprocprogramid as aid,
REPLACE(ap.spacegroup,' ','') as sg,
ap.refinedcell_a as cell_a,
ap.refinedcell_b as cell_b,
ap.refinedcell_c as cell_c,
ap.refinedcell_alpha as cell_al,
ap.refinedcell_beta as cell_be,
ap.refinedcell_gamma as cell_ga,
apssover.resolutionlimithigh as overallrhigh,
apssover.resolutionlimitlow as overallrlow,
apssinner.resolutionlimithigh as innerrhigh,
apssinner.resolutionlimitlow as innerrlow,
apssouter.resolutionlimithigh as outerrhigh,
apssouter.resolutionlimitlow as outerrlow,
apssover.completeness as overallcompleteness,
apssinner.completeness as innercompleteness,
apssouter.completeness as outercompleteness,
apssover.anomalouscompleteness as anomoverallcompleteness,
apssinner.anomalouscompleteness as anominnercompleteness,
apssouter.anomalouscompleteness as anomoutercompleteness,
apssinner.rmeasalliplusiminus as innerrmeas,
apssouter.cchalf as outercchalf,
apssinner.ccanomalous as innerccanom
FROM datacollection dc
LEFT OUTER JOIN blsample smp ON dc.blsampleid = smp.blsampleid
INNER JOIN processingjob pj ON dc.datacollectionid = pj.datacollectionid
INNER JOIN autoprocprogram app ON pj.processingjobid = app.processingjobid
INNER JOIN autoproc ap ON app.autoprocprogramid=ap.autoprocprogramid
INNER JOIN autoprocscaling aps ON ap.autoprocid = aps.autoprocid
INNER JOIN autoprocscalingstatistics apssover ON aps.autoprocscalingid = apssover.autoprocscalingid AND apssover.scalingStatisticsType='overall'
INNER JOIN autoprocscalingstatistics apssinner ON aps.autoprocscalingid = apssinner.autoprocscalingid AND apssinner.scalingStatisticsType='innerShell'
INNER JOIN autoprocscalingstatistics apssouter ON aps.autoprocscalingid = apssouter.autoprocscalingid AND apssouter.scalingStatisticsType='outerShell'
WHERE $where
ORDER BY $order",
$args
);

// Only take one processing job per data collection id
$data = array();
$dcids = array();
foreach ($jobs as $job) {
$dcid = $job['ID'];
if (!(in_array($dcid, $dcids))) {
array_push($data, $job);
array_push($dcids, $dcid);
}
}

// Strip down data to only the page needed
$tot = sizeof($data);
$data = array_slice($data, $start, $pp);

// Add classes to highlight fields in red/yellow/green
foreach ($data as &$d) {
foreach (array('OVERALL', 'INNER', 'OUTER') as $s) {
$c = $d[$s.'COMPLETENESS'];
$d[$s.'COMPLETENESSCLASS'] = $c > 95 ? 'active' : ($c > 80 ? 'minor' : 'inactive');
$c = $d['ANOM'.$s.'COMPLETENESS'];
$d['ANOM'.$s.'COMPLETENESSCLASS'] = $c > 95 ? 'active' : ($c > 80 ? 'minor' : 'inactive');
}
}

// Set number of decimal places
$nf = array(
0 => array('ENERGY'),
2 => array(
'RESOLUTION', 'INNERRMEAS', 'OUTERCCHALF', 'INNERCCANOM',
'CELL_A', 'CELL_B', 'CELL_C', 'CELL_AL', 'CELL_BE', 'CELL_GA',
'OVERALLRHIGH', 'OVERALLRLOW', 'INNERRHIGH', 'INNERRLOW', 'OUTERRHIGH', 'OUTERRLOW',
'OVERALLCOMPLETENESS', 'INNERCOMPLETENESS', 'OUTERCOMPLETENESS',
'ANOMOVERALLCOMPLETENESS', 'ANOMINNERCOMPLETENESS', 'ANOMOUTERCOMPLETENESS'
)
);

foreach ($nf as $nff => $cols) {
foreach ($cols as $c) {
foreach ($data as &$d) {
$d[$c] = number_format($d[$c], $nff);
}
}
}

$this->_output(array('total' => $tot, 'data' => $data));

}

/**
* Auto processing results
* (Integration results only)
Expand Down
2 changes: 1 addition & 1 deletion api/src/Page/Proposal.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function _get_proposals($id = null)
$order = 'p.proposalid DESC';

if ($this->has_arg('sort_by')) {
$cols = array('ST' => 'p.bltimestamp', 'PROPOSALCODE' => 'p.proposalcode', 'PROPOSALNUMBER' => 'p.proposalnumber', 'VCOUNT' => 'vcount', 'TITLE' => 'lower(p.title)');
$cols = array('ST' => 'p.bltimestamp', 'PROPOSALCODE' => 'p.proposalcode', 'PROPOSALNUMBER' => 'p.proposalnumber', 'VCOUNT' => 'vcount', 'TITLE' => 'lower(p.title)', 'STATE' => 'p.state');
$dir = $this->has_arg('order') ? ($this->arg('order') == 'asc' ? 'ASC' : 'DESC') : 'ASC';
if (array_key_exists($this->arg('sort_by'), $cols))
$order = $cols[$this->arg('sort_by')] . ' ' . $dir;
Expand Down
24 changes: 18 additions & 6 deletions api/src/Page/Shipment.php
Original file line number Diff line number Diff line change
Expand Up @@ -1642,12 +1642,24 @@ function _get_dewars()
$order = $cols[$this->arg('sort_by')] . ' ' . $dir;
}

$dewars = $this->db->paginate("SELECT CONCAT(p.proposalcode, p.proposalnumber) as prop, CONCAT(p.proposalcode, p.proposalnumber, '-', se.visit_number) as firstexperiment, r.labcontactid, se.beamlineoperator as localcontact, se.beamlinename, TO_CHAR(se.startdate, 'HH24:MI DD-MM-YYYY') as firstexperimentst, d.firstexperimentid, s.shippingid, s.shippingname, d.facilitycode, count(c.containerid) as ccount, (case when se.visit_number > 0 then (CONCAT(p.proposalcode, p.proposalnumber, '-', se.visit_number)) else '' end) as exp, d.code, d.barcode, d.storagelocation, d.dewarstatus, d.dewarid, d.trackingnumbertosynchrotron, d.trackingnumberfromsynchrotron, d.externalShippingIdFromSynchrotron, s.deliveryagent_agentname, d.weight, d.deliveryagent_barcode, GROUP_CONCAT(c.code SEPARATOR ', ') as containers, s.sendinglabcontactid, s.returnlabcontactid, pe.givenname, pe.familyname, s.safetylevel as shippingsafetylevel
FROM dewar d
LEFT OUTER JOIN container c ON c.dewarid = d.dewarid
INNER JOIN shipping s ON d.shippingid = s.shippingid
INNER JOIN proposal p ON p.proposalid = s.proposalid
LEFT OUTER JOIN blsession se ON d.firstexperimentid = se.sessionid
$dewars = $this->db->paginate("SELECT
CONCAT(p.proposalcode, p.proposalnumber) as prop,
CONCAT(p.proposalcode, p.proposalnumber, '-', se.visit_number) as firstexperiment,
CONCAT(p.proposalcode, p.proposalnumber, '-', se2.visit_number) as udcfirstexperiment,
r.labcontactid, se.beamlineoperator as localcontact, se.beamlinename,
TO_CHAR(se.startdate, 'HH24:MI DD-MM-YYYY') as firstexperimentst, d.firstexperimentid,
s.shippingid, s.shippingname, d.facilitycode, count(c.containerid) as ccount,
(case when se.visit_number > 0 then (CONCAT(p.proposalcode, p.proposalnumber, '-', se.visit_number)) else '' end) as exp,
d.code, d.barcode, d.storagelocation, d.dewarstatus, d.dewarid,
d.trackingnumbertosynchrotron, d.trackingnumberfromsynchrotron, d.externalShippingIdFromSynchrotron,
s.deliveryagent_agentname, d.weight, d.deliveryagent_barcode, GROUP_CONCAT(c.code SEPARATOR ', ') as containers,
s.sendinglabcontactid, s.returnlabcontactid, pe.givenname, pe.familyname, s.safetylevel as shippingsafetylevel
FROM dewar d
LEFT OUTER JOIN container c ON c.dewarid = d.dewarid
INNER JOIN shipping s ON d.shippingid = s.shippingid
INNER JOIN proposal p ON p.proposalid = s.proposalid
LEFT OUTER JOIN blsession se ON d.firstexperimentid = se.sessionid
LEFT OUTER JOIN blsession se2 ON c.sessionid = se2.sessionid
LEFT OUTER JOIN dewarregistry r ON r.facilitycode = d.facilitycode
LEFT OUTER JOIN labcontact lc ON s.sendinglabcontactid = lc.labcontactid
LEFT OUTER JOIN person pe ON lc.personid = pe.personid
Expand Down
Loading

0 comments on commit 4a10c81

Please sign in to comment.