void AMDataSourcesEditor::onSetViewIndexChanged(const QModelIndex &selected, const QModelIndex &deselected) {

	removeDetailEditor();

	// Nothing selected?
	////////////////////////
	if(!selected.isValid()) {
		nameEdit_->clear();
		descriptionEdit_->clear();
		descriptionEdit_->setReadOnly(true);
		addDataSourceButton_->setDisabled(true);
		return;
	}

	addDataSourceButton_->setEnabled(true);

	// Scan selected? (No selected data source)
	/////////////////////////
	if(!selected.parent().isValid()) {
		nameEdit_->clear();
		descriptionEdit_->clear();
		descriptionEdit_->setReadOnly(true);
		return;
	}


	// Data source selected.
	/////////////////

	// Remove old connection to the data source description.
	int oldSi = deselected.parent().row();
	int oldDi = deselected.row();
	AMDataSource *oldDataSource = model_->dataSourceAt(oldSi, oldDi);
	if (oldDataSource)
		disconnect(oldDataSource->signalSource(), SIGNAL(infoChanged()), this, SLOT(onDataSourceDescriptionChanged()));

	// Setup new data source.
	int si = selected.parent().row();
	int di = selected.row();
	AMDataSource* dataSource = model_->dataSourceAt(si, di);
	if(!dataSource)
		return;

	connect(dataSource->signalSource(), SIGNAL(infoChanged()), this, SLOT(onDataSourceDescriptionChanged()));

	nameEdit_->setText(dataSource->name());
	descriptionEdit_->setText(dataSource->description());
	descriptionEdit_->setReadOnly(false);

	installDetailEditor(dataSource->createEditorWidget());

	// Set the new selected data source as the exclusive view preference.
	model_->setExclusiveDataSourceByName(dataSource->name());
}
void AM1DBasicIntegralABEditor::populateComboBox()
{
    AMDataSource *tempSource = 0;

    for (int i = 0; i < analysisBlock_->inputDataSourceCount(); i++) {

        tempSource = analysisBlock_->inputDataSourceAt(i);

        if (analysisBlock_->name() != tempSource->name() && !tempSource->hiddenFromUsers())
            names_->addItem(tempSource->description(), tempSource->name());
    }
}
void AM4DBinningABEditor::populateComboBox()
{
	AMDataSource *tempSource = 0;

	for (int i = 0; i < analysisBlock_->inputDataSourceCount(); i++){

		tempSource = analysisBlock_->inputDataSourceAt(i);

		if (analysisBlock_->name() != tempSource->name())
			names_->addItem(tempSource->description(), tempSource->name());
	}
}
void AM3DNormalizationABEditor::populateComboBox()
{
	AMDataSource *tempSource = 0;
	int inputCount = analysisBlock_->inputDataSourceCount();

	for (int i = 0; i < inputCount; i++){

		tempSource = analysisBlock_->inputDataSourceAt(i);

		if (analysisBlock_->name() != tempSource->name()){

			dataNames_->addItem(tempSource->description(), tempSource->name());
			normalizationNames_->addItem(tempSource->description(), tempSource->name());
		}
	}
}
void AMOrderReductionABEditor::populateComboBox()
{
	AMDataSource *source = 0;

	for (int i = 0, size = analysisBlock_->inputDataSourceCount(); i < size; i++){

		source = analysisBlock_->inputDataSourceAt(i);

		if (analysisBlock_->name() != source->name())
			sourceNames_->addItem(source->description(), source->name());
	}

	if (analysisBlock_->rank() != 0){

		for (int i = 0, size = analysisBlock_->currentInputSource()->rank(); i < size; i++)
			reducedAxisOptions_->insertItem(i, analysisBlock_->currentInputSource()->axisInfoAt(i).description, i);
	}
}
void REIXSAppController::onScanAddedToEditor(AMGenericScanEditor *editor, AMScan *scan)
{
	QString exclusiveName = QString();

	for (int i = 0, count = scan->analyzedDataSourceCount(); i < count && exclusiveName.isNull(); i++){

		AMDataSource *source = scan->analyzedDataSources()->at(i);

		if (source->name().contains("TEYNorm") && !source->hiddenFromUsers())
			exclusiveName = source->name();

		if (source->name().contains("xesSpectrum") && !source->hiddenFromUsers())
			exclusiveName = source->name();
	}

	if (!exclusiveName.isNull())
		editor->setExclusiveDataSourceByName(exclusiveName);

	else if (editor->scanAt(0)->analyzedDataSourceCount())
		editor->setExclusiveDataSourceByName(editor->scanAt(0)->analyzedDataSources()->at(editor->scanAt(0)->analyzedDataSourceCount()-1)->name());
}
void VESPERSExporterSMAK::writeMainTable()
{
	QTextStream ts(file_);

	// 1. Column header.
	if(option_->columnHeaderIncluded()) {

		ts << "# ";

		for(int c=0; c<mainTableDataSources_.count(); c++) {

			setCurrentDataSource(mainTableDataSources_.at(c));

			if(mainTableIncludeX_.at(c))
				ts << "H" << option_->columnDelimiter() << "V" << option_->columnDelimiter();

			ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
		}
	}

	ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();

	// 2. rows
	VESPERS2DScanConfiguration *config = qobject_cast<VESPERS2DScanConfiguration *>(const_cast<AMScanConfiguration *>(currentScan_->scanConfiguration()));
	if (!config)
		return;

	QString suffix;

	if (config->ccdDetector().testFlag(VESPERS::Roper))
		suffix = "spe";

	else if (config->ccdDetector().testFlag(VESPERS::Mar))
		suffix = "tif";

	else if (config->ccdDetector().testFlag(VESPERS::Pilatus))
		suffix = "tif";

	QString ccdFileName = config->ccdFileName();
	int yRange = yRange_ == -1 ? currentScan_->scanSize(1) : (yRange_-1);
	int xRange = currentScan_->scanSize(0);

	for(int y = 0; y < yRange; y++) {

		for (int x = 0; x < xRange; x++){

			// over rows within columns
			for(int c=0; c<mainTableDataSources_.count(); c++) {

				setCurrentDataSource(mainTableDataSources_.at(c));
				AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
				int precision = option_->exportPrecision(ds->name());

				// print x and y column?
				if(mainTableIncludeX_.at(c)) {

					ts << ds->axisValue(0,x).toString(precision);
					ts << option_->columnDelimiter();
					ts << ds->axisValue(1, y).toString(precision);
					ts << option_->columnDelimiter();
				}

				if(ds->name().contains("FileNumber"))
					ts << QString("%1_%2.%3").arg(ccdFileName).arg(int(ds->value(AMnDIndex(x, y)))-1).arg(suffix);	// The -1 is because the value stored here is the NEXT number in the scan.  Purely a nomenclature setup from the EPICS interface.

				else
					ts << ds->value(AMnDIndex(x, y)).toString(precision);

				ts << option_->columnDelimiter();
			}

			ts << option_->newlineDelimiter();
		}
	}

	if (yRange_ != -1 && xIndex_ != -1){

		for (int x = 0; x < xIndex_; x++){

			// over rows within columns
			for(int c=0; c<mainTableDataSources_.count(); c++) {

				setCurrentDataSource(mainTableDataSources_.at(c));
				AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
				int precision = option_->exportPrecision(ds->name());

				// print x and y column?
				if(mainTableIncludeX_.at(c)) {

					ts << ds->axisValue(0,x).toString(precision);
					ts << option_->columnDelimiter();
					ts << ds->axisValue(1, yRange_-1).toString(precision);
					ts << option_->columnDelimiter();
				}

				if(ds->name().contains("FileNumber"))
					ts << QString("%1_%2.%3").arg(ccdFileName).arg(int(ds->value(AMnDIndex(x, yRange_-1)))-1).arg(suffix);	// The -1 is because the value stored here is the NEXT number in the scan.  Purely a nomenclature setup from the EPICS interface.

				else
					ts << ds->value(AMnDIndex(x, yRange_-1)).toString(precision);

				ts << option_->columnDelimiter();
			}


			ts << option_->newlineDelimiter();
		}
	}


	ts << option_->newlineDelimiter();
}
void BioXASXASScanActionController::buildScanControllerImplementation()
{
	BioXASBeamline *bioxas = BioXASBeamline::bioXAS();

	// Identify current beamline settings.
	scan_->setScanInitialConditions(bioxas->defaultXASScanControlInfos());

	// Identify exporter option.
	AMExporterOptionXDIFormat *exportXDI = 0;
	if (bioXASConfiguration_) {

		exportXDI = BioXAS::buildStandardXDIFormatExporterOption("BioXAS XAS (XDI Format)", bioXASConfiguration_->edge().split(" ").first(), bioXASConfiguration_->edge().split(" ").last(), true);

		if (exportXDI->id() > 0)
			AMAppControllerSupport::registerClass<BioXASXASScanConfiguration, AMExporterXDIFormat, AMExporterOptionXDIFormat>(exportXDI->id());

		// Clear the option of any previous data sources.

		exportXDI->clearDataSources();
	}

	// Identify and setup the zebra trigger source.
	AMZebraDetectorTriggerSource *zebraTriggerSource = bioxas->zebraTriggerSource();
	if (zebraTriggerSource) {
		zebraTriggerSource->removeAllDetectors();
		zebraTriggerSource->removeAllDetectorManagers();

		if (usingDetector(bioxas->i0Detector()))
			zebraTriggerSource->addDetector(bioxas->i0Detector());

		if (usingDetector(bioxas->i1Detector()))
			zebraTriggerSource->addDetector(bioxas->i1Detector());

		if (usingDetector(bioxas->i2Detector()))
			zebraTriggerSource->addDetector(bioxas->i2Detector());

		if (usingScaler())
			zebraTriggerSource->addDetectorManager(bioxas->scaler());

		AMDetectorSet *geDetectors = bioxas->ge32ElementDetectors();

		for (int i = 0, count = geDetectors->count(); i < count; i++) {
			AMDetector *detector = geDetectors->at(i);

			if (usingDetector(detector)) {
				zebraTriggerSource->addDetector(geDetectors->at(i));
				zebraTriggerSource->addDetectorManager(geDetectors->at(i));
			}
		}
	}

	// Identify data sources for the scaler channels and the scaler dwell time.
	AMDataSource *i0DetectorSource = detectorDataSource(bioxas->i0Detector());
	AMDataSource *i1DetectorSource = detectorDataSource(bioxas->i1Detector());
	AMDataSource *i2DetectorSource = detectorDataSource(bioxas->i2Detector());
	AMDataSource *diodeDetectorSource = detectorDataSource(bioxas->diodeDetector());
	AMDataSource *pipsDetectorSource = detectorDataSource(bioxas->pipsDetector());
	AMDataSource *lytleDetectorSource = detectorDataSource(bioxas->lytleDetector());
	AMDataSource *dwellTimeSource = detectorDataSource(bioxas->scalerDwellTimeDetector());

	// Create analyzed data source for the absorbance.

	AM1DExpressionAB *absorbanceSource = 0;

	if (i0DetectorSource && i1DetectorSource && i2DetectorSource) {
		absorbanceSource = new AM1DExpressionAB("Absorbance");
		absorbanceSource->setDescription("Absorbance");
		absorbanceSource->setInputDataSources(QList<AMDataSource*>() << i0DetectorSource << i1DetectorSource << i2DetectorSource);
		absorbanceSource->setExpression(QString("ln(%1/%2)").arg(i1DetectorSource->name(), i2DetectorSource->name()));

		scan_->addAnalyzedDataSource(absorbanceSource, true, false);
	}

	// Create analyzed data source for the derivative of the absorbance.

	AM1DDerivativeAB *derivAbsorbanceSource = 0;

	if (absorbanceSource) {
		derivAbsorbanceSource = new AM1DDerivativeAB("DerivAbsorbance");
		derivAbsorbanceSource->setInputDataSources(QList<AMDataSource*>() << absorbanceSource);

		scan_->addAnalyzedDataSource(derivAbsorbanceSource, true, false);
	}

	// Create analyzed data sources for the dark current corrected scaler channel detectors.

	AM1DDarkCurrentCorrectionAB *i0CorrectedDetectorSource = 0;

	if (dwellTimeSource && i0DetectorSource && exportXDI) {
		i0CorrectedDetectorSource = new AM1DDarkCurrentCorrectionAB(QString("%1_DarkCorrect").arg(i0DetectorSource->name()));
		i0CorrectedDetectorSource->setDescription(QString("%1 Dark Current Corrected").arg(i0DetectorSource->name()));
		i0CorrectedDetectorSource->setDataName(i0DetectorSource->name());
		i0CorrectedDetectorSource->setDwellTimeName(dwellTimeSource->name());
		i0CorrectedDetectorSource->setDarkCurrent(bioxas->exposedDetectorByName(i0DetectorSource->name())->darkCurrentValue());
		i0CorrectedDetectorSource->setInputDataSources(QList<AMDataSource*>() << i0DetectorSource << dwellTimeSource);
		i0CorrectedDetectorSource->setTimeUnitMultiplier(0.001);

		connect( bioxas->i0Detector(), SIGNAL(darkCurrentValueChanged(double)), i0CorrectedDetectorSource, SLOT(setDarkCurrent(double)) );

		scan_->addAnalyzedDataSource(i0CorrectedDetectorSource, true, false);

		exportXDI->addDataSource(i0CorrectedDetectorSource->name(), false);
	}
Exemple #9
0
QVariant AMScanSetModel::data(const QModelIndex & index, int role) const {
	if(!index.isValid())
		return QVariant();

	// scan-level index:
	///////////////////////////
	if(index.internalId() == -1 && index.row() < scans_.count() && index.column() == 0) {
		AMScan* scan = scans_.at(index.row());

		switch(role) {
		case Qt::DisplayRole: {
				QString rv = scan->fullName();
				if(scan->modified())
					rv.append( " (modified)");
				return rv;
			}
			break;
		case Qt::DecorationRole:
			/// \bug this is temporary and meaningless. It's just the color of the first data source in the scan.
			if(scan->dataSourceCount() > 0)
				return sourcePlotSettings_.at(index.row()).at(0).linePen.color();
			else
				return QVariant();
			break;
		case Qt::ToolTipRole:
			return QString("%1, #%2 (sample: %3): %4").arg(scan->name()).arg(scan->number()).arg(scan->sampleName()).arg(AMDateTimeUtils::prettyDateTime(scan->dateTime(), "h:mm:ssap"));
			break;
		case AM::DescriptionRole:
			return QString("%1, on %2").arg(AMDateTimeUtils::prettyDateTime(scan->dateTime())).arg(scan->sampleName());
		case AM::DateTimeRole:
			return scan->dateTime();
		case Qt::CheckStateRole:
			return QVariant();	/// \todo For now... No checking/unchecking scans.
			break;
		case AM::PointerRole:
			return qVariantFromValue(scan);
			break;
		case AM::ModifiedRole:
			return scan->modified();
		case AM::CanCloseRole:	// allows views to show the 'close' button beside each scan, to delete it. Do we want this on?
			return true;
		case AM::NameRole: {
				return scan->fullName();
			}
			break;
		default:
			return QVariant();
			break;
		}
	}


	// data source-level index:
	////////////////////////////
	if(index.internalId() >= 0 && index.internalId() < scans_.count() ) {
		AMScan* scan = scans_.at(index.internalId());

		if(index.row() < scan->dataSourceCount() && index.column() == 0) {
			AMDataSource* dataSource = scan->dataSourceAt(index.row());

			switch(role) {
			case Qt::DisplayRole:
				return QString("%1 (%2)").arg(dataSource->description(), dataSource->name());
				break;
			case Qt::DecorationRole:
				return sourcePlotSettings_.at(index.internalId()).at(index.row()).linePen.color();
				break;
			case Qt::ToolTipRole:
			case AM::NameRole:
				return dataSource->name();
			case AM::DescriptionRole:
				return dataSource->description();
			case AM::DetailedDescriptionRole:
				return QString("%1 (%2) From scan: %3\n%4").arg(dataSource->description(),
																dataSource->name(),
																scan->name(),
																//scan->evaluatedName(),
																dataSource->typeDescription());
				break;
			case Qt::CheckStateRole:	// this controls visibility on plots.
				if(isVisible(index.internalId(), index.row()))
					return Qt::Checked;
				else
					return Qt::Unchecked;
				break;
			case AM::PointerRole:
				return qVariantFromValue(dataSource);
				break;
			case AM::PriorityRole:
				return sourcePlotSettings_.at(index.internalId()).at(index.row()).priority;
				break;
			case AM::CanCloseRole:	// allows views to show the 'close' button beside each scan, to delete it.
				return true;
			case AM::LinePenRole:
				return sourcePlotSettings_.at(index.internalId()).at(index.row()).linePen;
			case AM::RankRole:
				return dataSource->rank();
			case AMScanSetModel::ColorMapRole:
				return qVariantFromValue(sourcePlotSettings_.at(index.internalId()).at(index.row()).colorMap);
			case AMScanSetModel::MarkerColorRole:
				return qVariantFromValue(sourcePlotSettings_.at(index.internalId()).at(index.row()).markerColor);
			case AMScanSetModel::MarkerShapeRole:
				return QVariant(sourcePlotSettings_.at(index.internalId()).at(index.row()).markerShape);
			default:
				return QVariant();
				break;
			}
		}
	}

	return QVariant();
}
bool AMExporterGeneralAscii::writeSeparateFiles(const QString& destinationFolderPath)
{
	if (option_->higherDimensionsInRows()){

		for(int s=0; s<separateFileDataSources_.count(); s++) {

			setCurrentDataSource(separateFileDataSources_.at(s));	// sets currentDataSourceIndex_
			AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
			int precision = option_->exportPrecision(ds->name());

			QFile file;
			QString separateFileName = parseKeywordString( destinationFolderPath % "/" % option_->separateSectionFileName() );
			separateFileName = removeNonPrintableCharacters(separateFileName);

			if(!openFile(&file, separateFileName)) {
				AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -4, "Export failed (partially): You selected to create separate files for certain data sets. Could not open the file '" % separateFileName % "' for writing.  Check that you have permission to save files there, and that a file with that name doesn't already exists."));
				return false;
			}

			QTextStream ts(&file);

			// section header?
			if(option_->sectionHeaderIncluded()) {
				ts << parseKeywordString(option_->sectionHeader());
				ts << option_->newlineDelimiter();
			}

			// column header?
			if(option_->columnHeaderIncluded()) {
				// 1D data sources:
				if(ds->rank() == 0) {
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
				}
				else if(ds->rank() == 1) {
					if(separateFileIncludeX_.at(s))
						ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
				}
				else if(ds->rank() == 2) {	// 2D
					if(separateFileIncludeX_.at(s))
						ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();
					// need a loop over the second axis columns
					for(int cc=0; cc<ds->size(1); cc++) {
						setCurrentColumnIndex(cc);
						ts << parseKeywordString(option_->columnHeader()) << "[" << ds->axisValue(1, cc).toString(precision) << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();
					}
				}
				ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();
			}

			// table
			switch(ds->rank()) {
			case 0:
				ts << ds->value(AMnDIndex()).toString(precision) << option_->columnDelimiter() << option_->newlineDelimiter();
				break;
			case 1: {
				int maxTableRows = ds->size(0);
				for(int r=0; r<maxTableRows; r++) {
					if(separateFileIncludeX_.at(s)) {
						ts << ds->axisValue(0,r).toString(precision) << option_->columnDelimiter();
					}
					ts << ds->value(r).toString(precision) << option_->columnDelimiter() << option_->newlineDelimiter();
				}
			}
				break;
			case 2: {
				int maxTableRows = ds->size(0);
				for(int r=0; r<maxTableRows; r++) {
					if(separateFileIncludeX_.at(s))
						ts << ds->axisValue(0,r).toString(precision) << option_->columnDelimiter();
					// need a loop over the second axis columns
					for(int cc=0; cc<ds->size(1); cc++) {
						ts << ds->value(AMnDIndex(r,cc)).toString(precision) << option_->columnDelimiter();
					}
					ts << option_->newlineDelimiter();
				}
			}
				break;
			default:
				/// \todo Implement 3D
				break;
			}
		}
	}

	// For writing out in columns.  Essentially transposing the file.
	else{

		for(int s=0; s<separateFileDataSources_.count(); s++) {

			setCurrentDataSource(separateFileDataSources_.at(s));	// sets currentDataSourceIndex_
			AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
			int precision = option_->exportPrecision(ds->name());

			QFile file;
			QString separateFileName = parseKeywordString( destinationFolderPath % "/" % option_->separateSectionFileName() );
			separateFileName = removeNonPrintableCharacters(separateFileName);

			if(!openFile(&file, separateFileName)) {
				AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -4, "Export failed (partially): You selected to create separate files for certain data sets. Could not open the file '" % separateFileName % "' for writing.  Check that you have permission to save files there, and that a file with that name doesn't already exists."));
				return false;
			}

			QTextStream ts(&file);

			// section header?
			if(option_->sectionHeaderIncluded()) {
				ts << parseKeywordString(option_->sectionHeader());
				ts << option_->newlineDelimiter();
			}

			// If including the X values.
			if (separateFileIncludeX_.at(s)){

				switch(ds->rank()){

				case 0:
					break;

				case 1:
				case 2:{

					ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();

					int maxTableColumns = ds->size(0);

					for(int column = 0; column < maxTableColumns; column++)
						ts << ds->axisValue(0,column).toString(precision) << option_->columnDelimiter();

					ts << option_->newlineDelimiter();

					break;
				}

				default:
					/// \todo 3D.
					break;
				}
			}

			// Main table with column headers prefacing rows.
			switch (ds->rank()){

			case 0:{

				if(option_->columnHeaderIncluded())
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();

				ts << ds->value(AMnDIndex()).toString(precision) << option_->columnDelimiter() << option_->newlineDelimiter();

				break;
			}

			case 1:{

				if (option_->columnHeaderIncluded())
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();

				int maxTableColumns = ds->size(0);

				for(int column = 0; column < maxTableColumns; column++)
					ts << ds->value(column).toString(precision) << option_->columnDelimiter();

				ts << option_->newlineDelimiter();

				break;
			}

			case 2:{

				for (int cc = 0; cc < ds->size(1); cc++){

					if (option_->columnHeaderIncluded())
						ts << parseKeywordString(option_->columnHeader()) << "[" << ds->axisValue(1, cc).toString(precision) << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();

					int maxTableColumns = ds->size(0);

					for (int column = 0; column < maxTableColumns; column++)
						ts << ds->value(AMnDIndex(column, cc)).toString(precision) << option_->columnDelimiter();

					ts << option_->newlineDelimiter();
				}

				break;
			}

			default:
				/// \todo 3D
				break;
			}
		}
	}

	return true;
}
void AMExporterGeneralAscii::writeSeparateSections()
{
	QTextStream ts(file_);

	if (option_->higherDimensionsInRows()){

		for(int s=0; s<separateSectionDataSources_.count(); s++) {

			ts << option_->newlineDelimiter();

			setCurrentDataSource(separateSectionDataSources_.at(s));	// sets currentDataSourceIndex_
			AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
			int precision = option_->exportPrecision(ds->name());

			// section header?
			if(option_->sectionHeaderIncluded()) {
				ts << parseKeywordString(option_->sectionHeader());
				ts << option_->newlineDelimiter();
			}

			// column header?
			if(option_->columnHeaderIncluded()) {
				// 1D data sources:
				if(ds->rank() == 0) {
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
				}
				else if(ds->rank() == 1) {
					if(separateSectionIncludeX_.at(s))
						ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
				}
				else if(ds->rank() == 2) {	// 2D
					if(separateSectionIncludeX_.at(s))
						ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();
					// need a loop over the second axis columns
					for(int cc=0; cc<ds->size(1); cc++) {
						setCurrentColumnIndex(cc);
						ts << parseKeywordString(option_->columnHeader()) << "[" << ds->axisValue(1, cc).toString(precision) << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();
					}
				}
				ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();
			}

			// table
			switch(ds->rank()) {
			case 0:
				ts << ds->value(AMnDIndex()).toString(precision) << option_->columnDelimiter() << option_->newlineDelimiter();
				break;
			case 1: {
				int maxTableRows = ds->size(0);
				for(int r=0; r<maxTableRows; r++) {
					if(separateSectionIncludeX_.at(s)) {
						ts << ds->axisValue(0,r).toString(precision) << option_->columnDelimiter();
					}
					ts << ds->value(r).toString(precision) << option_->columnDelimiter() << option_->newlineDelimiter();
				}
			}
				break;
			case 2: {
				int maxTableRows = ds->size(0);
				for(int r=0; r<maxTableRows; r++) {
					if(separateSectionIncludeX_.at(s))
						ts << ds->axisValue(0,r).toString(precision) << option_->columnDelimiter();
					// need a loop over the second axis columns
					for(int cc=0; cc<ds->size(1); cc++) {
						ts << ds->value(AMnDIndex(r,cc)).toString(precision) << option_->columnDelimiter();
					}
					ts << option_->newlineDelimiter();
				}
			}
				break;
			default:
				/// \todo Implement 3D
				break;
			}
		}
	}

	// For writing out in columns.  Essentially transposing the file.
	else{

		for(int s=0; s<separateSectionDataSources_.count(); s++) {

			setCurrentDataSource(separateSectionDataSources_.at(s));	// sets currentDataSourceIndex_
			AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
			int precision = option_->exportPrecision(ds->name());

			// section header?
			if(option_->sectionHeaderIncluded()) {
				ts << parseKeywordString(option_->sectionHeader());
				ts << option_->newlineDelimiter();
			}

			// If including the X values.
			if (separateSectionIncludeX_.at(s)){

				switch(ds->rank()){

				case 0:
					break;

				case 1:
				case 2:{

					ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();

					int maxTableColumns = ds->size(0);

					for(int column = 0; column < maxTableColumns; column++)
						ts << ds->axisValue(0,column).toString(precision) << option_->columnDelimiter();

					ts << option_->newlineDelimiter();

					break;
				}

				default:
					/// \todo 3D.
					break;
				}
			}

			// Main table with column headers prefacing rows.
			switch (ds->rank()){

			case 0:{

				if(option_->columnHeaderIncluded())
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();

				ts << ds->value(AMnDIndex()).toString(precision) << option_->columnDelimiter() << option_->newlineDelimiter();

				break;
			}

			case 1:{

				if (option_->columnHeaderIncluded())
					ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();

				int maxTableColumns = ds->size(0);

				for(int column = 0; column < maxTableColumns; column++)
					ts << ds->value(column).toString(precision) << option_->columnDelimiter();

				ts << option_->newlineDelimiter();

				break;
			}

			case 2:{

				for (int cc = 0; cc < ds->size(1); cc++){

					if (option_->columnHeaderIncluded())
						ts << parseKeywordString(option_->columnHeader()) << "[" << ds->axisValue(1, cc).toString(precision) << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();

					int maxTableColumns = ds->size(0);

					for (int column = 0; column < maxTableColumns; column++)
						ts << ds->value(AMnDIndex(column, cc)).toString(precision) << option_->columnDelimiter();

					ts << option_->newlineDelimiter();
				}

				break;
			}

			default:
				/// \todo 3D
				break;
			}
		}
	}
}
void AMExporterGeneralAscii::writeMainTable()
{
	QTextStream ts(file_);

	// 1. Column header.
	int maxTableRows = 0;
	if(option_->columnHeaderIncluded()) {
		for(int c=0; c<mainTableDataSources_.count(); c++) {
			setCurrentDataSource(mainTableDataSources_.at(c));
			AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
			int precision = option_->exportPrecision(ds->name());

			if(ds->size(0) > maxTableRows)
				maxTableRows = ds->size(0); // convenient... lets figure this out while we're looping through anyway

			// 1D data sources:
			if(ds->rank() == 1) {
				if(mainTableIncludeX_.at(c))
					ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();
				ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
			}
			else {	// 2D
				if(mainTableIncludeX_.at(c))
					ts << parseKeywordString(option_->columnHeader()) << ".X" << option_->columnDelimiter();
				// need a loop over the second axis columns
				for(int cc=0; cc<ds->size(1); cc++) {
					setCurrentColumnIndex(cc);
					ts << parseKeywordString(option_->columnHeader()) << "[" << ds->axisValue(1, cc).toString(precision) << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();
				}
			}
		}
		ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();
	}


	// 2. rows
	for(int r=0; r<maxTableRows; r++) {

		// over rows within columns
		for(int c=0; c<mainTableDataSources_.count(); c++) {
			setCurrentDataSource(mainTableDataSources_.at(c));
			AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
			int precision = option_->exportPrecision(ds->name());

			bool doPrint = (ds->size(0) > r);

			// print x column?
			if(mainTableIncludeX_.at(c)) {
				if(doPrint)
					ts << ds->axisValue(0,r).toString(precision);
				ts << option_->columnDelimiter();
			}

			// 1D data sources:
			if(ds->rank() == 1) {
				if(doPrint)
					ts << ds->value(r).toString(precision);
				ts << option_->columnDelimiter();
			}
			else if(ds->rank() == 2) {
				// need a loop over the second axis columns
				for(int cc=0; cc<ds->size(1); cc++) {
					if(doPrint)
						ts << ds->value(AMnDIndex(r,cc)).toString(precision);
					ts << option_->columnDelimiter();
				}
			}
		}
		ts << option_->newlineDelimiter();
	}
}
void AMDataSourcesEditor::onCloseButtonClicked(const QModelIndex &index) {

	// handle data source-level indexes only:
	if(!index.parent().isValid())
		return;

	int dataSourceIndex = index.row();
	int scanIndex = index.parent().row();

	AMScan* scan = model_->scanAt(scanIndex);
	if(!scan || dataSourceIndex >= scan->dataSourceCount())
		return;

	if (dataSourceIndex < scan->rawDataSourceCount()){

		QMessageBox::warning(this, "Can not remove raw data sources.", QString("Acquaman does not allow the deletion of raw data sources."));
		return;
	}

	AMDataSource* dataSource = scan->dataSourceAt(dataSourceIndex);
	int response = QMessageBox::question(this, "Remove Data Source?", QString("Remove this data source? \n\n'%1' (%2)\n\nThe data source will be deleted, and no longer visible in any plots. Any other data sources that depend on this data source will be reset.  Raw data will NOT be deleted, and you can re-create the data source later if you need it.").arg(dataSource->description()).arg(dataSource->name()), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);

	if(response == QMessageBox::Ok)
		scan->deleteDataSourceAt(dataSourceIndex);
}
void AMExporter2DAscii::writeMainTable()
{
	QTextStream ts(file_);

	// 1. Column header.
	if(option_->columnHeaderIncluded()) {

		ts << "# ";

		for(int c=0; c<mainTableDataSources_.count(); c++) {

			setCurrentDataSource(mainTableDataSources_.at(c));

			if(mainTableIncludeX_.at(c))
				ts << currentScan_->rawData()->scanAxisAt(0).name << option_->columnDelimiter() << currentScan_->rawData()->scanAxisAt(1).name << option_->columnDelimiter();

			ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
		}
	}

	ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();

	// 2. rows
	int yRange = yRange_ == -1 ? currentScan_->scanSize(1) : (yRange_-1);
	int xRange = currentScan_->scanSize(0);

	for(int y = 0; y < yRange; y++) {

		for (int x = 0; x < xRange; x++){

			// over rows within columns
			for(int c=0; c<mainTableDataSources_.count(); c++) {
				setCurrentDataSource(mainTableDataSources_.at(c));
				AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
				int precision = option_->exportPrecision(ds->name());
				// print x and y column?
				if(mainTableIncludeX_.at(c)) {

					ts << ds->axisValue(0, x).toString(precision);
					ts << option_->columnDelimiter();
					ts << ds->axisValue(1, y).toString(precision);
					ts << option_->columnDelimiter();
				}

				ts << ds->value(AMnDIndex(x, y)).toString(precision);

				ts << option_->columnDelimiter();
			}

			ts << option_->newlineDelimiter();
		}
	}

	if (yRange_ != -1 && xIndex_ != -1){

		for (int i = 0; i < xIndex_; i++){

			// over rows within columns
			for(int c=0; c<mainTableDataSources_.count(); c++) {
				setCurrentDataSource(mainTableDataSources_.at(c));
				AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
				int precision = option_->exportPrecision(ds->name());

				// print x and y column?
				if(mainTableIncludeX_.at(c)) {

					ts << ds->axisValue(0,i).toString(precision);
					ts << option_->columnDelimiter();
					ts << ds->axisValue(1, yRange_-1).toString(precision);
					ts << option_->columnDelimiter();
				}

				ts << ds->value(AMnDIndex(i, yRange_-1)).toString(precision);

				ts << option_->columnDelimiter();
			}

			ts << option_->newlineDelimiter();
		}
	}

	ts << option_->newlineDelimiter();
}
void VESPERSExporter2DAscii::writeMainTable()
{
	QTextStream ts(file_);

	// 1. Column header.
	if(option_->columnHeaderIncluded()) {

		ts << "# ";

		for(int c=0; c<mainTableDataSources_.count(); c++) {

			setCurrentDataSource(mainTableDataSources_.at(c));

			if(mainTableIncludeX_.at(c))
				ts << currentScan_->rawData()->scanAxisAt(0).name << option_->columnDelimiter() << currentScan_->rawData()->scanAxisAt(1).name << option_->columnDelimiter();

			ts << parseKeywordString(option_->columnHeader()) << option_->columnDelimiter();
		}
	}

	ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();

	// 2. rows
	VESPERS::CCDDetectors ccdDetector;
	QString ccdFileName = "";

	VESPERS2DScanConfiguration *configuration2D = qobject_cast<VESPERS2DScanConfiguration *>(const_cast<AMScanConfiguration *>(currentScan_->scanConfiguration()));
	VESPERSTimedLineScanConfiguration *timedConfiguration = qobject_cast<VESPERSTimedLineScanConfiguration *>(const_cast<AMScanConfiguration *>(currentScan_->scanConfiguration()));

	if (configuration2D){

		ccdDetector = configuration2D->ccdDetector();
		ccdFileName = configuration2D->ccdFileName();
	}

	else if (timedConfiguration){

		ccdDetector = timedConfiguration->ccdDetector();
		ccdFileName = timedConfiguration->ccdFileName();
	}

	else
		return;

	QString ccdString;

	// This will return -1 if it fails.  This means any checks inside this loop will always fail if the CCD was not included.
	int yRange = yRange_ == -1 ? currentScan_->scanSize(1) : (yRange_-1);
	int xRange = currentScan_->scanSize(0);


	if (ccdDetector.testFlag(VESPERS::Roper))
		ccdString = ccdFileName % "_%1.spe";

	else if (ccdDetector.testFlag(VESPERS::Mar))
		ccdString = ccdFileName % "_%1.tif";

	else if (ccdDetector.testFlag(VESPERS::Pilatus))
		ccdString = ccdFileName % "-%1.tif";
	else
		ccdString = "";

	for(int y = 0; y < yRange; y++) {

		for (int x = 0; x < xRange; x++){

			// over rows within columns
			for(int c=0; c<mainTableDataSources_.count(); c++) {
				setCurrentDataSource(mainTableDataSources_.at(c));
				AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
				int precision = option_->exportPrecision(ds->name());

				// print x and y column?
				if(mainTableIncludeX_.at(c)) {

					ts << ds->axisValue(0, x).toString(precision);
					ts << option_->columnDelimiter();
					ts << ds->axisValue(1, y).toString(precision);
					ts << option_->columnDelimiter();
				}

				if(ds->name().contains("FileNumber"))
					ts << QString(ccdString).arg(int(ds->value(AMnDIndex(x, y)))-1);	// The -1 is because the value stored here is the NEXT number in the scan.  Purely a nomenclature setup from the EPICS interface.
				else
					ts << ds->value(AMnDIndex(x, y)).toString(precision);

				ts << option_->columnDelimiter();
			}

			ts << option_->newlineDelimiter();
		}
	}

	if (yRange_ != -1 && xIndex_ != -1){

		for (int x = 0; x < xIndex_; x++){

			// over rows within columns
			for(int c=0; c<mainTableDataSources_.count(); c++) {

				setCurrentDataSource(mainTableDataSources_.at(c));
				AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);
				int precision = option_->exportPrecision(ds->name());

				// print x and y column?
				if(mainTableIncludeX_.at(c)) {

					ts << ds->axisValue(0,x).toString(precision);
					ts << option_->columnDelimiter();
					ts << ds->axisValue(1, yRange_-1).toString(precision);
					ts << option_->columnDelimiter();
				}

				if(ds->name().contains("FileNumber"))
					ts << QString(ccdString).arg(int(ds->value(AMnDIndex(x, yRange_-1)))-1);	// The -1 is because the value stored here is the NEXT number in the scan.  Purely a nomenclature setup from the EPICS interface.

				else
					ts << ds->value(AMnDIndex(x, yRange_-1)).toString(precision);

				ts << option_->columnDelimiter();
			}


			ts << option_->newlineDelimiter();
		}
	}


	ts << option_->newlineDelimiter();
}