Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 45 additions & 32 deletions mxcubeweb/core/components/harvester.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import logging

import gevent
from mxcubecore import HardwareRepository as HWR
from mxcubecore.HardwareObjects.abstract.sample_changer import Crims
from mxcubecore.HardwareObjects.Harvester import HarvesterState
from mxcubecore.queue_entry.data_collection import DataCollectionQueueEntry

from mxcubeweb.core.components.component_base import ComponentBase

Expand All @@ -25,6 +27,10 @@ def init_signals(self):
"harvester_contents_update", self.harvester_contents_update
)

HWR.beamline.queue_manager.connect(
"queue_entry_execute_finished", self.queue_entry_execute_finished
)

def harvester_state_changed(self, *args):
new_state = args[0]
state_str = HarvesterState.STATE_DESC.get(new_state, "Unknown").upper()
Expand All @@ -33,6 +39,14 @@ def harvester_state_changed(self, *args):
def harvester_contents_update(self):
self.app.server.emit("harvester_contents_update")

def queue_entry_execute_finished(self, entry, status):
"""Forward a finished data collection to CRIMS, since the sample
came from the Harvester."""
if not isinstance(entry, DataCollectionQueueEntry) or status != "Successful":
return

gevent.spawn(self._send_collection_to_crims, entry.get_data_model())

def get_initial_state(self):
if HWR.beamline.harvester_maintenance is not None:
(
Expand Down Expand Up @@ -139,56 +153,55 @@ def get_crystal_list(self):
}
crystal_list.append(lst)
except Exception:
logging.getLogger("user_level_log").exception("Could not get Crystal List")
logging.getLogger("user_level_log").error("Could not get Crystal List")
logging.getLogger("HWR").exception("")

return crystal_list

def get_global_state(self):
try:
return HWR.beamline.harvester_maintenance.get_global_state()
except Exception:
logging.getLogger("user_level_log").exception("Could not get global state")
logging.getLogger("user_level_log").error("Could not get global state")
logging.getLogger("HWR").exception("")
return "OFFLINE", "OFFLINE", "OFFLINE"

def send_data_collection_info_to_crims(self) -> bool:
"""Send Data collected to CRIMS.
def _send_collection_to_crims(self, data_model) -> None:
"""Send a single data collection's info to CRIMS.

Returns:
bool: Whether the request failed (``False``) or not (``True``).
Args:
data_model: The `DataCollection` queue model object to report.
"""
dataCollectionGroupId = ""
crystal_uuid = ""

try:
rest_token = HWR.beamline.lims.get_rest_token()
proposal = HWR.beamline.session.get_proposal()

crims_url = self.harvester_device.crims_upload_url
crims_key = self.harvester_device.crims_upload_key

queue_entries = HWR.beamline.queue_model.get_all_dc_queue_entries()
dc_id = ""
for qe in queue_entries:
dataCollectionGroupId = qe.get_data_model().lims_group_id
crystal_uuid = (
qe.get_data_model().get_sample_node().crystals[0].crystal_uuid
)
dc_id = qe.get_data_model().id

Crims.send_data_collection_info_to_crims(
crims_url,
crystal_uuid = data_model.get_sample_node().crystals[0].crystal_uuid
sample_name = data_model.get_sample_node().name
instrument_name = HWR.beamline.session.beamline_name
facility_name = HWR.beamline.session.synchrotron_name
investigation_id = HWR.beamline.session.session_id

sent = Crims.send_data_collection_info_to_crims(
crims_url,
crystal_uuid,
sample_name,
instrument_name,
facility_name,
investigation_id,
crims_key,
)
if not sent:
logging.getLogger("user_level_log").warning(
"Data collection was not sent to CRIMS: crystal=%s sample=%s",
crystal_uuid,
dataCollectionGroupId,
dc_id,
proposal,
rest_token,
crims_key,
sample_name,
)
return True
except Exception:
msg = "Could not send data collection to crims"
logging.getLogger("user_level_log").exception(msg)
return False
logging.getLogger("user_level_log").error(
"Could not send data collection to CRIMS"
)
logging.getLogger("HWR").exception("")

def get_sample_by_id(self, sampleID: str):
samples_list = HWR.beamline.sample_changer.get_sample_list()
Expand Down
9 changes: 0 additions & 9 deletions mxcubeweb/routes/harvester.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,6 @@ def calibrate():
return jsonify(app.harvester.get_harvester_contents())
return None

@bp.route("/send_data_collection_info_to_crims", methods=["GET"])
@server.require_control
@server.restrict
def send_data_collection_info_to_crims():
ret = app.harvester.send_data_collection_info_to_crims()
if ret:
return jsonify(app.harvester.get_harvester_contents())
return None

@bp.route("/validate_calibration", methods=["POST"])
@server.restrict
def validate_calibration():
Expand Down
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Flask-Security = { version = "5.7.1", extras = ["common", "fsqla"] }
Flask-SocketIO = "^5.3.6"
gevent = "^23.9.1"
markupsafe = "^2.1.5"
mxcubecore = ">=2.75.0"
mxcubecore = ">=2.99.0"
pydantic = ">=2.8.2,<2.9.0"
pytz = "^2022.6"
requests = "^2.33.0"
Expand Down
16 changes: 0 additions & 16 deletions ui/src/actions/harvester.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
sendAbortHarvester,
sendCalibratePin,
sendDataCollectionInfoToCrims,
sendHarvestAndLoadCrystal,
sendHarvestCrystal,
sendHarvesterCommand,
Expand Down Expand Up @@ -72,21 +71,6 @@ export function harvestAndLoadCrystal(xtalUUID, successCb = null) {
};
}

export function sendDataCollectionToCrims() {
return async (dispatch) => {
try {
const contents = await sendDataCollectionInfoToCrims();
dispatch(setContents(contents));

// temporary use ErrorPanel to display success message
dispatch(showErrorPanel(true, 'Succesfully sent DC to Crims'));
} catch (error) {
dispatch(showErrorPanel(true, error.response.headers.get('message')));
throw new Error('Server refused to send DC to Crims');
}
};
}

export function calibratePin(successCb = null) {
return async (dispatch) => {
try {
Expand Down
4 changes: 0 additions & 4 deletions ui/src/api/harvester.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export function sendCalibratePin() {
return endpoint.get('/calibrate').safeJson();
}

export function sendDataCollectionInfoToCrims() {
return endpoint.get('/send_data_collection_info_to_crims').safeJson();
}

export function sendValidateCalibration(validated) {
return endpoint
.post(JSON.stringify(validated), '/validate_calibration')
Expand Down
14 changes: 0 additions & 14 deletions ui/src/components/Equipment/HarvesterMaintenance.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useDispatch, useSelector } from 'react-redux';
import {
calibratePin,
sendCommand,
sendDataCollectionToCrims,
validateCalibration,
} from '../../actions/harvester';
import InOutSwitch from '../InOutSwitch/InOutSwitch';
Expand Down Expand Up @@ -126,19 +125,6 @@ export default function HarvesterMaintenance() {
</>
)}
</Row>
<hr />
<Row className="mt-2">
<Col sm={6}>
<Button
className="mt-1"
variant="outline-secondary"
onClick={() => dispatch(sendDataCollectionToCrims())}
title="TEST : Send latest Data collection Group and to Crims"
>
Send Data to Crims
</Button>
</Col>
</Row>
</Card.Body>
</Card>
</div>
Expand Down
Loading