void AMLoopAction3::internalOnCurrentActionProgressChanged(double numerator, double denominator) { if(internalAllActionsHaveExpectedDuration()) { double totalNumerator = 0, totalDenominator = 0; for(int i=0, cc=subActionCount(); i<cc; i++) { AMAction3* action = subActionAt(i); double expectedSecs = action->info()->expectedDuration(); totalDenominator += expectedSecs*loopCount(); int timesFinished = currentIteration_; if(i < currentSubActionIndex_) timesFinished++; totalNumerator += expectedSecs*timesFinished; if(i == currentSubActionIndex()) // if it's the current action, we have some partial progress. totalNumerator += numerator/denominator * expectedSecs; } setProgress(totalNumerator, totalDenominator); setExpectedDuration(totalDenominator); } // Otherwise, assume every subaction makes up an equal unit ('1') of the total amount of work. Our denominator will be the number of sub-actions * the number of loops, and our numerator will be the sub-actions we've completed (plus the current sub-action's fraction done). else { double totalDenominator = subActionCount()*loopCount(); double totalNumerator = subActionCount()*currentIteration_; // add the completed full loops totalNumerator += currentSubActionIndex_; // add the actions done in this loop totalNumerator += numerator/denominator; // add the fraction done for the current action. setProgress(totalNumerator, totalDenominator); setExpectedDuration(runningTime()*totalDenominator/totalNumerator); } }
void AMAppController::updateScanEditorModelItem() { // Get the action, or if it's in a list, the current running action. AMAction3 *currentAction = AMActionRunner3::workflow()->currentAction(); AMScanAction *action = 0; if (currentAction && !currentAction->hasChildren()) action = qobject_cast<AMScanAction *>(currentAction); else if (currentAction && currentAction->hasChildren()){ AMListAction3 *listAction = qobject_cast<AMListAction3 *>(currentAction); if (listAction) action = qobject_cast<AMScanAction *>(listAction->currentSubAction()); } // Do something with it if the action is valid. if (action && (action->state() == AMAction3::Running || action->inFinalState())){ AMGenericScanEditor *editor = editorFromScan(action->controller()->scan()); if (!editor) return; QString stateString; switch(action->state()){ case AMAction3::Running: stateString = "running"; break; case AMAction3::Succeeded: stateString = "succeeded"; break; case AMAction3::Failed: stateString = "failed"; break; case AMAction3::Cancelled: stateString = "cancelled"; break; default: stateString = "default"; break; } AMScanEditorModelItem *item = (AMScanEditorModelItem *)(mw_->windowPaneModel()->itemFromIndex(mw_->windowPaneModel()->indexForPane(editor))); if (item) item->scanActionStateChanged(stateString, editor == mw_->currentPane()); } }
void AMLoopAction3::internalCleanupAction(AMAction3 *action) { AMAction3 *cleanupAction = action ? action : currentSubAction_; internalDisconnectAction(cleanupAction); // delete it later (since we might still be executing inside the action's functions). cleanupAction->scheduleForDeletion(); //cleanupAction->deleteLater(); if (!action) currentSubAction_ = 0; }
void CLSSIS3820Scaler::measureDarkCurrent(int secondsDwell) { AMAction3 *action = createMeasureDarkCurrentAction(secondsDwell); if (action) { connect( action, SIGNAL(cancelled()), action, SLOT(deleteLater()) ); connect( action, SIGNAL(failed()), action, SLOT(deleteLater()) ); connect( action, SIGNAL(succeeded()), action, SLOT(deleteLater()) ); action->start(); } }
void CLSSIS3820ScalerDarkCurrentMeasurementAction::startImplementation() { // Must have a valid, connected scaler. CLSSIS3820Scaler *scaler = CLSBeamline::clsBeamline()->scaler(); if (! (scaler && scaler->isConnected()) ) { QString message = QString("There was an error measuring scaler dark current. The scaler is invalid or not connected."); AMErrorMon::alert(this, CLSSIS3820SCALERDARKCURRENTMEASUREMENTACTION_INVALID_SCALER, message); setFailed(message); } // Must have a valid dwell time. double secondsDwell = scalerDarkCurrentMeasurementActionInfo()->dwellTime(); if (!validDwellTime(secondsDwell)) { QString message = QString("There was an error measuring scaler dark current. The dwell time provided (%1 s) is invalid.").arg(secondsDwell); AMErrorMon::alert(this, CLSSIS3820SCALERDARKCURRENTMEASUREMENTACTION_INVALID_DWELL_TIME, message); setFailed(message); } // Update pre-measurement settings, to be restored once measurement is complete. measurementInitialization(); // Create measurement action. AMAction3 *measurementAction = createMeasurementAction(secondsDwell); // Make connections and start action. if (measurementAction) { startedMapper_->setMapping(measurementAction, measurementAction); failedMapper_->setMapping(measurementAction, measurementAction); succeededMapper_->setMapping(measurementAction, measurementAction); connect( measurementAction, SIGNAL(started()), startedMapper_, SLOT(map()) ); connect( measurementAction, SIGNAL(failed()), failedMapper_, SLOT(map()) ); connect( measurementAction, SIGNAL(succeeded()), succeededMapper_, SLOT(map()) ); measurementAction->start(); } else { QString message = QString("There was an error measuring scaler dark current. An invalid measurement action was generated."); AMErrorMon::alert(this, CLSSIS3820SCALERDARKCURRENTMEASUREMENTACTION_INVALID_ACTION, message); setFailed(message); } }
AMAction3 * AMListAction3::takeSubActionAt(int index) { if(state() != Constructed) { AMErrorMon::debug(this, AMLISTACTION3_CANNOT_REMOVE_SUBACTION_ONCE_RUNNING, "Cannot remove sub-actions once the action is already running."); return 0; } if(index <0 || index >= subActions_.count()) return 0; emit subActionAboutToBeRemoved(index); AMAction3* action = subActions_.takeAt(index); action->setParentAction(0); emit subActionRemoved(index); return action; }
QWidget * AMActionRunnerQueueItemDelegate3::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option) const AMActionRunnerQueueModel3* model = qobject_cast<const AMActionRunnerQueueModel3*>(index.model()); if(!model) return 0; AMAction3* action = model->actionAtIndex(index); if(!action) return 0; QWidget* rv = AMActionRegistry3::s()->createEditorForInfo(action->info()); if(rv) { rv->setParent(parent); rv->setFocusPolicy(Qt::StrongFocus); rv->setBackgroundRole(QPalette::Window); rv->setAutoFillBackground(true); } return rv; }
AMControl::FailureExplanation CLSMAXvMotor::calibrate(double oldValue, double newValue) { // Check that this motor is connected and able to be calibrated before proceeding. if (!isConnected()) { AMErrorMon::alert(this, CLSMAXVMOTOR_NOT_CONNECTED, QString("Failed to calibrate %1: motor is not connected.").arg(name())); return AMControl::NotConnectedFailure; } if (!canCalibrate()) { AMErrorMon::alert(this, CLSMAXVMOTOR_CANNOT_CALIBRATE, QString("Failed to calibrate %1: motor cannot currently be calibrated.").arg(name())); return AMControl::OtherFailure; } // Proceed with creating calibration action. AMAction3 *action = createCalibrationAction(oldValue, newValue); // Check that a valid calibration action was generated. // If an invalid calibration action was generated, abort the calibration. if (!action) { AMErrorMon::alert(this, CLSMAXVMOTOR_INVALID_CALIBRATION_ACTION, QString("Did not calibrate %1: invalid calibration action generated.").arg(name())); return AMControl::LimitFailure; } // Proceed with initializing the calibration action. // Connect it's final-state signals to its deleteLater() slot to prevent memory leak. connect( action, SIGNAL(cancelled()), action, SLOT(deleteLater()) ); connect( action, SIGNAL(failed()), action, SLOT(deleteLater()) ); connect( action, SIGNAL(succeeded()), action, SLOT(deleteLater()) ); // Run action. action->start(); return AMControl::NoFailure; }
void VESPERSBeamSelectorView::changeBeam(int id) { AMAction3 *action = 0; switch(id){ case 0: action = VESPERSBeamline::vespers()->createBeamChangeAction(VESPERS::Pink); break; case 1: action = VESPERSBeamline::vespers()->createBeamChangeAction(VESPERS::TenPercent); break; case 2: action = VESPERSBeamline::vespers()->createBeamChangeAction(VESPERS::OnePointSixPercent); break; case 3: action = VESPERSBeamline::vespers()->createBeamChangeAction(VESPERS::Si); break; } if (!action) return; progressBar_->setRange(0, 0); progressBar_->show(); connect(action, SIGNAL(cancelled()), this, SLOT(onBeamChangeCompleted())); connect(action, SIGNAL(failed()), this, SLOT(onBeamChangeCompleted())); connect(action, SIGNAL(succeeded()), this, SLOT(onBeamChangeCompleted())); connect(action, SIGNAL(cancelled()), action, SLOT(deleteLater())); connect(action, SIGNAL(failed()), action, SLOT(deleteLater())); connect(action, SIGNAL(succeeded()), action, SLOT(deleteLater())); action->start(); }
AMAction3 * SGMHexapodTransformedAxis::createWaitForCompletionActions() { AMListAction3* waitActions = new AMListAction3(new AMListActionInfo3("Waiting for coordinated move", "Waiting for coordinated move"), AMListAction3::Sequential); waitActions->addSubAction(AMActionSupport::buildControlWaitAction(trajectoryStartControl_, 0, lastDeltaTime_+1.5, AMControlWaitActionInfo::MatchWithinTolerance)); AMListAction3 *recorderActions = new AMListAction3(new AMListActionInfo3("Waiting for data recorders to monitor", "Waiting for data recorders to monitor"), AMListAction3::Parallel); // Read action for the detector emulators for data recorders. These detectors are set to AMDetectorDefinitions::WaitRead, which will mean they will only read once they monitor. AMAction3 *hexapodXRecorderDetectorReadAction = AMBeamline::bl()->exposedDetectorByName("HexapodXRecorder")->createReadAction(); hexapodXRecorderDetectorReadAction->setGenerateScanActionMessage(true); recorderActions->addSubAction(hexapodXRecorderDetectorReadAction); AMAction3 *hexapodYRecorderDetectorReadAction = AMBeamline::bl()->exposedDetectorByName("HexapodYRecorder")->createReadAction(); hexapodYRecorderDetectorReadAction->setGenerateScanActionMessage(true); recorderActions->addSubAction(hexapodYRecorderDetectorReadAction); AMAction3 *hexapodZRecorderDetectorReadAction = AMBeamline::bl()->exposedDetectorByName("HexapodZRecorder")->createReadAction(); hexapodZRecorderDetectorReadAction->setGenerateScanActionMessage(true); recorderActions->addSubAction(hexapodZRecorderDetectorReadAction); AMAction3 *hexapodTimeRecorderDetectorReadAction = AMBeamline::bl()->exposedDetectorByName("HexapodTimeRecorder")->createReadAction(); hexapodTimeRecorderDetectorReadAction->setGenerateScanActionMessage(true); recorderActions->addSubAction(hexapodTimeRecorderDetectorReadAction); AMListAction3 *positionWaitActions = new AMListAction3(new AMListActionInfo3("Waiting for hexapod positions", "Waiting for hexapod positions"), AMListAction3::Parallel); // We need to add 1.5 seconds to the delta time, as the data recorder is slow AMAction3* positionWaitAction = AMActionSupport::buildControlWaitAction(this, lastEndPoint_, lastDeltaTime_+1.5, AMControlWaitActionInfo::MatchWithinTolerance); /* AMAction3* statusXWaitAction = AMActionSupport::buildControlWaitAction(globalXAxisStatus_, 0, lastDeltaTime_+1.5, AMControlWaitActionInfo::MatchWithinTolerance); AMAction3* statusYWaitAction = AMActionSupport::buildControlWaitAction(globalYAxisStatus_, 0, lastDeltaTime_+1.5, AMControlWaitActionInfo::MatchWithinTolerance); AMAction3* statusZWaitAction = AMActionSupport::buildControlWaitAction(globalZAxisStatus_, 0, lastDeltaTime_+1.5, AMControlWaitActionInfo::MatchWithinTolerance); */ positionWaitActions->addSubAction(positionWaitAction); /* positionWaitActions->addSubAction(statusXWaitAction); positionWaitActions->addSubAction(statusYWaitAction); positionWaitActions->addSubAction(statusZWaitAction); */ /* waitActions->addSubAction(positionWaitAction); waitActions->addSubAction(statusXWaitAction); waitActions->addSubAction(statusYWaitAction); waitActions->addSubAction(statusZWaitAction); */ AMListAction3 *centralParallelActions = new AMListAction3(new AMListActionInfo3("Parallel List of Recorder and Position Waits", "Parallel List of Recorder and Position Waits"), AMListAction3::Parallel); centralParallelActions->addSubAction(recorderActions); centralParallelActions->addSubAction(positionWaitActions); waitActions->addSubAction(centralParallelActions); // Return the data recorder to the off state (we need a clean up actions function adding to the AMControl API) waitActions->addSubAction(AMActionSupport::buildControlMoveAction(dataRecorderStatus_, 0)); waitActions->addSubAction(AMActionSupport::buildControlWaitAction(dataRecorderStatus_, 0, 2.0, AMControlWaitActionInfo::MatchWithinTolerance)); waitActions->addSubAction(AMActionSupport::buildControlMoveAction(systemVelocity_, lastSavedVelocity_)); waitActions->addSubAction(AMActionSupport::buildControlWaitAction(systemVelocity_, lastSavedVelocity_, 2.0, AMControlWaitActionInfo::MatchWithinTolerance)); return waitActions; }