AMAction3* CLSSIS3820ScalerDarkCurrentMeasurementAction::createMeasurementAction(double secondsDwell)
{
	AMAction3 *result = 0;

	CLSSIS3820Scaler *scaler = CLSBeamline::clsBeamline()->scaler();

	if (scaler) {
		AMListAction3 *measurementAction = new AMListAction3(new AMListActionInfo3("Taking dark current measurement.", "Taking dark current measurement."), AMListAction3::Sequential);

		measurementAction->addSubAction(scaler->createDwellTimeAction3(secondsDwell));
		measurementAction->addSubAction(scaler->createTriggerAction(AMDetectorDefinitions::SingleRead));

		AMListAction3 *notifyChannelDetectors = new AMListAction3(new AMListActionInfo3("Set last measurement as dark current measurement", "Set last measurement as dark current measurement"));

		for (int i = 0; i < scaler->channels().count(); i++) {
			CLSSIS3820ScalerChannel *channel = scaler->channelAt(i);

			if (channel && channel->isEnabled() && channel->detector() && channel->detector()->canDoDarkCurrentCorrection()) {
				notifyChannelDetectors->addSubAction(channel->detector()->createSetLastMeasurementAsDarkCurrentAction());
			}
		}

		measurementAction->addSubAction(notifyChannelDetectors);

		result = measurementAction;
	}

	return result;
}
BioXASSIS3820ScalerChannelsView::BioXASSIS3820ScalerChannelsView(CLSSIS3820Scaler *scaler, bool biasEnabledVisible, bool biasVisible, bool darkCurrentVisible, QWidget *parent) :
    QWidget(parent)
{
	// Initialize member variables.

	scaler_ = scaler;
	biasEnabledEditorVisible_ = false;
	biasEditorVisible_ = false;
	darkCurrentVisible_ = false;

	// Create UI elements.

	int channelCount = scaler_->channels().count();

	if (scaler_) {
		for (int i = 0; i < channelCount; i++) {
			CLSSIS3820ScalerChannel *channel = scaler_->channelAt(i);

			if (channel) {
				BioXASSIS3820ScalerChannelView *channelView = new BioXASSIS3820ScalerChannelView(channel, biasEnabledEditorVisible_, biasEditorVisible_);
				channelViews_ << channelView;

				channelView->setAmplifierViewFormat('e');
				channelView->setVisible(channel->detector());

				connect( channelView, SIGNAL(amplifierViewModeChanged(AMCurrentAmplifierView::ViewMode)), this, SLOT(setAmplifierViewMode(AMCurrentAmplifierView::ViewMode)) );
				connect( channelView, SIGNAL(outputViewModeChanged(CLSSIS3820ScalerChannelView::OutputViewMode)), this, SLOT(setOutputViewMode(CLSSIS3820ScalerChannelView::OutputViewMode)) );
			}
		}
	}

	// Create and set layouts.

	QVBoxLayout *layout = new QVBoxLayout();
	layout->setMargin(0);

	for (int i = 0, viewCount = channelViews_.count(); i < viewCount; i++) {
		BioXASSIS3820ScalerChannelView *channelView = channelViews_.at(i);
		layout->addWidget(channelView);
	}

	setLayout(layout);

	// Connect to channels.

	for (int i = 0; i < channelCount; i++)
		connect( scaler_->channelAt(i), SIGNAL(detectorChanged(AMDetector*)), this, SLOT(refresh()) );

	// Current settings.

	refresh();

	setBiasEnabledEditorVisible(biasEnabledVisible);
	setBiasEditorVisible(biasVisible);
	setDarkCurrentVisible(darkCurrentVisible);
}
CLSSIS3820ScalerDarkCurrentMeasurementAction::CLSSIS3820ScalerDarkCurrentMeasurementAction(CLSSIS3820ScalerDarkCurrentMeasurementActionInfo *info, QObject *parent) :
    AMListAction3(info, AMListAction3::Sequential, parent)
{
	CLSSIS3820Scaler *scaler = CLSBeamline::clsBeamline()->scaler();
	double secondsDwell = scalerDarkCurrentMeasurementActionInfo()->dwellTime();

	connect( this, SIGNAL(failed()), this, SLOT(onActionFailed()) );

	if (scaler && scaler->isConnected() && secondsDwell > 0) {

		// pre-measurement settings.
		double oldDwell = scaler->dwellTime();

		// first turn off beam.
//		addSubAction(AMBeamline::bl()->createTurnOffBeamActions());

		// set the scaler's dwell time to new time.
		addSubAction(scaler->createDwellTimeAction3(secondsDwell));

		// initiate a scaler measurement and wait until it is complete.
		addSubAction(scaler->createStartAction3(true));
		addSubAction(scaler->createWaitForDwellFinishedAction(secondsDwell + 5.0));

		// notify attached and able scaler channel detectors that the latest measurement was a dark current measurement.
		AMListAction3 *notifyChannelDetectors = new AMListAction3(new AMListActionInfo3("Set last measurement as dark current measurement", "Set last measurement as dark current measurement"));

		for (int i = 0; i < scaler->channels().count(); i++) {
			CLSSIS3820ScalerChannel *channel = scaler->channelAt(i);

			if (channel && channel->isEnabled() && channel->detector() && channel->detector()->canDoDarkCurrentCorrection()) {
				notifyChannelDetectors->addSubAction(channel->detector()->createSetLastMeasurementAsDarkCurrentAction());
			}
		}

		addSubAction(notifyChannelDetectors);

		// reset settings to pre-measurement conditions.
		addSubAction(scaler->createDwellTimeAction3(oldDwell));

	} else {
		AMErrorMon::alert(this, CLSSIS3820SCALERDARKCURRENTMEASUREMENTACTION_SCALER_NOT_VALID, "Failed to complete dark current measurement--scaler not valid.");
		setFailed();
	}

}
void CLSSIS3820ScalerDarkCurrentMeasurementAction::onFailed(QObject *action)
{
	// Cleanup after the measurement action and restore pre-measurement settings.

	onMeasurementFinished(action);

	// Notify each detector that the dark current measurement failed.

	CLSSIS3820Scaler *scaler = CLSBeamline::clsBeamline()->scaler();

	if (scaler && scaler->isConnected()) {

		for (int i = 0; i < scaler->channels().count(); i++) {
			CLSSIS3820ScalerChannel *channel = scaler->channelAt(i);

			if (channel && channel->isEnabled() && channel->detector() && channel->detector()->canDoDarkCurrentCorrection()) {
				channel->detector()->setDarkCurrentValue(0);
				channel->detector()->setDarkCurrentValidState(false);
			}
		}
	}

	// Issue error.

	QString message = "Failed to complete scaler dark current measurement.";
	AMErrorMon::alert(this, CLSSIS3820SCALERDARKCURRENTMEASUREMENTACTION_ACTION_FAILED, message);
	setFailed(message);
}
void CLSSIS3820ScalerDarkCurrentMeasurementAction::onActionFailed()
{
	AMErrorMon::alert(this, CLSSIS3820SCALERDARKCURRENTMEASUREMENTACTION_ACTION_FAILED, "Failed to complete dark current measurement.");

	CLSSIS3820Scaler *scaler = CLSBeamline::clsBeamline()->scaler();

	if (scaler && scaler->isConnected()) {

		// Notify each able channel detector that the dark current measurement has failed.

		for (int i = 0; i < scaler->channels().count(); i++) {
			CLSSIS3820ScalerChannel *channel = scaler->channelAt(i);

			if (channel && channel->isEnabled() && channel->detector() && channel->detector()->canDoDarkCurrentCorrection()) {
				channel->detector()->setDarkCurrentValue(0);
				channel->detector()->setDarkCurrentValidState(false);
			}
		}
	}
}