/// <summary> /// Query the Information Model using the given query message. /// </summary> /// <param name="queryMessage">Message used to query the Information Model.</param> /// <returns>DicomMessageCollection - containing the query responses. The final query response (without a dataset) is also included.</returns> public DicomMessageCollection QueryInformationModel(DicomMessage queryMessage) { DicomMessageCollection responseMessages = new DicomMessageCollection(); DvtkHighLevelInterface.Dicom.Other.Values values = queryMessage.CommandSet["0x00000002"].Values; System.String sopClassUid = values[0]; DataSet queryDataset = queryMessage.DataSet; Dvtk.Dicom.InformationEntity.DataSetCollection queryResponses = _root.QueryInformationModel(queryDataset.DvtkDataDataSet); DvtkData.Dimse.DicomMessage dvtkDicomMessage = null; DvtkData.Dimse.CommandSet dvtkCommand = null; DicomMessage responseMessage = null; if (queryResponses != null) { foreach (DvtkData.Dimse.DataSet dvtkDataset in queryResponses) { dvtkDicomMessage = new DvtkData.Dimse.DicomMessage(); dvtkCommand = new DvtkData.Dimse.CommandSet(DvtkData.Dimse.DimseCommand.CFINDRSP); dvtkCommand.AddAttribute(0x0000, 0x0002, DvtkData.Dimse.VR.UI, sopClassUid); dvtkCommand.AddAttribute(0x0000, 0x0900, DvtkData.Dimse.VR.US, 0xFF00); dvtkDicomMessage.Apply(dvtkCommand, dvtkDataset, queryMessage.EncodedPresentationContextID); responseMessage = new DicomMessage(dvtkDicomMessage); responseMessages.Add(responseMessage); } } dvtkDicomMessage = new DvtkData.Dimse.DicomMessage(); dvtkCommand = new DvtkData.Dimse.CommandSet(DvtkData.Dimse.DimseCommand.CFINDRSP); dvtkCommand.AddAttribute(0x0000, 0x0002, DvtkData.Dimse.VR.UI, sopClassUid); dvtkCommand.AddAttribute(0x0000, 0x0900, DvtkData.Dimse.VR.US, 0x0000); dvtkDicomMessage.Apply(dvtkCommand, queryMessage.EncodedPresentationContextID); responseMessage = new DicomMessage(dvtkDicomMessage); responseMessages.Add(responseMessage); return(responseMessages); }
/// <summary> /// Overridden C-FIND-RQ message handler that makes use of the appropriate Information Model to handle the query. /// </summary> /// <param name="queryMessage">C-FIND-RQ Identifier (Dataset) containing query attributes.</param> /// <returns>Boolean - true if dicomMessage handled here.</returns> public override bool HandleCFindRequest(DicomMessage queryMessage) { // Query response messages DicomMessageCollection responseMessages = new DicomMessageCollection(); DvtkHighLevelInterface.Dicom.Other.Values values = queryMessage.CommandSet["0x00000002"].Values; System.String sopClassUid = values[0]; DicomMessage responseMessage = null; foreach (DataSet randomDataset in randomizedDatasets) { responseMessage = new DicomMessage(DvtkData.Dimse.DimseCommand.CFINDRSP); responseMessage.CommandSet.Set("0x00000002", DvtkData.Dimse.VR.UI, sopClassUid); responseMessage.CommandSet.Set("0x00000900", DvtkData.Dimse.VR.US, 0xFF00); responseMessage.DataSet.CloneFrom(randomDataset); responseMessages.Add(responseMessage); } responseMessage = new DicomMessage(DvtkData.Dimse.DimseCommand.CFINDRSP); responseMessage.CommandSet.Set("0x00000002", DvtkData.Dimse.VR.UI, sopClassUid); responseMessage.CommandSet.Set("0x00000900", DvtkData.Dimse.VR.US, 0x0000); responseMessages.Add(responseMessage); // handle responses foreach (DicomMessage rspMessage in responseMessages) { try { int waitedTime = 0; // Check for cancel message from SCU if (WaitForPendingDataInNetworkInputBuffer(100, ref waitedTime)) { DicomMessage cancelRq = ReceiveDicomMessage(); if (cancelRq.CommandSet.DimseCommand == DvtkData.Dimse.DimseCommand.CCANCELRQ) { // set up the C-FIND-RSP with cancel status DicomMessage respMessage = new DicomMessage(DvtkData.Dimse.DimseCommand.CFINDRSP); respMessage.Set("0x00000900", DvtkData.Dimse.VR.US, 0xFE00); // send the response this.Send(respMessage); break; } } this.Send(rspMessage); } catch (Exception) { string theErrorText = "DICOM Connection Error: RIS Emulator is failed to send the C-FIND-RSP."; WriteError(theErrorText); } } // message handled return(true); }
/// <summary> /// Adds a single attribute with the tag sequence, VR and values specified. /// </summary> /// <remarks> /// If an attribute already exists with this tag, it is removed first before it is again /// added. /// <br></br><br></br> /// If sequence items (each with a sequence item index) are specified in the tag sequence, /// empty sequence items will be added automatically to avoid gaps in the sequence items of sequence /// attributes. /// </remarks> /// <param name="tagSequence">The tag sequence of the attribute.</param> /// <param name="vR">The VR of the attribute.</param> /// <param name="values">The values, which will be copied from another attribute, for this attribute.</param> /// <exception cref="System.ArgumentException"> /// <paramref name="dvtkDataTag"/> is not valid for setting an attribute.<br></br> /// -or-<br></br> /// <paramref name="dvtkDataTag"/> is not valid for setting a CommandSet attribute.<br></br> /// </exception> /// <exception cref="System.ArgumentNullException"> /// <paramref name="values"/> is a null reference. /// </exception> public override void Set(String tagSequence, VR vR, Values values) { TagSequence internalTagSequence = new TagSequence(tagSequence); // // Sanity checks. // if (!internalTagSequence.IsSingleAttributeMatching) { throw new ArgumentException(internalTagSequence.ToString() + " not valid for setting an attribute."); } // Check if the tag supplied is valid for a CommandSet. if (!internalTagSequence.IsValidForCommandSet) { throw new ArgumentException(internalTagSequence.ToString() + " not valid for setting a CommandSet attribute.", "dvtkDataTag"); } if (values == null) { throw new ArgumentNullException("values"); } // // Perform the actual operation in the base class. // Set(internalTagSequence, vR, values); }
/// <summary> /// Adds a single attribute with the tag, VR and values specified. /// </summary> /// <remarks> /// If an attribute already exists with this tag, it is removed first before it is again /// added. /// </remarks> /// <param name="dvtkDataTag">The tag of the attribute.</param> /// <param name="vR">The VR of the attribute.</param> /// <param name="values">The values, which will be copied from another attribute, for this attribute.</param> /// <exception cref="System.ArgumentException"> /// <paramref name="dvtkDataTag"/> is not valid for setting a CommandSet attribute.<br></br> /// </exception> /// <exception cref="System.ArgumentNullException"> /// <paramref name="values"/> is a null reference. /// </exception> public override void Set(DvtkData.Dimse.Tag dvtkDataTag, VR vR, Values values) { TagSequence internalTagSequence = new TagSequence(); internalTagSequence.Add(new Tag(dvtkDataTag.GroupNumber, dvtkDataTag.ElementNumber)); // // Sanity checks. // // Check if the tag supplied is valid for a CommandSet. if (!internalTagSequence.IsValidForCommandSet) { throw new ArgumentException(internalTagSequence.ToString() + " is not valid for setting a CommandSet attribute.", "dvtkDataTag"); } if (values == null) { throw new ArgumentNullException("values"); } // // Perform the actual operation in the base class. // Set(internalTagSequence, vR, values); }
public override bool HandleCMoveRequest(DicomMessage retrieveMessage) { // try to get the SOP Class Uid so that we know which Information Model to use. DvtkHighLevelInterface.Dicom.Other.Values values = retrieveMessage.CommandSet["0x00000002"].Values; System.String sopClassUid = values[0]; DvtkData.Dul.AbstractSyntax abstractSyntax = new DvtkData.Dul.AbstractSyntax(sopClassUid); // try to get the Move Destination AE. values = retrieveMessage.CommandSet["0x00000600"].Values; string vr = retrieveMessage.CommandSet["0x00000600"].VR.ToString(); System.String moveDestinationAE = values[0]; string hexString = moveDestinationAE; System.Text.StringBuilder sb = new System.Text.StringBuilder(); if (DicomThread.Options.LoadedDefinitionFileNames.Length < 10) { WriteWarning("Some of the definition files is not loaded properly."); } if (vr == "UN") { for (int i = 0; i <= hexString.Length - 2; i += 2) { sb.Append(Convert.ToString(Convert.ToChar(Int32.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.HexNumber)))); } } else if (vr == "AE") { sb.Append(moveDestinationAE); } if (moveDestinationAE == null || moveDestinationAE == "") { DicomMessage responseMessage = new DicomMessage(DvtkData.Dimse.DimseCommand.CMOVERSP); responseMessage.Set("0x00000900", VR.US, 0xA801); responseMessage.Set("0x00000902", VR.LO, "Unknown Move Destination"); this.Send(responseMessage); return(true); } MoveAEdetailsIndex = FindMoveAEDetails(sb.ToString()); if (IsHaveMoveDestinations && MoveAEdetailsIndex == -1) { DicomMessage responseMessage = new DicomMessage(DvtkData.Dimse.DimseCommand.CMOVERSP); responseMessage.Set("0x00000900", VR.US, 0xA801); responseMessage.Set("0x00000902", VR.LO, "Move Destination not registered in SCP"); this.Send(responseMessage); WriteWarning("Move destination is not registered in SCP"); return(true); } DvtkData.Collections.StringCollection retrieveList = null; // check if we should use the Patient Root Information Model if ((abstractSyntax.UID == DvtkData.Dul.AbstractSyntax.Patient_Root_Query_Retrieve_Information_Model_MOVE.UID) && (PatientRootInformationModel != null)) { // check if the information model should be refreshed before retrieving if (RefreshInformationModelBeforeUse == true) { PatientRootInformationModel.RefreshInformationModel(); } // perform retrieve retrieveList = PatientRootInformationModel.RetrieveInformationModel(retrieveMessage); } // check if we should use the Study Root Information Model else if ((abstractSyntax.UID == DvtkData.Dul.AbstractSyntax.Study_Root_Query_Retrieve_Information_Model_MOVE.UID) && (StudyRootInformationModel != null)) { // check if the information model should be refreshed before retrieving if (RefreshInformationModelBeforeUse == true) { StudyRootInformationModel.RefreshInformationModel(); } // perform retrieve retrieveList = StudyRootInformationModel.RetrieveInformationModel(retrieveMessage); } // check if we should use the Patient Study Only Information Model else if ((abstractSyntax.UID == DvtkData.Dul.AbstractSyntax.Patient_Study_Only_Query_Retrieve_Information_Model_MOVE.UID) && (PatientStudyOnlyInformationModel != null)) { // check if the information model should be refreshed before retrieving if (RefreshInformationModelBeforeUse == true) { PatientStudyOnlyInformationModel.RefreshInformationModel(); } // perform retrieve retrieveList = PatientStudyOnlyInformationModel.RetrieveInformationModel(retrieveMessage); } // process the retrieve list return(ProcessRetrieveList(moveDestinationAE, retrieveList)); }
/// <summary> /// Compares this instance with another Values instance. /// </summary> /// <remarks> /// Two Values instances are considered equal when:<br></br> /// - Both contain the same number of values.<br></br> /// - The String representations of the individual values are the same.<br></br><br></br> /// /// When spaces are non-significant according to part 5, /// they are left out, when comparing, like specified below.<br></br><br></br> /// /// When the attribute, a Values instance belongs to, has VR AE, CS, DS, IS, LO or SH, /// all leading and trailing spaces are removed before comparing.<br></br><br></br> /// /// When the attribute, a Values instance belongs to, has VR LT, PN, ST, TM or UT, /// all trailing spaces are removed before comparing.<br></br><br></br> /// /// When the attribute, a Values instance belongs to, has VR DA or DT, /// all trailing spaces are removed before comparing although /// nothing is mentioned in part 5 about non-significant spaces. This is /// because trailing spaces may be present in queries with range matching.<br></br><br></br> /// </remarks> /// <param name="values">The Values instance to compare with.</param> /// <returns>Boolean indicating if they are equal.</returns> public bool Equals(Values values) { bool equals = true; ValidAttribute validAttribute1 = Attribute as ValidAttribute; ValidAttribute validAttribute2 = values.Attribute as ValidAttribute; if ((validAttribute1 != null) && (validAttribute2 != null) && ((attribute.VR == VR.OB) || (attribute.VR == VR.OF) || (attribute.VR == VR.OW)) && ((values.Attribute.VR == VR.OB) || (values.Attribute.VR == VR.OF) || (values.Attribute.VR == VR.OW))) { equals = Dvtk.DvtkDataHelper.ComparePixelAttributes(validAttribute1.DvtkDataAttribute, validAttribute2.DvtkDataAttribute); } else { if (Count != values.Count) { equals = false; } else { for (int index = 0; index < Count; index++) { if (this[index] != values[index]) { equals = false; break; } } } } return (equals); }
/// <summary> /// Adds values to the end of this instance. /// </summary> /// <param name="values">Values to add.</param> /// public void Add(Values values) { Insert(this.Count, values); }
/// <summary> /// Inserts another Values instance in this instance at a specified position. /// </summary> /// <param name="zeroBasedIndex">The zero based index to insert.</param> /// <param name="values">The Values instance to insert.</param> public void Insert(int zeroBasedIndex, Values values) { if ((attribute.VR == VR.OB) || (attribute.VR == VR.OF) || (attribute.VR == VR.OW)) { ValidAttribute thisAttribute = this.attribute as ValidAttribute; ValidAttribute attributeToCopyFrom = values.Attribute as ValidAttribute; if ((thisAttribute != null) && (attributeToCopyFrom != null)) { // It is safe to use the same other...String object because it is never // changed through the HLI. thisAttribute.DvtkDataAttribute.DicomValue = attributeToCopyFrom.DvtkDataAttribute.DicomValue; thisAttribute.DvtkDataAttribute.Length = attributeToCopyFrom.DvtkDataAttribute.Length; } } else { String[] valuesAsStringArray = new String[values.Count]; for (int index = 0; index < values.Count; index++) { valuesAsStringArray[index] = values[index]; } Insert(zeroBasedIndex, valuesAsStringArray); } }
/// <summary> /// Adds a single attribute with the tag sequence, VR and values specified. /// </summary> /// <remarks> /// If an attribute already exists with this tag, it is removed first before it is again /// added. /// <br></br> /// If sequence items (each with a sequence item index) are specified in the tag sequence, /// empty sequence items will be added automatically to avoid gaps in the sequence items of sequence /// attributes. /// </remarks> /// <param name="tagSequence">The tag sequence of the attribute.</param> /// <param name="vR">The VR of the attribute.</param> /// <param name="values">The values, which will be copied from another attribute, for this attribute.</param> /// <exception cref="System.ArgumentException"> /// <paramref name="dvtkDataTag"/> is not valid for setting an attribute.<br></br> /// -or-<br></br> /// <paramref name="dvtkDataTag"/> is not valid for setting a FileMetaInformation attribute.<br></br> /// </exception> /// <exception cref="System.ArgumentNullException"> /// <paramref name="values"/> is a null reference. /// </exception> public override void Set(String tagSequence, VR vR, Values values) { TagSequence internalTagSequence = new TagSequence(tagSequence); // // Sanity checks. // if (!internalTagSequence.IsSingleAttributeMatching) { throw new ArgumentException(internalTagSequence.ToString() + " not valid for setting an attribute."); } // Check if the tag supplied is valid for a FileMetaInformation. if (!internalTagSequence.IsValidForFileMetaInformation) { throw new ArgumentException(internalTagSequence.ToString() + " not valid for setting a FileMetaInformation attribute.", "dvtkDataTag"); } if (values == null) { throw new ArgumentNullException("values"); } // // Perform the actual operation. // Set(internalTagSequence, vR, values); if ((internalTagSequence.ToString() == "0x00020010") && (values.Count == 1)) { this.dvtkDataFileHead.TransferSyntax = new DvtkData.Dul.TransferSyntax(values[0]); } }