/*******************************************************************************
 *  Copyright 2017-2018 Centre for Development of Advanced Computing(C-DAC), Pune
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package cdac.medinfo.sdk.dcm30_04.dicommodel.modules;



import cdac.medinfo.sdk.dcm30_04.baselibs.Tag;
import cdac.medinfo.sdk.dcm30_04.commoninterface.IDataSet;
import cdac.medinfo.sdk.dcm30_04.commoninterface.ITag;
import cdac.medinfo.sdk.dcm30_04.enums.EnumCoverageofkSpace;
import cdac.medinfo.sdk.dcm30_04.enums.EnumEchoPlanarPulseSequence;
import cdac.medinfo.sdk.dcm30_04.enums.EnumEchoPulseSequence;
import cdac.medinfo.sdk.dcm30_04.enums.EnumGeometryofk_SpaceTraversal;
import cdac.medinfo.sdk.dcm30_04.enums.EnumImageType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumMRAcquisitionType;
import cdac.medinfo.sdk.dcm30_04.enums.EnumMultiplanarExcitation;
import cdac.medinfo.sdk.dcm30_04.enums.EnumMultipleSpinEcho;
import cdac.medinfo.sdk.dcm30_04.enums.EnumOversamplingPhase;
import cdac.medinfo.sdk.dcm30_04.enums.EnumPhaseContrast;
import cdac.medinfo.sdk.dcm30_04.enums.EnumRectilinearPhaseEncodeReordering;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSaturationRecovery;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSegmentedkSpaceTraversal;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSpectrallySelectedSuppression;
import cdac.medinfo.sdk.dcm30_04.enums.EnumSteadyStatePulseSequence;
import cdac.medinfo.sdk.dcm30_04.enums.EnumTimeofFlightContrast;

import cdac.medinfo.sdk.dcm30_04.exceptions.ConditionFailedException;
import cdac.medinfo.sdk.dcm30_04.exceptions.InvalidModuleException;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConfig;
import cdac.medinfo.sdk.dcm30_04.utils.DicomConstants;
import cdac.medinfo.sdk.dcm30_04.utils.DicomLogger;
import cdac.medinfo.sdk.dcm30_04.utils.ISingleCollection;
import cdac.medinfo.sdk.dcm30_04.utils.SingleCollection;

// TODO: Auto-generated Javadoc
/**
 \* This module specifies the attributes of the MR Pulse Sequence Module.
 * 
 * 
 */

public class MRPulseSequenceModule extends Module  
{


	/**
	 * The obj single collection.
	 */
	public static ISingleCollection<ITag> objSingleCollection = null;


	/**
	 * Instantiates a new mR pulse sequence module.
	 * 
	 * @param objIDataSet the obj i data set
	 */
	public MRPulseSequenceModule(IDataSet objIDataSet)
	{
		super(objIDataSet);
	}

	static
	{
		objSingleCollection = new SingleCollection<ITag>();
		objSingleCollection.add(new Tag(0x0018,0x0023));
		objSingleCollection.add(new Tag(0x0018,0x9005));
		objSingleCollection.add(new Tag(0x0018,0x9008));
		objSingleCollection.add(new Tag(0x0018,0x9011));
		objSingleCollection.add(new Tag(0x0018,0x9012));
		objSingleCollection.add(new Tag(0x0018,0x9014));
		objSingleCollection.add(new Tag(0x0018,0x9015));
		objSingleCollection.add(new Tag(0x0018,0x9017));
		objSingleCollection.add(new Tag(0x0018,0x9018));
		objSingleCollection.add(new Tag(0x0018,0x9024));
		objSingleCollection.add(new Tag(0x0018,0x9025));
		objSingleCollection.add(new Tag(0x0018,0x9029));
		objSingleCollection.add(new Tag(0x0018,0x9032));
		objSingleCollection.add(new Tag(0x0018,0x9033));
		objSingleCollection.add(new Tag(0x0018,0x9034));
		objSingleCollection.add(new Tag(0x0018,0x9093));
		objSingleCollection.add(new Tag(0x0018,0x9094));
	}

	/**
	 * This method validates each Attribute in the Module according to the Type
	 * of the Attribute.Attributes are of 5 types.
	 * Type 1,Type 2 are Mandatory:
	 * Mandatory Attributes have to present in the Module.
	 * Type 1C,2C are Conditional:
	 * Conditional Attributes' presence depend on a condition.
	 * If the condition is satisfied the Attribute has to be present.
	 * Type 3 are Optional
	 * Optional Attributes can be added as and when required.
	 * 
	 * @return - returns validation status as success or failure.
	 * 
	 * @throws InvalidModuleException - If validation of Module fails.
	 */
	public  boolean validateModule() throws InvalidModuleException
	{

		try
		{
			EnhancedMRImageModule objEnhancedMRImageModule = new EnhancedMRImageModule(objIDataSet);
			String[] arrStrImageType = objEnhancedMRImageModule.getImageType();
			if(arrStrImageType != null)
			{
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x9005)))
					throw new ConditionFailedException("Cardiac Synchronization Technique (0018,9005) should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x0023)))
					throw new ConditionFailedException("MR Acquisition Type (0018,0023) should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x9008))) 
					throw new ConditionFailedException("0018,9008 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if(isPresent(0x0018, 0x9011)) 
				{
					if(arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))
					{		
						if(!(getEchoPulseSequence().equalsIgnoreCase(EnumEchoPulseSequence.SPIN.getValue())||getEchoPulseSequence().equalsIgnoreCase(EnumEchoPulseSequence.BOTH.getValue())))
							throw new ConditionFailedException("(0018,9011) should be present if Image Type(0008,0008) is ORIGINAL or MIXED or DERIVED and " +
							"Echo Pulse Sequence value is SPIN or BOTH");
					}
				}
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x9012))) 
					throw new ConditionFailedException("0018,9012 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))&& (!isPresent(0x0018, 0x9014))) 
					throw new ConditionFailedException("0018,9014 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if(isPresent(0x0018, 0x9015) && !(arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))) 
					throw new ConditionFailedException("0018,9015 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))&& (!isPresent(0x0018, 0x9017))) 
					throw new ConditionFailedException("0018,9017 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))&& (!isPresent(0x0018, 0x9018))) 
					throw new ConditionFailedException("0018,9018 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))&&(!isPresent(0x0018, 0x9024))) 
					throw new ConditionFailedException("0018,9024 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) &&(!isPresent(0x0018, 0x9025))) 
					throw new ConditionFailedException("0018,9025 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x9029))) 
					throw new ConditionFailedException("0018,9029 should be present if Image Type(0008,0008) is ORIGINAL or MIXED"); 
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x9032))) 
					throw new ConditionFailedException("0018,9032 should be present if Image Type(0008,0008) is ORIGINAL or MIXED"); 

				/* 0x0018, 0x9034 Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Geometry of k-Space Traversal (0018,9032) equals RECTILINEAR.
				 * Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Geometry of k-Space Traversal (0018,9032) equals RECTILINEAR.
				 * The otherwise may be conditon is removed as it is not the required one. We have not checked for may be conditions.
				 */
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())))
				{
					if(getGeometryOfKSpaceTraversal().equalsIgnoreCase(EnumGeometryofk_SpaceTraversal.RECTILINEAR.getValue()) && (!isPresent(0x0018, 0x9034)))
						throw new ConditionFailedException("0018,9034 should be present if Image Type(0008,0008) is ORIGINAL or MIXED and value of Geometry Of K-Space Traversal(0018,9032) should be RECTILINEAR");
				}

				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())) && (!isPresent(0x0018, 0x9033))) 
					throw new ConditionFailedException("0018,9033 should be present if Image Type(0008,0008) is ORIGINAL or MIXED"); 

				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue())))
				{
					if(getMRAcquisitionType().equalsIgnoreCase(EnumMRAcquisitionType.THREE_D.getValue()) && (!isPresent(0x0018, 0x9094)))
						throw new ConditionFailedException("0018,9094 should be present if Image Type(0008,0008) is ORIGINAL or MIXED and value of Geometry Of K-Space Traversal(0018,9032) should be RECTILINEAR");
				}
				if((arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.ORIGINAL.getValue())||arrStrImageType[0].equalsIgnoreCase(EnumImageType.Value1.MIXED.getValue()))&& (!isPresent(0x0018, 0x9093))) 
					throw new ConditionFailedException("0018,9093 should be present if Image Type(0008,0008) is ORIGINAL or MIXED");
			}

		}
		catch(ConditionFailedException cfe)
		{
			if(DicomConfig.createInstance().isLoggingOn())
				DicomLogger.getLogger().log(cfe.getMessage());

			
				throw new InvalidModuleException(this.getClass().getSimpleName(),cfe);

		}
		return true;
	}

	/**
	 * Sets name of the pulse sequence for annotation purposes. Potentially vendorspecific name.
	 * 
	 * @param strPulseSequenceName - String value of Pulse Sequence Name.
	 */
	public void setPulseSequenceName(String strPulseSequenceName)
	{
		/* Accept Pulse Sequence Name in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9005, DicomConstants.DCM_DT_SH, strPulseSequenceName);
	}

	/**
	 * Retrieves name of the pulse sequence for annotation purposes.
	 * 
	 * @return String - String value of Pulse Sequence Name.
	 */
	public String getPulseSequenceName()
	{
		Object objectValue = getValue(0x0018, 0x9005);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Identification of spatial data encoding scheme.
	 * Defined Terms: 1D,2D,3D.
	 * 
	 * @param enumMRAcquisitionType - enum value of MR Acquisition Type.
	 */
	public void setMRAcquisitionType(EnumMRAcquisitionType enumMRAcquisitionType)
	{
		/*Accept MR Acquisition Type in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x0023, DicomConstants.DCM_DT_CS, enumMRAcquisitionType.getValue());
	}

	/**
	 * Return Identification of data encoding scheme.
	 * 
	 * @return String - String value of MR Acquisition Type.
	 */
	public String getMRAcquisitionType()
	{
		Object objectValue = getValue(0x0018, 0x0023);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Echo category of pulse sequences.
	 * Enumerated Values:
	 * 1) SPIN.
	 * 2) GRADIENT.
	 * 3) BOTH.
	 * 
	 * @param enumEchoPulseSequence - Enum value of Echo Pulse Sequence.
	 */
	public void setEchoPulseSequence(EnumEchoPulseSequence enumEchoPulseSequence)
	{
		/*Accept Echo Pulse Sequence in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9008, DicomConstants.DCM_DT_CS, enumEchoPulseSequence.getValue());
	}

	/**
	 * Return Echo category of pulse sequences.
	 * 
	 * @return String - String value of Echo Pulse Sequence.
	 */
	public String getEchoPulseSequence()
	{
		Object objectValue = getValue(0x0018, 0x9008);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Multiple Spin Echo category of pulse sequence used to collect different lines in k-space for a single frame.
	 * numerated Values: YES,NO.
	 * 
	 * @param enumMultipleSpinEcho - enum value of Multiple Spin Echo.
	 */
	public void setMultipleSpinEcho(EnumMultipleSpinEcho enumMultipleSpinEcho)
	{
		/*Accept Multiple Spin Echo in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9011, DicomConstants.DCM_DT_CS, enumMultipleSpinEcho.getValue());
	}

	/**
	 * Return Multiple Spin Echo category of pulse sequence used to collect different lines in k-space for a single frame.
	 * 
	 * @return String - String value of Multiple Spin Echo.
	 */
	public String getMultipleSpinEcho()
	{
		Object objectValue = getValue(0x0018, 0x9011);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets technique that simultaneously excites several volumes.
	 * Enumerated Values: YES,NO.
	 * 
	 * @param enumMultiPlanarExcitation - Enum value of Multi-planar Excitation.
	 */
	public void setMultiPlanarExcitation(EnumMultiplanarExcitation enumMultiPlanarExcitation)
	{
		/*Accept Multi-planar Excitation in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9012, DicomConstants.DCM_DT_CS, enumMultiPlanarExcitation.getValue());
	}

	/**
	 * Return technique that simultaneously excites several volumes.
	 * 
	 * @return String - String value of Multi-planar Excitation.
	 */
	public String getMultiPlanarExcitation()
	{
		Object objectValue = getValue(0x0018, 0x9012);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets phase contrast Pulse sequence is a pulse sequence in which the flowing spins are velocity encoded in phase.
	 * Enumerated Values: YES,NO.
	 * 
	 * @param enumPhaseContrast - enum value of Phase Contrast.
	 */
	public void setPhaseContrast(EnumPhaseContrast enumPhaseContrast)
	{
		/*Accept Phase Contrast in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9014, DicomConstants.DCM_DT_CS, enumPhaseContrast.getValue());
	}

	/**
	 * Return phase contrast Pulse sequence is a pulse sequence in which the flowing spins are velocity encoded in phase.
	 * 
	 * @return String - String value of Phase Contrast.
	 */
	public String getPhaseContrast()
	{
		Object objectValue = getValue(0x0018, 0x9014);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Time of Flight contrast is created by the inflow of blood in the saturated plane.
	 * Enumerated Values: YES,NO.
	 * 
	 * @param enumTimeOfFlightContrast - Enum value of  Time of Flight Contrast.
	 */
	public void setTimeOfFlightContrast(EnumTimeofFlightContrast enumTimeOfFlightContrast)
	{
		/*Accept Time of Flight Contrast in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9015, DicomConstants.DCM_DT_CS,  enumTimeOfFlightContrast.getValue());
	}

	/**
	 * Return Time of Flight contrast is created by the inflow of blood in the saturated plane.
	 * 
	 * @return String - String value of  Time of Flight Contrast.
	 */
	public String getTimeOfFlightContrast()
	{
		Object objectValue = getValue(0x0018, 0x9015);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Steady State Sequence.
	 * Defined Terms:
	 * 1) FREE_PRECESSION.
	 * 2) TRANSVERSE.
	 * 3) TIME_REVERSED.
	 * 4) LONGITUDINAL.
	 * 5) NONE.
	 * 
	 * @param enumSteadyStatePulseSequence - Enum value of Steady State Pulse Sequence.
	 */
	public void setSteadyStatePulseSequence(EnumSteadyStatePulseSequence enumSteadyStatePulseSequence)
	{
		/*Accept Steady State Pulse Sequence in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9017, DicomConstants.DCM_DT_CS, enumSteadyStatePulseSequence.getValue());
	}

	/**
	 * Return Steady State Pulse Sequence.
	 * 
	 * @return String - String value of Steady State Pulse Sequence.
	 */
	public String getSteadyStatePulseSequence()
	{
		Object objectValue = getValue(0x0018, 0x9017);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Echo Planar category of Pulse Sequences.
	 * Enumerated Values: YES,NO.
	 * 
	 * @param enumEchoPlanarPulseSequence - Enum value of Echo Planar Pulse Sequence.
	 */
	public void setEchoPlanarPulseSequence(EnumEchoPlanarPulseSequence enumEchoPlanarPulseSequence)
	{
		/*Accept Echo Planar Pulse Sequence in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9018, DicomConstants.DCM_DT_CS, enumEchoPlanarPulseSequence.getValue());
	}

	/**
	 * Return Echo Planar Pulse Sequence.
	 * 
	 * @return String - String value of Echo Planar Pulse Sequence.
	 */
	public String getEchoPlanarPulseSequence()
	{
		Object objectValue = getValue(0x0018, 0x9018);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Saturation recovery pulse sequence.
	 * Enumerated Values: YES,NO.
	 * 
	 * @param enumSaturationRecovery the enum saturation recovery
	 */
	public void setSaturationRecovery(EnumSaturationRecovery enumSaturationRecovery)
	{
		/*Accept Saturation Recovery in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9024, DicomConstants.DCM_DT_CS, enumSaturationRecovery.getValue());
	}

	/**
	 * Return Saturation recovery pulse sequence.
	 * 
	 * @return String - String value of Saturation Recovery.
	 */
	public String getSaturationRecovery()
	{
		Object objectValue = getValue(0x0018, 0x9024);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets spectrally Selected Suppression.
	 * Defined Terms:
	 * 1) FAT.
	 * 2) WATER.
	 * 3) FAT_AND_WATER.
	 * 4) SILICON_GEL.
	 * 5) NONE.
	 * 
	 * @param enumSpectrallySelectedSuppression - Enum value of spectrally Selected Suppression.
	 */
	public void setSpectrallySelectedSuppression(EnumSpectrallySelectedSuppression enumSpectrallySelectedSuppression)
	{
		/*Accept Spectrally Selected Suppression in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9025, DicomConstants.DCM_DT_CS, enumSpectrallySelectedSuppression.getValue());
	}

	/**
	 * Return Spectrally Selected Suppression.
	 * 
	 * @return String - String value of Spectrally Selected Suppression.
	 */
	public String getSpectrallySelectedSuppression()
	{
		Object objectValue = getValue(0x0018, 0x9025);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Oversampling Phase.
	 * Enumerated Values:
	 * 1) 2D = phase direction
	 * 2) 3D = out of plane direction
	 * 3) 2D_3D = both.
	 * 4) NONE.
	 * 
	 * @param enumOversamplingPhase - Enum value of Oversampling Phase.
	 */
	public void setOversamplingPhase(EnumOversamplingPhase enumOversamplingPhase)
	{
		/*Accept Oversampling Phase in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9029, DicomConstants.DCM_DT_CS, enumOversamplingPhase.getValue());
	}

	/**
	 * Return  Oversampling Phase.
	 * 
	 * @return String - String value of Oversampling Phase.
	 */
	public String getOversamplingPhase()
	{
		Object objectValue = getValue(0x0018, 0x9029);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Geometry category of k-Space traversal.
	 * Defined Terms:
	 * 1) RECTILINEAR.
	 * 2) RADIAL.
	 * 3) SPIRAL.
	 * 
	 * @param enumGeometryOfKSpaceTraversal - Enum value of Geometry of k-Space Traversal.
	 */
	public void setGeometryOfKSpaceTraversal(EnumGeometryofk_SpaceTraversal enumGeometryOfKSpaceTraversal)
	{
		/*Accept Geometry of k-Space Traversal in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9032, DicomConstants.DCM_DT_CS, enumGeometryOfKSpaceTraversal.getValue());
	}

	/**
	 * Return Geometry category of k-Space traversal.
	 * 
	 * @return String - String value of Geometry of k-Space Traversal.
	 */
	public String getGeometryOfKSpaceTraversal()
	{
		Object objectValue = getValue(0x0018, 0x9032);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Rectilinear phase encode reordering.
	 * Defined Terms:
	 * 1) LINEAR.
	 * 2) CENTRIC.
	 * 3) SEGMENTED.
	 * 4) REVERSE_LINEAR.
	 * 5) REVERSE_CENTRIC.
	 * 
	 * @param enumRectilinearPhaseEncodeReordering - Enum value of Rectilinear Phase Encode Reordering.
	 */
	public void setRectilinearPhaseEncodeReordering(EnumRectilinearPhaseEncodeReordering enumRectilinearPhaseEncodeReordering)
	{
		/*Accept Rectilinear Phase Encode Reordering in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9034, DicomConstants.DCM_DT_CS, enumRectilinearPhaseEncodeReordering.getValue());
	}

	/**
	 * Return Rectilinear phase encode reordering.
	 * 
	 * @return String - String value of Rectilinear Phase Encode Reordering.
	 */
	public String getRectilinearPhaseEncodeReordering()
	{
		Object objectValue = getValue(0x0018, 0x9034);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}

	/**
	 * Sets Segmented k-Space traversal. If Geometry of k-Space Traversal is rectilinear, multiple lines can be acquired
	 * at one time. If Geometry of k-Space Traversal is spiral or radial, paths can be interleaved and acquired at one time.
	 * Enumerated Values:
	 * 1) SINGLE = successive single echo coverage.
	 * 2) PARTIAL = segmented coverage.
	 * 3) FULL = single shot full coverage.
	 * 
	 * @param enumSegmentedKSpaceTraversal - enum value of Segmented k-Space Traversal.
	 */
	public void setSegmentedKSpaceTraversal(EnumSegmentedkSpaceTraversal enumSegmentedKSpaceTraversal)
	{
		/*Accept Segmented k-Space Traversal in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9033, DicomConstants.DCM_DT_CS, enumSegmentedKSpaceTraversal.getValue());
	}

	/**
	 * Return Segmented k-Space traversal.
	 * 
	 * @return String - String value of Segmented k-Space Traversal.
	 */
	public String getSegmentedKSpaceTraversal()
	{
		Object objectValue = getValue(0x0018, 0x9033);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}


	/**
	 * Sets Coverage of k-Space in the ky-kz plane.
	 * Defined Terms:
	 * 1) FULL.
	 * 2) ELLIPTICAL.
	 * 3) WEIGHTED.
	 * 
	 * @param enumCoverageOfKSpace - Enum value of Coverage of k-Space.
	 */
	public void setCoverageOfKSpace(EnumCoverageofkSpace enumCoverageOfKSpace)
	{
		/*Accept Coverage of k-Space in String format of type CS.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9094, DicomConstants.DCM_DT_CS, enumCoverageOfKSpace.getValue());
	}

	/**
	 * Return Coverage of k-Space.
	 * 
	 * @return String - String value of Coverage of k-Space.
	 */
	public String getCoverageOfKSpace()
	{
		Object objectValue = getValue(0x0018, 0x9094);
		if(objectValue!=null)
			return objectValue.toString();
		return null;
	}


	/**
	 * Sets Number of k-Space Trajectories.
	 * 
	 * @param shNumberOfKSpaceTrajectories - short value of Number of k-Space Trajectories.
	 */
	public void setNumberOfKSpaceTrajectories(short shNumberOfKSpaceTrajectories)
	{
		/*Accept Number of k-Space Trajectories in String format of type US.
		 * Read the Transfer Syntax and check if ImplicitDE or ExplicitDE to create.
		 * Set the iGroupNumber and iElementNumber to ImplicitDE object 
		 * Set the iVRType
		 * Set length from the element
		 * Add this element to the Hash Map
		 */
		addDataElement(0x0018, 0x9093, DicomConstants.DCM_DT_US, shNumberOfKSpaceTrajectories);
	}

	/**
	 * Return Number of interleaves or shots.
	 * 
	 * @return short - short value of Number of k-Space Trajectories.
	 */
	public short getNumberOfKSpaceTrajectories()
	{
		Object objectValue = getValue(0x0018, 0x9093);
		if(objectValue!=null)
			return Short.parseShort(objectValue.toString());
		return DicomConstants.DCM_NO_VALUE;
	}

	/**
	 * This method returns the collection of keys representing the DataElements
	 * that belong to this module.
	 * 
	 * @return collection of Tags - returns the collection of tags
	 */
	public ISingleCollection<ITag> getVectorOfKeys()
	{
		return objSingleCollection;
	}
}
