//
//	Main program for measuring isotopes in the IMS-4f
//	in non-imaging mode.
//
//	AUTHOR: A. J. Fahey			Oct, 1995
//	NIST, Gaithersburg
//
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <io.h>
#include <fstream.h>
#include <iostream.h>
#include <time.h>
#include <conio.h>
#include <dos.h>
#include <signal.h>
#include "3f_io.h"
#include "3f_ctrl.h"
#include "ims-3f.h"
#include "FileIO.h"
#include "utils.h"
#include "Display.h"
#include "FastTmr.h"

//	Function Prototypes
void FinishUp(void);
int AbortRun(void);
void Ignore(int *a);
void CleanUp(int *a);

typedef void (*fptr)(int);

//	Function to speed up the system timer
#pragma startup InstallFastTmr	// Turbo C++ pragma executed before main
#pragma exit	FinishUp		// Turbo C++ pragma executed after main

int	verbose=TRUE;

void main(int argc, char *argv[])
{
//	Flags
extern int verbose;
int		Ccycle = FALSE;
int		EScycle = FALSE;
int		FinishedHere;
//	Indices
register i, j, c, m;
unsigned int run;
//	Control Parameters
unsigned int HystCycles = HYST_CYCLES;
int		MassRange = LOWMASS;
unsigned int PreCycles = PRE_CYCLES;
//	Constants
const int PreCycleDelay = 2.0;
// Temporary variables with short names
unsigned long B, dB;
double	M, dM;
float	StartingMass;
float	E;
int		p1, p2;
int		BRef, ERef;
float	RefHVO;
unsigned long RefField;
double	RefMass;
char	dummy[20];
//	Strings
char	response[10];
char	*StartupFile="No File Specified";
//	Structures
struct	CycleParam Cycle;
struct	MeasParam Measurement;
struct	RawData **data;
struct	Peak *Peaks;
struct	EnergyDist *EDist;
time_t	StartTime, TimeNow;
//	Classes
ofstream RawDataFile;
//	Turn on control-break watching!
//ctrlbrk(AbortRun);
signal(SIGFPE,(fptr)Ignore);		// ignore floating point errors!
signal(SIGINT,(fptr)CleanUp);
//	Parse the command line args
for(i=1;i<argc;i++)
	{
	if(strnicmp(argv[i],"-ver",4) == 0)			// verbose mode
		{ verbose = TRUE; }
	else if(strnicmp(argv[i],"-hig",4) == 0)	// high mass range
		{ MassRange = HIGHMASS; }				// default is low
	else if(strnicmp(argv[i],"-low",4) == 0)	// low mass range
		{ MassRange = LOWMASS; }
	else if(strnicmp(argv[i],"-pre",4) == 0)	// No. of pre-cycles
		{										// these are before the
		i++;									// run starts but after
		PreCycles = atoi(argv[i]);				// centering and hyst.
		if(PreCycles > 10)                      // loops.
			{ PreCycles = 10; }
		}
	else if(strnicmp(argv[i],"-hys",4) == 0)	// No. of Hyst. cycles
		{
		i++;
		HystCycles = atoi(argv[i]);
		if(HystCycles > 10)
			{ HystCycles = 10; }
		}
	else                                        // startup data file name
		{
		if(access(argv[i],04)!=0)	// check to see that the
			{						// file exists.
			fprintf(stderr,
				"Cannot access startup data file: %s\n",
				argv[i]);
			exit(0);
			}
		else
			{ StartupFile = argv[i]; }
		}
	}
//	Read the startup data file, initialize the machine
//	and the appropriate variables.  This function also
//	allocates memory for the structures "Cycle" and "Measurement"
if(!ReadStartupData(StartupFile,&Cycle,&Measurement))
	{ cerr << "Error Reading file: " << StartupFile << endl; exit(0); }
StartingMass = Cycle.thisMass[0].Mass - 0.5;	// Where all cycles start!
//	Allocate memory for the peak parameters
Peaks = (struct Peak *)malloc(Cycle.NMasses*sizeof(struct Peak));
//	Allocate memory for energy distributions parameters
EDist = (struct EnergyDist *)malloc(Cycle.NMasses*sizeof(struct EnergyDist));
for(i=0;i<Cycle.NMasses;i++)	// Initialize array
	{
	EDist[i].VoltageShift = 0;
	EDist[i].Locked = FALSE;
	}
//	Display the data and ask if it is correct
DisplayStartupData(Cycle,Measurement);
cout << "Is this startup data correct?" << endl;
if(!AskYes()) { exit(0); }
//
//	Initialize the Ion Probe
Init();		// Initialize the Control lines via the CEA interface
if(Measurement.PrimaryPolarity == '+')	// Set the beam polarities.
	{ p1 = Positive; } else { p1 = Negative; }
if(Measurement.SecondaryPolarity == '+')
	{ p2 = Positive; } else { p2 = Negative; }
WritePolarity(p1,p2);
WriteHVOffset(0);				// Make sure this starts at zero.
SetMassRange(MassRange);		// Set the mass range
SelectCounter(SelectEM);		// Select the EM (vs the RAE);
//
//	Start the hysteresis loops
for(c=0;c<HystCycles;c++)
	{
	for(m=0;m<Cycle.NMasses;m++)
		{
		if(m == 0)
			{ WriteMass(StartingMass); Wait(PreCycleDelay); }
		cout << "Hysteresis cycle  " << c+1;
		cout << "  Mass:  " << Cycle.thisMass[m].Mass << CR;
		SetMagnet(Cycle.thisMass[m]);
		Wait(Cycle.thisMass[m].CountTime);
		}
	}
//
//	Get the peak centers
FinishedHere = FALSE;
do {
   for(i=0;i<Cycle.NMasses;i++)
	{
	if(i == 0) { WriteMass(StartingMass); Wait(PreCycleDelay); }
	SetMagnet(Cycle.thisMass[i]);
	if(((Cycle.thisMass[i].PeakFlag) & CENTER_MASK) == CENTER)
		{
		cout << "Press any key when the position is valid!" << endl;
		while(!kbhit())
			{
			B = ReadMagnetField();
			cout << "Field: " << B;
			cout << " Mass: " << Cycle.thisMass[i].Mass;
			cout << " Count Rate: " << (Count(0.1)/0.1) << "      " << CR;
			Wait(0.1);
			Reset(Magnet);
			}
		getch();	// clear the input buffer!
		cout << endl << "Centering mass " << Cycle.thisMass[i].Mass;
		cout << " please wait!" << endl;
		//	Initialize the Peak structure
		WriteBeam(ON);
		WriteDetector(Cycle.thisMass[i].Detector);
		Peaks[i].Center = ReadMagnetField();
		Peaks[i].Width = 2;
		Peaks[i].LowSlope = 0;
		Peaks[i].HighSlope = 0;
		Peaks[i].CountRate = Count(Cycle.thisMass[i].CountTime);
		Peaks[i].CountRate /= Cycle.thisMass[i].CountTime;
		Peaks[i].Locked = FALSE;
		//	Determine the peak center precisely
		Peaks[i] = CenterPeak(Cycle.thisMass[i].CountTime,Peaks[i]);
		if(!Peaks[i].Locked)
			{
			cerr << "Peak center not found!" << endl;
			cout << "Try again? ";
			if(AskYes())
				{ i--; }
			else
				{
				cout << "Continue with next mass?" << endl;
				if(!AskYes()) { exit(0); }
				}
			}
		else
			{ Cycle.thisMass[i].Field = Peaks[i].Center; }
		}
	else
		{ Wait(Cycle.thisMass[i].CountTime); }
	}
   //	Fill in the data for the run
   for(i=0;i<Cycle.NMasses;i++)
	{
	BRef = Cycle.thisMass[i].BRefIndex;
	RefField = Cycle.thisMass[BRef].Field;
	RefMass = Cycle.thisMass[BRef].Mass;
	switch(Cycle.thisMass[i].PeakFlag&CENTER_MASK)
		{
		case CENTER:
			Cycle.thisMass[i].FieldDisp = Cycle.thisMass[i].Field -
							  RefField;
			Cycle.thisMass[i].MassDisp = FieldToMass(Cycle.thisMass[i].Field) -
							 FieldToMass(RefField);
			break;
		case FIELD_JUMP:
			Cycle.thisMass[i].Field = Cycle.thisMass[i].FieldDisp +
							  RefField;
			Cycle.thisMass[i].Mass = RefMass +
						2*Cycle.thisMass[i].FieldDisp*RefMass/RefField;
			Cycle.thisMass[i].MassDisp = Cycle.thisMass[i].Mass -
							 RefMass;
			printf("Mass: %f: field jump to: %ld (%ld + %ld)\n",
				Cycle.thisMass[i].Mass, Cycle.thisMass[i].Field,
				RefField, Cycle.thisMass[i].FieldDisp);
			break;
		case MASS_JUMP:
			Cycle.thisMass[i].Field = MassToField(RefMass +
						  Cycle.thisMass[i].MassDisp);
			Cycle.thisMass[i].FieldDisp = Cycle.thisMass[i].Field -
							  RefField;
			Cycle.thisMass[i].Mass = RefMass +
						 Cycle.thisMass[i].MassDisp;
			break;
		default:
			cerr << "Unknown Centering Flag! " << endl;
			cerr << "for mass: " << Cycle.thisMass[i].Mass << endl;
			exit(0);
		}
	}
   //	Ask to check positions
   cout << "Do you want to check the peak positions? ";
   if(!AskYes())
	{ FinishedHere = TRUE; }
   else
	{
	cout << "Hit any key to go to the next mass!" << endl;
	do {
	   for(i=0;i<Cycle.NMasses;i++)
		{
		if(i == 0)
			{ SetMagnet(StartingMass); Wait(PreCycleDelay); }
		SetMagnet(Cycle.thisMass[i]);
		do {
		   B = ReadMagnetField();
		   M = FieldToMass(B);
		   WriteMassDisplay(M);
		   cout << M << " " << B << " " << (Count(0.10)/0.01) << CR;
		   Wait(0.01);
		   Reset(Magnet);
		   } while(!kbhit());
		getch();	// Clear the input buffer
		}
	   cout << endl << "Again? ";
	   if(!AskYes())
		{ FinishedHere = TRUE; } else { FinishedHere = FALSE; }
	   } while(!FinishedHere);
	cout << "Re-center peaks?";
	if(!AskYes())
		{ FinishedHere = TRUE; } else { FinishedHere = FALSE; }
	}
   } while(!FinishedHere);
//	Run 3 cycles of auto centering
cout << "Centering Peaks!  Please Wait!" << endl;
for(c=0;c<PreCycles;c++)
	{
	for(m=0;m<Cycle.NMasses;m++)
		{
		WriteBeam(ON);
		WriteDetector(Cycle.thisMass[m].Detector);
		BRef = Cycle.thisMass[m].BRefIndex;
		RefField = Cycle.thisMass[BRef].Field;
		RefMass = Cycle.thisMass[BRef].Mass;
		ERef = Cycle.thisMass[m].ERefIndex;
		if(m == 0)
			{ SetMagnet(StartingMass); Wait(PreCycleDelay); }
		if(c == 1)
			{
			SetMagnet(Cycle.thisMass[m]);
			Wait(MAGNET_DELAY);
			if((Cycle.thisMass[m].PeakFlag & ENERGY_MASK) == ENERGYSCAN)
				{
				cout << "Energy Scan on Mass: "
					 << Cycle.thisMass[m].Mass << endl;
				//	Initialize the Energy Distribution structure
				EDist[m].VoltageOfMax = 0;
				EDist[m].TargetEdgeVoltage = p2*Cycle.thisMass[m].ESlitWidth/2;
				EDist[m].VoltageShift = 0;
				EDist[m].Locked = FALSE;
				//	Scan the distribution
				EDist[m] = AdjustEnergyDist(Cycle.thisMass[m].CountTime, EDist[m]);
				RefHVO = EDist[ERef].VoltageShift;
				WriteHVOffset(RefHVO + Measurement.thisRun[0].EOffset +
							  Cycle.thisMass[m].EOffset);
				Wait(SHV_WAIT);
				Peaks[m].CountRate = Count(Cycle.thisMass[m].CountTime)/
									 Cycle.thisMass[m].CountTime;
				}
			}
		RefHVO = EDist[ERef].VoltageShift;
		if(EDist[ERef].Locked)
			{ WriteHVOffset(RefHVO + Measurement.thisRun[0].EOffset +
					  Cycle.thisMass[m].EOffset); }
		else
			{ WriteHVOffset(Measurement.thisRun[0].EOffset +
					  Cycle.thisMass[m].EOffset); }
		Wait(SHV_WAIT);
		if(((Cycle.thisMass[m].PeakFlag) & CENTER_MASK) == CENTER)
			{
			Peaks[m] = CenterPeak(Cycle.thisMass[m].CountTime,Peaks[m]);
			//	Adjust the values for this mass
			Cycle.thisMass[m].Field = Peaks[m].Center;
			Cycle.thisMass[m].FieldDisp = Peaks[m].Center - RefField;
			}
		else
			{ SetMagnet(Cycle.thisMass[m]); Wait(Cycle.thisMass[m].CountTime); }
		}
	}
//	Ask to check positions
cout << "Do you want to check the peak positions? ";
if(AskYes())
	{
	cout << "Hit any key to go to the next mass!" << endl;
	do {
	   for(m=0;m<Cycle.NMasses;m++)
		{
		if(m == 0)
			{ SetMagnet(StartingMass); Wait(PreCycleDelay); }
		SetMagnet(Cycle.thisMass[m]);
		do {
		   B = ReadMagnetField();
		   M = FieldToMass(B);
		   WriteMassDisplay(M);
		   cout << M << " " << B << CR;
		   Reset(Magnet);
		   Wait(0.01);
		   } while(!kbhit());
		getch();	// Clear the input buffer
		}
	   cout << "Again? ";
	   if(!AskYes())
			{ FinishedHere = TRUE; } else { FinishedHere = FALSE; }
	   } while(!FinishedHere);
	}
//	Go to the lowest mass
SetMagnet(StartingMass);
Wait(PreCycleDelay);
//
//
//	Loop through the runs!
for(run=0;run<Measurement.NRuns;run++)
	{
	//
	//	Open the raw data file
	RawDataFile.open(Measurement.thisRun[run].FileName,
					 ios::out,
					 filebuf::openprot);
	//	Write the run information at the head of the file
	RawDataFile << Measurement.thisRun[run].Description << endl;
	RawDataFile << Cycle.NMasses << endl;
	RawDataFile << Measurement.thisRun[run].x << "\t"
				<< Measurement.thisRun[run].y << endl;
	for(m=0;m<Cycle.NMasses;m++)
		{
		RawDataFile << Cycle.thisMass[m].Mass << "\t"
					<< Cycle.thisMass[m].CountTime << "\t"
					<< Cycle.thisMass[m].PeakFlag << endl;
		}
	//
	//	Allocate the memory for the data
	data = allocData(Cycle.NMasses,Measurement.thisRun[run].NCycles);
	//
	//	Startup Preliminaries
	ERef = Cycle.thisMass[0].ERefIndex;
	RefHVO = EDist[ERef].VoltageShift;
	if(EDist[ERef].Locked)
		{ WriteHVOffset(RefHVO + Measurement.thisRun[run].EOffset +
					  Cycle.thisMass[0].EOffset); }
	else
		{ WriteHVOffset(Measurement.thisRun[run].EOffset +
					  Cycle.thisMass[0].EOffset); }
	MoveStageTo(Measurement.thisRun[run].x, Measurement.thisRun[run].y);
	WriteBeam(ON);
	Wait(SHV_WAIT);
	//	Wait if desired
	//	Run through hysteresis loop during this time.
	time(&StartTime);
	TimeNow = StartTime;
	while(TimeNow - StartTime < Measurement.thisRun[run].WaitTime)
	   {
	   for(m=0;m<Cycle.NMasses;m++)
		{
		if(m==0) { WriteMass(StartingMass); Wait(PreCycleDelay); }
		SetMagnet(Cycle.thisMass[m]);
		Wait(Cycle.thisMass[m].CountTime);
		}
	   time(&TimeNow);
	   }
	//	Run "PRE_CYCLES" cycles of auto centering
	//	before the measurement starts
	if(run == 0)	// don't do it for the first run (it was already done)
		{ j = 0; }
	else
		{
		j = PRE_CYCLES;
		cout << "Centering Peaks!  Please Wait!" << endl;
		}
	for(c=0;c<j;c++)
		{
		for(m=0;m<Cycle.NMasses;m++)
			{
			WriteBeam(ON);
			WriteDetector(Cycle.thisMass[m].Detector);
			BRef = Cycle.thisMass[m].BRefIndex;
			RefField = Cycle.thisMass[BRef].Field;
			RefMass = Cycle.thisMass[BRef].Mass;
			ERef = Cycle.thisMass[m].ERefIndex;
			if(m == 0)
				{ SetMagnet(StartingMass); Wait(PreCycleDelay); }
			if(c == 1)
				{
				SetMagnet(Cycle.thisMass[m]);
				Wait(MAGNET_DELAY);
				if((Cycle.thisMass[m].PeakFlag & ENERGY_MASK) == ENERGYSCAN)
					{
					//	Initialize the Energy Distribution structure
					EDist[m].VoltageOfMax = 0;
					EDist[m].TargetEdgeVoltage = p2*Cycle.thisMass[m].ESlitWidth/2;
					EDist[m].VoltageShift = 0;
					EDist[m].Locked = FALSE;
					//	Scan the distribution
					EDist[m] = AdjustEnergyDist(Cycle.thisMass[m].CountTime, EDist[m]);
					RefHVO = EDist[ERef].VoltageShift;
					WriteHVOffset(RefHVO + Measurement.thisRun[run].EOffset +
								  Cycle.thisMass[m].EOffset);
					Wait(SHV_WAIT);
					Peaks[m].CountRate = Count(Cycle.thisMass[m].CountTime)/
										 Cycle.thisMass[m].CountTime;
					}
				}
			RefHVO = EDist[ERef].VoltageShift;
			WriteHVOffset(RefHVO + Measurement.thisRun[run].EOffset +
						  Cycle.thisMass[m].EOffset);
			Wait(SHV_WAIT);
			if((Cycle.thisMass[m].PeakFlag) & CENTER_MASK == CENTER)
				{
				Peaks[m] = CenterPeak(Cycle.thisMass[m].CountTime,Peaks[m]);
				//	Adjust the values for the mass
				Cycle.thisMass[m].Field = Peaks[m].Center;
				Cycle.thisMass[m].FieldDisp = Peaks[m].Center - RefField;
				Cycle.thisMass[m].Mass = FieldToMass(Peaks[m].Center);
				Cycle.thisMass[m].MassDisp = Cycle.thisMass[m].Mass -
											 RefMass;
				}
			else
				{ SetMagnet(Cycle.thisMass[m]); Wait(Cycle.thisMass[m].CountTime); }
			}
		}
	//
	// Start the measurement
	Ccycle = FALSE;
	EScycle = FALSE;
	for(c=0;c<Measurement.thisRun[run].NCycles;c++)	// Loop through cycles
		{
		// Determine if it is a centering cycle
		if(c%Measurement.thisRun[run].CenteringInterval == 0)
			{ Ccycle = TRUE; } else { Ccycle = FALSE; }
		if(c%Measurement.thisRun[run].EScanInterval == 0)
			{ EScycle = TRUE; } else  { EScycle = FALSE; }
		SetMagnet(StartingMass);					// Go to the lowest mass
		Wait(PreCycleDelay);
		for(m=0;m<Cycle.NMasses;m++)					// Loop through masses
			{
			//	Set up references, etc for this mass
			ERef = Cycle.thisMass[m].ERefIndex;
			RefHVO = EDist[ERef].VoltageShift;
			BRef = Cycle.thisMass[m].BRefIndex;
			RefField = Cycle.thisMass[BRef].Field;
			RefMass = Cycle.thisMass[BRef].Mass;
			//	Set up machine for this mass
			WriteHVOffset(RefHVO + Measurement.thisRun[run].EOffset +
								   Cycle.thisMass[m].EOffset);
			WriteBeam(ON);
			WriteDetector(Cycle.thisMass[m].Detector);
			Wait(SHV_WAIT);
			//      Make the measurements
			if(EScycle &&
			   ((Cycle.thisMass[m].PeakFlag & ENERGY_MASK) == ENERGYSCAN))
				{										//	Scan the distribution
				SetMagnet(Cycle.thisMass[m]);
				Wait(MAGNET_DELAY);
				EDist[m] = AdjustEnergyDist(Cycle.thisMass[m].CountTime, EDist[m]);
				WriteHVOffset(RefHVO + Measurement.thisRun[run].EOffset +
							  Cycle.thisMass[m].EOffset);
				Wait(SHV_WAIT);
				Peaks[m].CountRate = Count(Cycle.thisMass[m].CountTime)/
									 Cycle.thisMass[m].CountTime;
				}
			switch((Cycle.thisMass[m].PeakFlag) & CENTER_MASK)
				{
				case CENTER:							// Center the mass
					if(Ccycle)							// if it is a centering cycle
						{
						Peaks[m] = CenterPeak(Cycle.thisMass[m].CountTime,Peaks[m]);
						// Set the new data
						data[m][c].Counts =	Peaks[m].CountRate *
											Cycle.thisMass[m].CountTime;
						data[m][c].Time = Peaks[m].Time;
						data[m][c].Field = Peaks[m].Center;
						data[m][c].EnergyShift = RefHVO +
												 Measurement.thisRun[run].EOffset +
												 Cycle.thisMass[m].EOffset;
						//	Adjust the values for the mass
						Cycle.thisMass[m].Field = Peaks[m].Center;
						Cycle.thisMass[m].FieldDisp = Peaks[m].Center - RefField;
						Cycle.thisMass[m].Mass = FieldToMass(Peaks[m].Center);
						Cycle.thisMass[m].MassDisp = Cycle.thisMass[m].Mass -
													 RefMass;
						}
					else
						{
						SetMagnet(Cycle.thisMass[m]);
						Wait(MAGNET_DELAY);
						data[m][c] = AcquireData(Cycle.thisMass[m]);
						data[m][c].EnergyShift = RefHVO +
												 Measurement.thisRun[run].EOffset +
												 Cycle.thisMass[m].EOffset;
						}
					break;
				case FIELD_JUMP:						// Referenced field jump
					// Set up values
					Cycle.thisMass[m].Field = Cycle.thisMass[m].FieldDisp +
											  RefField;
					Cycle.thisMass[m].Mass = RefMass +
						2*Cycle.thisMass[m].FieldDisp*RefMass/RefField;
					Cycle.thisMass[m].MassDisp = Cycle.thisMass[m].Mass -
												 RefMass;
					printf("Mass: %f: field jump to: %ld (%ld + %ld)\n",
						Cycle.thisMass[m].Mass, Cycle.thisMass[m].Field,
						RefField, Cycle.thisMass[m].FieldDisp);
					// Get the data
					SetMagnet(Cycle.thisMass[m]);
					Wait(MAGNET_DELAY);
					data[m][c] = AcquireData(Cycle.thisMass[m]);
					data[m][c].EnergyShift = RefHVO +
											 Measurement.thisRun[run].EOffset +
											 Cycle.thisMass[m].EOffset;
					break;
				case MASS_JUMP:							// Refernced mass jump
					// Set up values
					dM = Cycle.thisMass[m].MassDisp;
					Cycle.thisMass[m].Field = (unsigned int)(sqrt(dM/RefMass+1)*RefField + 0.5);

					Cycle.thisMass[m].FieldDisp = Cycle.thisMass[m].Field -
												  RefField;
					// Get the data
					SetMagnet(Cycle.thisMass[m]);
					Wait(MAGNET_DELAY);
					data[m][c] = AcquireData(Cycle.thisMass[m]);
					data[m][c].EnergyShift = RefHVO +
											 Measurement.thisRun[run].EOffset +
											 Cycle.thisMass[m].EOffset;

					break;
				case NO_CHECK:							// unreferenced jump
					// Get the data
					SetMagnet(Cycle.thisMass[m]);
					Wait(MAGNET_DELAY);
					data[m][c] = AcquireData(Cycle.thisMass[m]);
					data[m][c].EnergyShift = RefHVO +
											 Measurement.thisRun[run].EOffset +
											 Cycle.thisMass[m].EOffset;
					break;
				default:								// this is an error!
					cerr << "Unknown peak flag for mass: "
						 << Cycle.thisMass[m].Mass
						 << endl;
					SetMagnet(Cycle.thisMass[m]);
					Wait(MAGNET_DELAY);
					data[m][c] = AcquireData(Cycle.thisMass[m]);
					data[m][c].EnergyShift = RefHVO +
											 Measurement.thisRun[run].EOffset +
											 Cycle.thisMass[m].EOffset;
				}
			//	Write the data for this cycle
			RawDataFile	<< Cycle.thisMass[m].MassDisp << "\t"
						<< data[m][c].Field << "\t"
						<< Cycle.thisMass[m].FieldDisp << "\t"
						<< data[m][c].EnergyShift << "\t"
						<< data[m][c].Time << "\t"
						<< data[m][c].Counts << endl;
			// Show it on the screen!
			cout << run << " " << c << " "
				 << Cycle.thisMass[m].Mass << "\t"
				 << data[m][c].Field << "\t"
				 << Cycle.thisMass[m].FieldDisp << "\t"
				 << data[m][c].EnergyShift << "\t"
				 << data[m][c].Time << "\t"
				 << data[m][c].Counts << endl;
			}
		//	Showing and printing intermediate results.
		// Write something to show intermediate results!
		// A function call might be nice!
		//	Graph field and intensity if desired
		}
	//	close the data files
	RawDataFile.close();
	//	Free the memory for the run data
	freeData(data,Cycle.NMasses);
	}
free(Cycle.thisMass);
free(Measurement.thisRun);
}

int AbortRun(void)
{ exit(-1); return(-1); }

void FinishUp(void)
{
WriteBeam(OFF);
RestoreTmr();
return;
}

void Ignore(int *a)
{
cerr << "Got a floating point error! " << *a << endl;
return;
}

void CleanUp(int *a)
{
cerr << "Bye! " << *a << endl;
exit(0);
return;
}