void AMExternalScanDataSourceAB::copyValues(int dataSourceIndex)
{
	AMDataSource* ds = scan_->dataSourceAt(dataSourceIndex);
	const AMnDIndex size = ds->size();

	switch(ds->rank()) {
	case 0:
		values_.clear();
		values_ << ds->value(AMnDIndex());
		break;

	case 1: {
		values_.resize(size.i());
		for(int i=0; i<size.i(); i++)
			values_[i] = ds->value(i);
		break;
	}
	case 2: {
		values_.resize(size.i()*size.j());
		for(int i=0; i<size.i(); i++)
			for(int j=0; j<size.j(); j++)
				values_[i*size.j() + j] = ds->value(AMnDIndex(i,j));
		break;
	}
	case 3: {
		values_.resize(size.i()*size.j()*size.k());
		for(int i=0; i<size.i(); i++)
			for(int j=0; j<size.j(); j++)
				for(int k=0; k<size.k(); k++)
					values_[i*size.j()*size.k() + j*size.k() + k] = ds->value(AMnDIndex(i,j,k));
		break;
	}
	case 4: {
		values_.resize(size.i()*size.j()*size.k()*size.l());
		for(int i=0; i<size.i(); i++)
			for(int j=0; j<size.j(); j++)
				for(int k=0; k<size.k(); k++)
					for(int l=0; l<size.l(); l++)
						values_[i*size.j()*size.k()*size.l() + j*size.k()*size.l() + k*size.l() + l] = ds->value(AMnDIndex(i,j,k,l));
		break;
	}
	case 5: {
		values_.resize(size.i()*size.j()*size.k()*size.l()*size.m());
		for(int i=0; i<size.i(); i++)
			for(int j=0; j<size.j(); j++)
				for(int k=0; k<size.k(); k++)
					for(int l=0; l<size.l(); l++)
						for(int m=0; m<size.m(); m++)
							values_[i*size.j()*size.k()*size.l()*size.m() + j*size.k()*size.l()*size.m() + k*size.l()*size.m() + l*size.m() + m] = ds->value(AMnDIndex(i,j,k,l,m));
		/// \todo oh god, we really need a block copy or a multi-dimensional iterator for AMDataSource::value()...
		break;
	}
	}
}
Exemple #2
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();
}
Exemple #3
0
bool AMExporterGeneralAscii::writeSeparateFiles(const QString& destinationFolderPath)
{
	for(int s=0; s<separateFileDataSources_.count(); s++) {

		setCurrentDataSource(separateFileDataSources_.at(s));	// sets currentDataSourceIndex_
		AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);

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

		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() << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();
				}
			}
			ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();
		}

		// table
		switch(ds->rank()) {
		case 0:
			ts << ds->value(AMnDIndex()).toString() << 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() << option_->columnDelimiter();
				}
				ts << ds->value(r).toString() << 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() << 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() << option_->columnDelimiter();
				}
				ts << option_->newlineDelimiter();
			}
		}
		break;
		default:
			/// \todo Implement 3D
			break;
		}
	}

	return true;
}
Exemple #4
0
void AMExporterGeneralAscii::writeSeparateSections()
{
	QTextStream ts(file_);

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

		ts << option_->newlineDelimiter();

		setCurrentDataSource(separateSectionDataSources_.at(s));	// sets currentDataSourceIndex_
		AMDataSource* ds = currentScan_->dataSourceAt(currentDataSourceIndex_);

		// 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() << ds->axisInfoAt(1).units << "]" << option_->columnDelimiter();
				}
			}
			ts << option_->newlineDelimiter() << option_->columnHeaderDelimiter() << option_->newlineDelimiter();
		}

		// table
		switch(ds->rank()) {
		case 0:
			ts << ds->value(AMnDIndex()).toString() << 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() << option_->columnDelimiter();
				}
				ts << ds->value(r).toString() << 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() << 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() << option_->columnDelimiter();
				}
				ts << option_->newlineDelimiter();
			}
		}
		break;
		default:
			/// \todo Implement 3D
			break;
		}
	}
}
Exemple #5
0
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_);

			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() << 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_);

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

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

			// 1D data sources:
			if(ds->rank() == 1) {
				if(doPrint)
					ts << ds->value(r).toString();
				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();
					ts << option_->columnDelimiter();
				}
			}
		}
		ts << option_->newlineDelimiter();
	}
}
Exemple #6
0
bool AMExporterGeneralAscii::prepareDataSources() {

	mainTableDataSources_.clear();
	mainTableIncludeX_.clear();
	separateSectionDataSources_.clear();
	separateSectionIncludeX_.clear();
	separateFileDataSources_.clear();
	separateFileIncludeX_.clear();

	if(option_->includeAllDataSources() && !option_->firstColumnOnly()) {
		// assumptions: 1D goes in main table. 0D, 2D and higher goes in separate section.
		for(int i=0; i<currentScan_->dataSourceCount(); i++) {
			switch(currentScan_->dataSourceAt(i)->rank()) {
			case 0:
				separateSectionDataSources_ << i;
				separateSectionIncludeX_ << false;	// default false for 0D (scalar point) data
				break;
			case 1:
				mainTableDataSources_ << i;
				mainTableIncludeX_ << true;
				break;
			default:

				if (option_->includeHigherDimensionSources()){

					if (option_->separateHigherDimensionalSources()){

						separateFileDataSources_ << i;
						separateFileIncludeX_ << false;
					}
					else{

						separateSectionDataSources_ << i;
						separateSectionIncludeX_ << true;
					}
				}
				break;
			}
		}
	}

	else if (option_->includeAllDataSources() && option_->firstColumnOnly()){

		// assumptions: 1D goes in main table. 0D, 2D and higher goes in separate section.
		for(int i=0; i<currentScan_->dataSourceCount(); i++) {
			switch(currentScan_->dataSourceAt(i)->rank()) {
			case 0:
				separateSectionDataSources_ << i;
				separateSectionIncludeX_ << false;	// default false for 0D (scalar point) data
				break;
			case 1:
				mainTableDataSources_ << i;
				mainTableIncludeX_ << (i == 0 ? true : false);
				break;
			default:

				if (option_->includeHigherDimensionSources()){

					if (option_->separateHigherDimensionalSources()){

						separateFileDataSources_ << i;
						separateFileIncludeX_ << false;
					}
					else{

						separateSectionDataSources_ << i;
						separateSectionIncludeX_ << true;
					}
				}

				break;
			}
		}
	}

	// otherwise look at what the user specified
	else {
		QStringList dataSources = option_->dataSources();
		for(int i=0; i<dataSources.count(); i++) {	// i iterates through data sources in the option: these are ones that the user requested to include

			int dataSourceIndex = currentScan_->indexOfDataSource(dataSources.at(i));

			if(dataSourceIndex == -1) {	// missing data source?
				if(option_->isDataSourceRequired(i)) {
					AMErrorMon::report(AMErrorReport(this,
													 AMErrorReport::Alert,
													 -3,
													 "Export failed: The scan '" % currentScan_->fullName() % "' does not contain the required data set '" % dataSources.at(i) % "'."));
					return false;
				}
				else
					continue;
			}

			AMDataSource* dataSource = currentScan_->dataSourceAt(dataSourceIndex);

			switch(option_->dataSourceOrganizeMode(i)) {
			case  AMExporterOptionGeneralAscii::CombineInColumnsMode:
				if(dataSource->rank() > 0 && dataSource->rank() < 3) {
					mainTableDataSources_ << dataSourceIndex;
					mainTableIncludeX_ << !option_->isDataSourceAxisValueColumnOmitted(i);
				}
				else {
					separateSectionDataSources_ << dataSourceIndex;	// only 1D and 2D data allowed in the main table.  I don't know how else to break it to you...
					separateSectionIncludeX_ << !option_->isDataSourceAxisValueColumnOmitted(i);
					AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 0, "Moving " % QString::number(dataSource->rank()) % "D data to its own section in the exported file.  Only 1D and 2D data is allowed in the main table."));
				}
				break;

			case AMExporterOptionGeneral::SeparateSectionsMode:
				separateSectionDataSources_ << dataSourceIndex;
				separateSectionIncludeX_ << !option_->isDataSourceAxisValueColumnOmitted(i);
				break;
			case AMExporterOptionGeneral::SeparateFilesMode:
				separateFileDataSources_ << dataSourceIndex;
				separateFileIncludeX_ << !option_->isDataSourceAxisValueColumnOmitted(i);
			}
		}
	}

	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 AMDataSourcesEditor::onNewDataSourceNamed() {

	if(!editingNewDataSourceName_)
		return;

	editingNewDataSourceName_ = false;
	QString chName = nameEdit_->text();
	disconnect(nameEdit_, SIGNAL(editingFinished()), this, SLOT(onNewDataSourceNamed()));
	nameEdit_->clearFocus();
	nameEdit_->setReadOnly(true);


	int si = currentScanIndex();
	if(si < 0 || si >= model_->scanCount()) {
		// this should have never happened. How did we get here? You shouldn't have been able to press the addNewChannel button without a current scan.
		return;
	}

	if(chName.isEmpty())
		return;


	if(model_->scanAt(si)->indexOfDataSource(chName) != -1) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -1, QString("Couldn't create a new data source with the name \"%1\". Make sure to choose a name that doesn't exist already in this scan.").arg(chName)));
		scanSetView_->setCurrentIndex(scanSetView_->currentIndex());
		return;
	}

	AMScan* scan = model_->scanAt(si);
	QList<AMDataSource*> singleDimDataSources;
	QList<AMDataSource *> twoDimDataSources;
	QList<AMDataSource *> threeDimDataSources;
	AMAnalysisBlock *newAnalysisBlock = 0;
	AMDataSource *tempSource = 0;

	// find out all the available 1D and 2D data sources, to use for inputs on this new data source.
	/// \todo Currently this only provides access to the raw data sources, until we can figure out a way to detect or work-around the circular reference problem if analyzed data sources could be used as input.
	/// \note DH: I have changed this to use all of the data sources.  There currently is still no work-around for the circular reference problem.  We are just going to have to be careful about using this.

	for(int i=0; i<scan->dataSourceCount(); i++){

		tempSource = scan->dataSourceAt(i);

		if(tempSource->rank() == 1)
			singleDimDataSources << tempSource;

		else if(tempSource->rank() == 2)
			twoDimDataSources << tempSource;

		else if (tempSource->rank() == 3)
			threeDimDataSources << tempSource;
	}

	newAnalysisBlock = qobject_cast<AMAnalysisBlock *>(AMDbObjectSupport::s()->objectInfoForClass(nameOfAnalysisBlockToBeAdded_)->metaObject->newInstance(Q_ARG(QString, chName)));

	// This should always happen.  But just to be safe.
	if (newAnalysisBlock){

		if (newAnalysisBlock->desiredInputRank() == 1)
			newAnalysisBlock->setInputDataSources(singleDimDataSources);

		else if (newAnalysisBlock->desiredInputRank() == 2)
			newAnalysisBlock->setInputDataSources(twoDimDataSources);

		else if (newAnalysisBlock->desiredInputRank() == 3)
			newAnalysisBlock->setInputDataSources(threeDimDataSources);

		scan->addAnalyzedDataSource(newAnalysisBlock);
	}

	int di = scan->dataSourceCount()-1;
	scanSetView_->setCurrentIndex(model_->indexForDataSource(si, di));
		// this should automatically create a new detail editor for this new scan.
}