protected void CalibrateInstrument()
    {
        try
		{
			// SGF  14-Jun-2011  INS-1732
			// Create sensor gas response objects for each sensor in the instrument
			foreach ( InstalledComponent installedComponent in _returnEvent.DockedInstrument.InstalledComponents )
			{
				if ( !( installedComponent.Component is Sensor ) )  // Skip non-sensors.
					continue;
				if ( !installedComponent.Component.Enabled )
					continue;

				Sensor sensor = (Sensor)installedComponent.Component;
				SensorGasResponse sgr = new SensorGasResponse( sensor.Uid, DateTime.UtcNow );
				sgr.GasConcentration = new GasConcentration( sensor.CalibrationGas, sensor.CalibrationGasConcentration );
                sgr.GasDetected = sensor.GasDetected;
				sgr.Type = GasResponseType.Calibrate;
				// JFC 07-Mar-2014 INS-4839
				// Recording the last calibration time before calibration to ensure it will be changed by the instrument once
				// calibration of the sensor completes.  If it does not, a status of InstrumentAborted should be assumed.
				sgr.PreCal_LastCalibrationTime = _instrumentController.GetSensorLastCalibrationTime( installedComponent.Position );

				if ( _zeroingUsedGasEndPoint != null )
					sgr.UsedGasEndPoints.Add( _zeroingUsedGasEndPoint );

				_returnEvent.GasResponses.Add( sgr );
			}

			// SGF  14-Jun-2011  INS-1732
			SensorGasResponse response = null;
			if ( _returnEvent.GasResponses.Count > 0 )
				response = _returnEvent.GasResponses[ 0 ];

			if ( _instrumentController.TestForInstrumentReset( response, "calibrating instrument, start" ) == true )
			{
				Log.Warning( "CALIBRATION: ABORTED DUE TO INSTRUMENT RESET" );
				//_returnEvent.GasResponses.Add( response ); // SGF  14-Jun-2011  INS-1732 -- responses already added to return event
				return;
			}

			// Prior to zeroing, preconditioning, and calibrating, we need to tell the
			// instrument to turn on its sensors.
			Stopwatch stopwatch = Log.TimingBegin( "CAL - TURN ON SENSORS" );
			_instrumentController.TurnOnSensors( true,true );
            Log.TimingEnd( "CAL - TURN ON SENSORS", stopwatch );

            // BEIGN INS-7657 RHP v7.5.2
            DateTime biasStateLoopStartTime = DateTime.UtcNow;
            TimeSpan biasStateElapsedTime = TimeSpan.Zero;

            while (!_instrumentController.GetSensorBiasStatus())
            {
                // Calculate the time that has elapsed since the start of the calibration loop
                biasStateElapsedTime = DateTime.UtcNow - biasStateLoopStartTime;
                Log.Debug(string.Format("{0} Time elapsed in Bias State pass = {1}", "CALIBRATION", (int)biasStateElapsedTime.TotalSeconds));

                Master.Instance.ConsoleService.UpdateState(ConsoleState.CalibratingInstrument, new string[] { string.Format(ConsoleServiceResources.ELAPSEDBIASSTATE, Math.Round(biasStateElapsedTime.TotalSeconds).ToString()) });

                if (biasStateElapsedTime.TotalSeconds > _biasStateTimeout) // Have we timed out?
                {
                    Log.Debug("CALIBRATION: ABORTED DUE TO TIMING OUT BIAS STATE CHECK");
                    throw new InstrumentNotReadyException();
                }
#if !TEST
                    // Allow a ten second interval so that we give some interval before we check the sensor Bias state again.
                    Thread.Sleep(10000);
#endif
            }
            //END DSW-7657

			if ( _instrumentController.TestForInstrumentReset( response, "calibrating instrument, after turning on sensors" ) == true )
			{
				Log.Warning( "CALIBRATION: ABORTED DUE TO INSTRUMENT RESET" );
				//_returnEvent.GasResponses.Add( response ); // SGF  14-Jun-2011  INS-1732 -- responses already added to return event
				return;
			}

			#region Check for Sensors in Error Mode

            stopwatch = Log.TimingBegin( "CAL - CHECK SENSORS ERROR MODE" );

			// SGF  Sep-15-2008  DSZ-1501 ("DS sometimes attempts to zero/calibrate MX6 sensors in 'ERR'")
			// Prior to calibrating the sensors in the instrument, we must ensure that sensors have powered 
			// up, and then we must ensure that none of the sensors go into error. Sensors were already turned on above.

			Master.Instance.SwitchService.Instrument.SensorsInErrorMode.Clear(); //Suresh 05-JAN-2012 INS-2564
			SensorPosition[] sensorPositions = _instrumentController.GetSensorPositions();

			foreach ( SensorPosition sensorPosition in sensorPositions )
			{
				if ( sensorPosition.Mode == SensorMode.Error )
				{
					string sensorPosString = sensorPosition.Position.ToString();
					Log.Warning( "CALIBRATION: SENSOR IN ERROR MODE AT POSITION " + sensorPosString );
					InstalledComponent ic = new InstalledComponent();
					ic.Component = new Sensor();
					ic.Position = sensorPosition.Position;
					Master.Instance.SwitchService.Instrument.SensorsInErrorMode.Add( ic );
				}
			}

            Log.TimingEnd( "CAL - CHECK SENSORS ERROR MODE", stopwatch );

			if ( Master.Instance.SwitchService.Instrument.SensorsInErrorMode.Count > 0 )
				throw new SensorErrorModeException( "The calibration failed due to sensor being in error.  Instrument: " + _returnEvent.DockedInstrument.SerialNumber + " ." );

			#endregion
             
			// Clear the gases in the lines.
            stopwatch = Log.TimingBegin( "CAL - PURGE(INITIAL)" );
			new InstrumentPurgeOperation( PurgeType.PreCalibration, _instrumentController, GasEndPoints, _returnEvent ).Execute();
            Log.TimingEnd( "CAL - PURGE(INITIAL)", stopwatch );

			if ( _instrumentController.TestForInstrumentReset( response, "calibrating instrument, after clearing gases" ) == true )
			{
				Log.Warning( "CALIBRATION: ABORTED DUE TO INSTRUMENT RESET" );
				//_returnEvent.GasResponses.Add(response); // SGF  14-Jun-2011  INS-1732 -- responses already added to return event
				return;
			}

			// Zero the sensor before proceeding.
            stopwatch = Log.TimingBegin( "CAL - ZEROING" );
			ZeroSensors( _returnEvent.DockedInstrument.InstalledComponents );
            Log.TimingEnd( "CAL - ZEROING", stopwatch );

			if ( _instrumentController.TestForInstrumentReset( response, "calibrating instrument, after zeroing" ) == true )
			{
				Log.Warning( "CALIBRATION: ABORTED DUE TO INSTRUMENT RESET" );
				//_returnEvent.GasResponses.Add(response); // SGF  14-Jun-2011  INS-1732 -- responses already added to return event
				return;
			}

            //Clear if any flags before initiating calibration once again since this would be set to true during Pre-Calibration Purge
            Pump.IsBadPumpTubing = false;

            if ( _returnEvent.DockedInstrument.Type == DeviceType.TX1
            ||   _returnEvent.DockedInstrument.Type == DeviceType.VPRO
            ||   _returnEvent.DockedInstrument.Type == DeviceType.SC  )
			{
				CalibrateInstrumentParallel(); // Also known as "quick cal".
			}
			else
			{
				CalibrateInstrumentSequential();
			}            

			// Wipe out most data that will be uploaded to iNet when sensor calibration was aborted by the instrument.
			for ( int i = 0; i < _returnEvent.GasResponses.Count; i++ )
			{
				if ( _returnEvent.GasResponses[ i ].Status == Status.InstrumentAborted )
				{
					_returnEvent.GasResponses[ i ] = SensorGasResponse.CreateInstrumentAbortedSensorGasResponse( _returnEvent.GasResponses[ i ] );
				}
			}
		}
		catch ( CorrectCalibrationGasUnavailable ccgu )
		{
			Log.Warning( Name + ": Calibration gas unavailable", ccgu );
			throw;
		}
		catch ( FlowFailedException ffe )
		{
			Log.Warning( Name + ": Flow failed", ffe );
			throw;
		}
		catch ( SensorErrorModeException )
		{
			Log.Warning( Name + ": SensorErrorModeException thrown." );
			throw;
		}
		catch ( ISC.Instrument.Driver.CommunicationAbortedException cae )
		{
			throw new InstrumentNotDockedException( cae );
		}
		catch ( InstrumentNotDockedException )
		{
			throw;
		}
		catch ( ISC.Instrument.Driver.SystemAlarmException sae ) // some instruments may throw this during sensor warmup.
		{
			throw new InstrumentSystemAlarmException( Master.Instance.SwitchService.Instrument.SerialNumber, sae.ErrorCode );
		}
        // INS-7657 RHP v7.5.2 Display Instrument Not Ready Message to be specific that the error is due to Sesnor not biased within 2 hours
        catch (InstrumentNotReadyException inr)
        {
            throw new InstrumentNotReadyException(inr);
        }
		catch ( Exception e )
		{
			throw new FailedCalibrationException( e );
		}
        finally
        {            
            // Make sure we turn off instrument pump before leave.  It may be still on
            // if the reason we're in this finally block is due to a thrown exception.
            _instrumentController.EnablePump( false ); // This call will first check if instrument is docked.

            if(Master.Instance.SwitchService.BadPumpTubingDetectedDuringCal)
                Master.Instance.ConsoleService.UpdateState(ConsoleState.CalibrationStoppedCheckTubing);
            else
                // Clear the reference to a step in the calibration process
                Master.Instance.ConsoleService.UpdateState( ConsoleState.CalibratingInstrument );
        }
    }