private void LoadAdditionalEntities()
        {
            Debug.Assert(ServerPartition != null);
            Debug.Assert(StorageLocation != null);

			using (ServerExecutionContext context = new ServerExecutionContext())
			{
				if (_filesystem != null)
					_filesystem = FilesystemMonitor.Instance.GetFilesystemInfo(StorageLocation.FilesystemKey);
				_study = StorageLocation.LoadStudy(context.ReadContext);
				_patient = Patient.Load(context.ReadContext, _study.PatientKey);
			}
        }
Пример #2
0
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="thePartition"></param>
		/// <param name="location"></param>
		/// <param name="thePatient"></param>
		/// <param name="theStudy"></param>
		public StudyEditor(ServerPartition thePartition, StudyStorageLocation location, Patient thePatient, Study theStudy, WorkQueue workQueue)
		{
			FailureReason = string.Empty;
			Platform.CheckForNullReference(thePartition, "thePartition");
			Platform.CheckForNullReference(location, "location");
			Platform.CheckForNullReference(thePatient, "thePatient");
			Platform.CheckForNullReference(theStudy, "theStudy");

			ServerPartition = thePartition;
			StorageLocation = location;
			
            Patient = thePatient;
            Study = theStudy;
			_workQueue = workQueue;

            // Scrub for invalid characters that may cause a failure when the Xml is generated for the history
		    Patient.PatientId = XmlUtils.XmlCharacterScrub(Patient.PatientId);
            Patient.PatientsName = XmlUtils.XmlCharacterScrub(Patient.PatientsName);
            
            Study.StudyDescription = XmlUtils.XmlCharacterScrub(Study.StudyDescription);
            Study.ReferringPhysiciansName = XmlUtils.XmlCharacterScrub(Study.ReferringPhysiciansName);
            Study.PatientId = XmlUtils.XmlCharacterScrub(Study.PatientId);
            Study.PatientsName = XmlUtils.XmlCharacterScrub(Study.PatientsName);            
		}
Пример #3
0
 public Patient LoadPatient(IPersistenceContext context)
 {
     if (_patient==null)
     {
         lock (SyncRoot)
         {
             if (_patient == null)
             {
                 _patient = Patient.Load(context, PatientKey);
             }
         }
     }
     return _patient;
 }
Пример #4
0
        /// <summary>
        /// Populate data from a <see cref="Patient"/> entity into a DICOM C-FIND-RSP message.
        /// </summary>
        /// <param name="response">The response message to populate with results.</param>
        /// <param name="tagList">The list of tags to populate.</param>
        /// <param name="row">The <see cref="Patient"/> table to populate from.</param>
        private void PopulatePatient(DicomMessageBase response, IEnumerable<DicomTag> tagList, Patient row)
        {
            DicomAttributeCollection dataSet = response.DataSet;

            dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle);
            //dataSet[DicomTags.InstanceAvailability].SetStringValue("ONLINE");

            var characterSet = GetPreferredCharacterSet();
            if (!string.IsNullOrEmpty(characterSet))
            {
                dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet);
                dataSet.SpecificCharacterSet = characterSet; 
            }
            else if (false == String.IsNullOrEmpty(row.SpecificCharacterSet))
            {
                dataSet[DicomTags.SpecificCharacterSet].SetStringValue(row.SpecificCharacterSet);
                dataSet.SpecificCharacterSet = row.SpecificCharacterSet; // this will ensure the data is encoded using the specified character set
            }

        	IList<Study> relatedStudies = row.LoadRelatedStudies();
        	Study study = null;
			if (relatedStudies.Count > 0)
				study = CollectionUtils.FirstElement(relatedStudies);

            foreach (DicomTag tag in tagList)
            {
                try
                {
                    switch (tag.TagValue)
                    {
                        case DicomTags.PatientsName:
                            dataSet[DicomTags.PatientsName].SetStringValue(row.PatientsName);
                            break;
                        case DicomTags.PatientId:
                            dataSet[DicomTags.PatientId].SetStringValue(row.PatientId);
                            break;
                        case DicomTags.IssuerOfPatientId:
                            dataSet[DicomTags.IssuerOfPatientId].SetStringValue(row.IssuerOfPatientId);
                            break;
                        case DicomTags.NumberOfPatientRelatedStudies:
                            dataSet[DicomTags.NumberOfPatientRelatedStudies].AppendInt32(row.NumberOfPatientRelatedStudies);
                            break;
                        case DicomTags.NumberOfPatientRelatedSeries:
                            dataSet[DicomTags.NumberOfPatientRelatedSeries].AppendInt32(row.NumberOfPatientRelatedSeries);
                            break;
                        case DicomTags.NumberOfPatientRelatedInstances:
                            dataSet[DicomTags.NumberOfPatientRelatedInstances].AppendInt32(
                                row.NumberOfPatientRelatedInstances);
                            break;
                        case DicomTags.QueryRetrieveLevel:
                            dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("PATIENT");
                            break;
						case DicomTags.PatientsSex:
							if (study == null)
								dataSet[DicomTags.PatientsSex].SetNullValue();
							else
								dataSet[DicomTags.PatientsSex].SetStringValue(study.PatientsSex);
                    		break;
						case DicomTags.PatientsBirthDate:
							if (study == null)
								dataSet[DicomTags.PatientsBirthDate].SetNullValue();
							else
								dataSet[DicomTags.PatientsBirthDate].SetStringValue(study.PatientsBirthDate);
							break;
                    
						// Meta tags that should have not been in the RQ, but we've already set
						case DicomTags.RetrieveAeTitle:
						case DicomTags.InstanceAvailability:
						case DicomTags.SpecificCharacterSet:
                    		break;

                        default:
                            if (!tag.IsPrivate)
                                dataSet[tag].SetNullValue();

                            foreach (var q in _queryExtensions)
                                q.PopulatePatient(response, tag, row, study);

                            break;
                    }
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Warn, e, "Unexpected error setting tag {0} in C-FIND-RSP",
                                 dataSet[tag].Tag.ToString());
                    if (!tag.IsPrivate)
                        dataSet[tag].SetNullValue();
                }
            }
        }
Пример #5
0
		private void TransferStudy(ServerEntityKey studyKey, PatientInfo oldPatient, Patient newPatient)
		{
			Platform.Log(LogLevel.Info, "Transferring study from {0} [ID={1}] to {2} [ID={3}]",
			             oldPatient.Name, oldPatient.PatientId, newPatient.PatientsName, newPatient.PatientId);

            IAttachStudyToPatient attachStudyToPatientBroker = UpdateContext.GetBroker<IAttachStudyToPatient>();
			AttachStudyToPatientParamaters parms = new AttachStudyToPatientParamaters
			                                       	{
			                                       		StudyKey = studyKey,
			                                       		NewPatientKey = newPatient.GetKey()
			                                       	};
			attachStudyToPatientBroker.Execute(parms);            
		}
Пример #6
0
		private void UpdateDatabase()
		{
			// Reload the StudyStorage and Study tables.
			LoadEntities();

			UpdateEntity(_study);
			UpdateEntity(_curPatient);
			UpdateEntity(_storage);

            SetStudyEncoding(_study);
            
			// Update the Study table
			IStudyEntityBroker studyUpdateBroker = UpdateContext.GetBroker<IStudyEntityBroker>();
			studyUpdateBroker.Update(_study);
            
			// Update the StudyStorage table
			IStudyStorageEntityBroker storageUpdateBroker = UpdateContext.GetBroker<IStudyStorageEntityBroker>();
			storageUpdateBroker.Update(_storage);

			// Update Patient level info. Different cases can occur here: 
			//      A) Patient demographic info is not changed ==> update the current patient
			//      B) New patient demographics matches (another) existing patient in the datbase 
			//              ==> Transfer the study to that patient. This means the study count on both patients must be updated.
			//                  The current patient should also be deleted if there's no more study attached to it after the transfer.
			//      C) New patient demographics doesn't match any patient in the database
			//              ==> A new patient should be created for this study. The study count on the current patient should be updated
			//                  and the patient should also be deleted if this is the only study attached to it.
			if (_patientInfoIsNotChanged)
			{
				UpdateCurrentPatient();
                UpdatePatientEncoding(_curPatient);
			}
			else if (_newPatient == null)
			{
				// No matching patient in the database. We should create a new patient for this study
				_newPatient = CreateNewPatient(_newPatientInfo);
                UpdatePatientEncoding(_newPatient);
			}
			else
			{
				// There's already patient in the database with the new patient demographics
				// The study should be attached to that patient.
				TransferStudy(_study.Key, _oldPatientInfo, _newPatient);
                UpdatePatientEncoding(_newPatient);
			}

		}
Пример #7
0
        private void UpdatePatientEncoding(Patient patient)
        {
            // Note: patient can be an existing one or a new one

            // set the SpecificCharacterSet of the patient and study record. This will update the database
            // and force Patient/Study/Series level query response to be encoded in UTF8. Image level responses
            // will be encoded using the character set in the image (see QueryScpExtension) 
            //
            if (atLeastOneFileUpdatedToUTF8)
            {
                // Only update the db if necessary
                if (!IsUTF8(patient.SpecificCharacterSet))
                {
                    Platform.Log(LogLevel.Info, "Updating encoding for patient information in the database to UTF8 [ Name={0}, ID={1} ]", patient.Name, patient.PatientId);
                    
                    // update to UTF8
                    patient.SpecificCharacterSet = UTF8;

                    // This method is called at the very end of UpdateDatabase(), update the database now
                    IPatientEntityBroker broker = UpdateContext.GetBroker<IPatientEntityBroker>();
                    PatientUpdateColumns columns = new PatientUpdateColumns() { SpecificCharacterSet = UTF8 };
                    broker.Update(patient.Key, columns);
                }
            }
        }
Пример #8
0
		private void Initialize()
		{
			_backupDir = ProcessorContext.BackupDirectory;

				_oldStudyPath = _oldStudyLocation.GetStudyPath();
				_oldStudyInstanceUid = _oldStudyLocation.StudyInstanceUid;
				_oldStudyFolder = _oldStudyLocation.StudyFolder;
				_newStudyInstanceUid = _oldStudyInstanceUid;

			_study = _oldStudyLocation.LoadStudy(ServerExecutionContext.Current.ReadContext);
				_totalSopCount = _study.NumberOfStudyRelatedInstances;
			_curPatient = _study.LoadPatient(ServerExecutionContext.Current.ReadContext);
				_oldPatientInfo = new PatientInfo
				                  	{
				                  		Name = _curPatient.PatientsName,
				                  		PatientId = _curPatient.PatientId,
				                  		IssuerOfPatientId = _curPatient.IssuerOfPatientId
				                  	};

				_newPatientInfo = new PatientInfo(_oldPatientInfo);
				Debug.Assert(_newPatientInfo.Equals(_oldPatientInfo));

				foreach (BaseImageLevelUpdateCommand command in _commands)
				{
					ImageLevelUpdateEntry imageLevelUpdate = command.UpdateEntry;
					if (imageLevelUpdate == null)
						continue;

					if (imageLevelUpdate.TagPath.Tag.TagValue == DicomTags.StudyInstanceUid)
					{
						_newStudyInstanceUid = imageLevelUpdate.GetStringValue();
					}
					else if (imageLevelUpdate.TagPath.Tag.TagValue == DicomTags.PatientId)
					{
						_newPatientInfo.PatientId = imageLevelUpdate.GetStringValue();
					}
					else if (imageLevelUpdate.TagPath.Tag.TagValue == DicomTags.IssuerOfPatientId)
					{
						_newPatientInfo.IssuerOfPatientId = imageLevelUpdate.GetStringValue();
					}
					else if (imageLevelUpdate.TagPath.Tag.TagValue == DicomTags.PatientsName)
					{
						_newPatientInfo.Name = imageLevelUpdate.GetStringValue();
					}
				}

				Platform.CheckForNullReference(_newStudyInstanceUid, "_newStudyInstanceUid");

				NewStudyPath = Path.Combine(_oldStudyLocation.FilesystemPath, _partition.PartitionFolder);
				NewStudyPath = Path.Combine(NewStudyPath, _oldStudyFolder);
				NewStudyPath = Path.Combine(NewStudyPath, _newStudyInstanceUid);

			_newPatient = FindPatient(_newPatientInfo, ServerExecutionContext.Current.ReadContext);
				_patientInfoIsNotChanged = _newPatientInfo.Equals(_oldPatientInfo);

				Statistics.InstanceCount = _study.NumberOfStudyRelatedInstances;
				Statistics.StudySize = (ulong) _oldStudyLocation.LoadStudyXml().GetStudySize();

				// The study path will be changed. We will need to delete the original folder at the end.
				// May be too simple to test if two paths are the same. But let's assume it is good enough for 99% of the time.
				_deleteOriginalFolder = NewStudyPath != _oldStudyPath;
				_initialized = true;
			}
		private void Initialize()
		{
			_study = Study.Find(ServerExecutionContext.Current.ReadContext,_studyLocation.StudyInstanceUid, _partition);
			_curPatient = _study.LoadPatient(ServerExecutionContext.Current.ReadContext);
			_oldPatientInfo = new PatientInfo
				{
					PatientsName = _curPatient.PatientsName,
					PatientId = _curPatient.PatientId,
					IssuerOfPatientId = _curPatient.IssuerOfPatientId
				};

			_seriesInstanceUid = _file.DataSet[DicomTags.SeriesInstanceUid].ToString();
			var broker = ServerExecutionContext.Current.ReadContext.GetBroker<ISeriesEntityBroker>();
			var select = new SeriesSelectCriteria();
			select.SeriesInstanceUid.EqualTo(_seriesInstanceUid);
			select.ServerPartitionKey.EqualTo(_partition.Key);
			_curSeries = broker.FindOne(select);

			_newPatientInfo = new PatientInfo(_oldPatientInfo);
			_file.DataSet.LoadDicomFields(_newPatientInfo);

			_newPatient = FindPatient(_newPatientInfo, ServerExecutionContext.Current.ReadContext);
			_patientInfoIsNotChanged = _newPatientInfo.Equals(_oldPatientInfo);
		}
Пример #10
0
		private void UpdateDatabase()
		{
			var patientUpdate = new PatientUpdateColumns();
			var seriesUpdate = new SeriesUpdateColumns();
			var studyUpdate = new StudyUpdateColumns();

			// Update Patient level info. Different cases can occur here: 
			//      A) Patient demographic info is not changed ==> update the current patient
			//      B) New patient demographics matches (another) existing patient in the datbase 
			//              ==> Transfer the study to that patient. This means the study count on both patients must be updated.
			//                  The current patient should also be deleted if there's no more study attached to it after the transfer.
			//      C) New patient demographics doesn't match any patient in the database
			//              ==> A new patient should be created for this study. The study count on the current patient should be updated
			//                  and the patient should also be deleted if this is the only study attached to it.
			if (_patientInfoIsNotChanged)
			{
				_newPatient = _curPatient;
			}
			else if (_newPatient == null)
			{
				// No matching patient in the database. We should create a new patient for this study
				_newPatient = CreateNewPatient(_newPatientInfo);
			}
			else
			{
				// There's already patient in the database with the new patient demographics
				// The study should be attached to that patient.
				TransferStudy(_study.Key, _oldPatientInfo, _newPatient);
			}

			// Copy the existing valus over into the study & series objects
			// Note, this sets up an update statement that will update the key columns for
			// Study Instance UID, Series Instance UID, however, note that the columns will not
			// actually change value.  Its alittle ugly, but it will make it so if we add new
			// columns in the future, it just "works".
			_file.DataSet.LoadDicomFields(patientUpdate);
			_file.DataSet.LoadDicomFields(studyUpdate);
			_file.DataSet.LoadDicomFields(seriesUpdate);

			// Get any extensions that exist and process them
			var ep = new ProcessorInsertExtensionPoint();
			var extensions = ep.CreateExtensions();
			foreach (IInsertExtension e in extensions)
				e.UpdateExtension(_partition.Key, patientUpdate,studyUpdate,seriesUpdate, _file);

			UpdatePatientEncoding(_newPatient, patientUpdate);
			SetStudyEncoding(_study, studyUpdate);

			// Update the Study table
			var patientUpdateBroker = UpdateContext.GetBroker<IPatientEntityBroker>();
			patientUpdateBroker.Update(_newPatient.Key, patientUpdate);

			// Update the Study table
			var studyUpdateBroker = UpdateContext.GetBroker<IStudyEntityBroker>();
			studyUpdateBroker.Update(_study.Key, studyUpdate);

			// Update the Series table
			var seriesUpdateBroker = UpdateContext.GetBroker<ISeriesEntityBroker>();
			seriesUpdateBroker.Update(_curSeries.Key, seriesUpdate);

			// If the Request Attributes Sequence is in the dataset, do an insert.
			// Small hole in this that if the value of this sequence has changed, both the old and
			// the new values will stay in the database, not much to do about it, except
			// reprocess the whole series, which doesn't seem worth it.
			if (_file.DataSet.Contains(DicomTags.RequestAttributesSequence))
			{
				var attribute = _file.DataSet[DicomTags.RequestAttributesSequence] as DicomAttributeSQ;
				if (attribute != null && !attribute.IsEmpty)
				{
					foreach (DicomSequenceItem sequenceItem in (DicomSequenceItem[])attribute.Values)
					{
						var requestParms = new RequestAttributesInsertParameters();
						sequenceItem.LoadDicomFields(requestParms);
						requestParms.SeriesKey = _curSeries.Key;

						var insertRequest = UpdateContext.GetBroker<IInsertRequestAttributes>();
						insertRequest.Execute(requestParms);
					}
				}
			}
		}
Пример #11
0
		private void UpdatePatientEncoding(Patient patient, PatientUpdateColumns update)
		{
			// set the SpecificCharacterSet of the patient and study record. This will update the database
			// and force Patient/Study/Series level query response to be encoded in UTF8. Image level responses
			// will be encoded using the character set in the image (see QueryScpExtension) 
			//
			// Only update the db if necessary
			if (IsUTF8(patient.SpecificCharacterSet))
			{
				update.SpecificCharacterSet = UTF8;
			}
		}
Пример #12
0
 static public Patient Insert(IUpdateContext update, Patient entity)
 {
     var broker = update.GetBroker<IPatientEntityBroker>();
     var updateColumns = new PatientUpdateColumns();
     updateColumns.ServerPartitionKey = entity.ServerPartitionKey;
     updateColumns.NumberOfPatientRelatedStudies = entity.NumberOfPatientRelatedStudies;
     updateColumns.NumberOfPatientRelatedSeries = entity.NumberOfPatientRelatedSeries;
     updateColumns.NumberOfPatientRelatedInstances = entity.NumberOfPatientRelatedInstances;
     updateColumns.SpecificCharacterSet = entity.SpecificCharacterSet;
     updateColumns.PatientsName = entity.PatientsName;
     updateColumns.PatientId = entity.PatientId;
     updateColumns.IssuerOfPatientId = entity.IssuerOfPatientId;
     Patient newEntity = broker.Insert(updateColumns);
     return newEntity;
 }
Пример #13
0
 static public Patient Insert(Patient entity)
 {
     using (var update = PersistentStoreRegistry.GetDefaultStore().OpenUpdateContext(UpdateContextSyncMode.Flush))
     {
         Patient newEntity = Insert(update, entity);
         update.Commit();
         return newEntity;
     }
 }