Index: processors/DicomPACSQueryFileReader.h
===================================================================
--- processors/DicomPACSQueryFileReader.h	(revision 0)
+++ processors/DicomPACSQueryFileReader.h	(revision 0)
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2009,
+* Computational Image and Simulation Technologies in Biomedicine (CISTIB),
+* Universitat Pompeu Fabra (UPF), Barcelona, Spain. All rights reserved.
+* See license.txt file for details.
+*/
+
+#ifndef _DicomPACSQueryFileReader_H
+#define _DicomPACSQueryFileReader_H
+
+// DCMAPIIO_EXPORT
+#include "dcmAPIIOWin32Header.h"
+
+// BaseLib
+#include "blLightObject.h"
+#include "CILabExceptionMacros.h"
+
+//DcmAPI
+#include "dcmDataSet.h"
+#include "dcmTypes.h"
+
+namespace DicomPlugin{
+
+/** 
+* \brief DICOM PACS query file DataSet reader.
+* 
+* Reads a DICOM PACS query file and create the objects to 
+* store the DataSet using the hierarchy defined by dcmAPI classes. 
+* 
+* \ingroup dset_readers
+* \author Xavi Planes
+* \date 24 July 2009
+*/
+class PLUGIN_EXPORT PACSQueryFileReader : public blLightObject
+{
+public:
+	typedef PACSQueryFileReader Self;
+	typedef blSmartPointer<Self> Pointer;
+	blNewMacro(Self);
+	cilabDeclareExceptionMacro(Exception, std::exception)
+
+	//!
+	dcmAPI::DataSet::Pointer GetDataSet() const;
+	void SetDataSet(dcmAPI::DataSet::Pointer val);
+
+	//!
+	std::string GetPath() const;
+	void SetPath(std::string val);
+
+	std::vector< dcmAPI::Tag > GetQuery() const;
+	void SetQuery( const std::vector< dcmAPI::Tag > &val );
+
+	//! 
+	void Update( );
+
+private:
+
+	//!
+	PACSQueryFileReader();
+	//!
+	~PACSQueryFileReader();
+
+private:
+
+	std::vector< dcmAPI::Tag > m_Query;
+
+	//!
+	std::string m_Path;
+
+	//!
+	dcmAPI::DataSet::Pointer m_DataSet;
+};
+
+} // namespace dcmAPI
+
+#endif // _DicomPACSQueryFileReader_H

Property changes on: processors\DicomPACSQueryFileReader.h
___________________________________________________________________
Added: svn:eol-style
   + native

Index: processors/DicomPACSQueryFileReader.cxx
===================================================================
--- processors/DicomPACSQueryFileReader.cxx	(revision 0)
+++ processors/DicomPACSQueryFileReader.cxx	(revision 0)
@@ -0,0 +1,164 @@
+/*
+* Copyright (c) 2009,
+* Computational Image and Simulation Technologies in Biomedicine (CISTIB),
+* Universitat Pompeu Fabra (UPF), Barcelona, Spain. All rights reserved.
+* See license.txt file for details.
+*/
+
+#include "DicomPACSQueryFileReader.h"
+
+#include "dcmTypes.h"
+
+using namespace DicomPlugin;
+
+PACSQueryFileReader::PACSQueryFileReader()
+{
+	m_DataSet = dcmAPI::DataSet::New( );
+}
+
+PACSQueryFileReader::~PACSQueryFileReader()
+{
+}
+
+void PACSQueryFileReader::Update()
+{
+	// Open query file
+	std::ifstream queryFile;
+	queryFile.open ( m_Path.c_str() );
+	if ( queryFile.bad() )
+	{
+		return;
+	}
+
+	// For each patient -> Add to the vector
+	std::string line;
+
+	// Set info to dcmData
+	//m_DataSet->Clear();
+
+	bool fileisOk = true;
+	while ( fileisOk )
+	{
+		// Collect all TAGS for each query result
+		dcmAPI::TagsMap tagMap;
+		for ( unsigned i = 0 ; i < m_Query.size() ; i++ )
+		{
+			fileisOk = std::getline(queryFile,line);
+			dcmAPI::Tag dcmTAG( line );
+			tagMap[ dcmTAG.m_tagId ] = dcmTAG.m_value;
+		}
+
+
+		if ( fileisOk )
+		{
+
+			// Find if the patient already exists
+			bool bNewPatient=false;
+			dcmAPI::Patient::Pointer patient;
+			patient = m_DataSet->GetPatient( tagMap[ dcmAPI::tags::PatientRealID ] );
+			
+			if(patient==NULL)
+			{
+				patient = dcmAPI::Patient::New();
+				patient->AddTag( dcmAPI::Tag( dcmAPI::tags::PatientId,tagMap[ dcmAPI::tags::PatientRealID ]));
+				patient->AddTag( dcmAPI::Tag( dcmAPI::tags::PatientRealID, tagMap[ dcmAPI::tags::PatientRealID ] ) );
+				patient->AddTag( dcmAPI::Tag( dcmAPI::tags::PatientName, tagMap[ dcmAPI::tags::PatientName ] ) );
+				patient->AddTag( dcmAPI::Tag( dcmAPI::tags::PatientDate, tagMap[ dcmAPI::tags::PatientDate ] ) );
+				bNewPatient=true;
+			}
+			
+			if ( tagMap[ dcmAPI::tags::PatientRealID ].empty() )
+			{
+				continue;
+			}
+
+
+			// Fill study data
+			dcmAPI::Study::Pointer study;
+			if ( !tagMap[ dcmAPI::tags::StudyInstanceUID ].empty() )
+			{
+				study = patient->Study( tagMap[ dcmAPI::tags::StudyInstanceUID ] );
+				if(study==NULL)
+				{
+					study=dcmAPI::Study::New();
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyInstanceUID, tagMap[ dcmAPI::tags::StudyInstanceUID ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyRealID, tagMap[ dcmAPI::tags::StudyRealID ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyId, tagMap[ dcmAPI::tags::StudyInstanceUID ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyDate, tagMap[ dcmAPI::tags::StudyDate ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyDescription, tagMap[ dcmAPI::tags::StudyDescription ] ) );
+					patient->AddStudy( study );
+				}
+			}
+
+			// Fill series data
+			if ( !tagMap[ dcmAPI::tags::SeriesInstanceUID ].empty())
+			{
+				//handle the case in which the studyinstanceuid is not present, but a series has been retrieved anyway:
+				//this could happen if the query level is series and no studyinstanceuid have been specified (but only
+				//patient id (note: on some server this kind of query should be forbidden since the studyinstanceuid is
+				//specifically required in the case of sublevel queries - series is a sublevel respect to study!)
+				//In this case create an empty study first...of course the study information has no sense in this case!
+				if(study==NULL)
+				{
+					study=dcmAPI::Study::New();
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyInstanceUID, tagMap[ dcmAPI::tags::StudyInstanceUID ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyRealID, tagMap[ dcmAPI::tags::StudyRealID ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyId, tagMap[ dcmAPI::tags::StudyInstanceUID ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyDate, tagMap[ dcmAPI::tags::StudyDate ] ) );
+					study->AddTag( dcmAPI::Tag( dcmAPI::tags::StudyDescription, tagMap[ dcmAPI::tags::StudyDescription ] ) );
+					patient->AddStudy( study );
+				}
+
+
+				dcmAPI::Series::Pointer series = study->Series( tagMap[ dcmAPI::tags::SeriesInstanceUID ] );
+				if(series==NULL)
+				{
+					series=dcmAPI::Series::New();
+					series->AddTag( dcmAPI::Tag( dcmAPI::tags::SeriesInstanceUID, tagMap[ dcmAPI::tags::SeriesInstanceUID ] ) );
+					series->AddTag( dcmAPI::Tag( dcmAPI::tags::SeriesId, tagMap[ dcmAPI::tags::SeriesInstanceUID ] ) );
+					series->AddTag( dcmAPI::Tag( dcmAPI::tags::SeriesNumber, tagMap[ dcmAPI::tags::SeriesNumber ] ) );
+					series->AddTag( dcmAPI::Tag( dcmAPI::tags::SeriesDescription, tagMap[ dcmAPI::tags::SeriesDescription ] ) );
+					series->AddTag( dcmAPI::Tag( dcmAPI::tags::Modality, tagMap[ dcmAPI::tags::Modality ] ) );
+					study->AddSeries( series );
+				}
+			}
+
+			if(bNewPatient)
+				m_DataSet->AddPatient( patient );
+		}
+	}
+
+	// Close file
+	queryFile.close();
+}
+
+dcmAPI::DataSet::Pointer PACSQueryFileReader::GetDataSet() const
+{
+	return m_DataSet;
+}
+
+void PACSQueryFileReader::SetDataSet( dcmAPI::DataSet::Pointer val )
+{
+	m_DataSet = val;
+}
+
+std::string PACSQueryFileReader::GetPath() const
+{
+	return m_Path;
+}
+
+void PACSQueryFileReader::SetPath( std::string val )
+{
+	m_Path = val;
+}
+
+std::vector< dcmAPI::Tag > PACSQueryFileReader::GetQuery() const
+{
+	return m_Query;
+}
+
+void PACSQueryFileReader::SetQuery( 
+	const std::vector< dcmAPI::Tag > &val )
+{
+	m_Query = val;
+}
Index: widgets/DicomConnectToPACSWidget/DicomConnectToPacsDialogWidget.cpp
===================================================================
--- widgets/DicomConnectToPACSWidget/DicomConnectToPacsDialogWidget.cpp	(revision 15552)
+++ widgets/DicomConnectToPACSWidget/DicomConnectToPacsDialogWidget.cpp	(working copy)
@@ -30,7 +30,7 @@
 #include <wx/process.h>
 
 #include "dcmTypes.h"
-#include "dcmPACSQueryFileReader.h"
+#include "DicomPACSQueryFileReader.h"
 
 #include "PACS.xpm"
 
@@ -203,8 +203,24 @@
 		pacsAPI->SetNetworkParams( networkParams );
 
 		// Create query
+		// So, for the Patient Root model, first you need to get the Paient ID
+		// (0010,0020) at the PATIENT level (if you already have this, you can
+		// skip this query).  Then, at the STUDY level, you have to query for the
+		// Study Instance UID (0020,000d) by supplying the Patient ID.  Then you
+		// can query at the SERIES level, but you have to supply the Study
+		// InstanceUID and Patient ID.  You could also use the Study Root model,
+		// which would eliminate the PATIENT level query. 
+
+		// if your server supports relational queries, you can use that, but it must be negotiated when
+		// the association is created (extended behavior).  In that case, you can
+		// query at any level in a model, with any keys you like.  The only
+		// requirement is that the unique key for the level you are querying must
+		// be present.  This is specified in Part 4, C.4.2.2.2.  I haven't
+		// implemented or used the relational part of Q/R, so I might be
+		// misreading it myself, but there are others who could clarify this
+		// issue if I'm wrong. 
 		PACS::QueryParams queryParams;
-		queryParams.retrieveLevel = PACS::SERIES;
+		queryParams.retrieveLevel = PACS::STUDY; //PACS::SERIES;
 		FillQueryParamsFromFields( queryParams );
 
 		// Add other params to retrieve the information
@@ -226,6 +242,46 @@
 		// Fill DICOM Tree
 		FillQueryResults( pacsAPI );
 
+		// If server does NOT support relational queries -> Query for each study, all series
+		dcmAPI::DataSet::Pointer dataSet = m_DICOMTree->GetDcmData();
+		dcmAPI::PatientIdVectorPtr patiendIdVector = dataSet->GetPatientIds();
+		for(unsigned i=0; i < patiendIdVector->size(); i++)
+		{
+			std::string patientID = patiendIdVector->at(i);
+			dcmAPI::Patient::Pointer patientData = dataSet->GetPatient( patientID );
+			dcmAPI::StudyIdVectorPtr studiesIdVector = patientData->StudyIds();
+			for(unsigned i=0; i < studiesIdVector->size(); i++)
+			{
+				dcmAPI::Study::Pointer studyData = patientData->Study( studiesIdVector->at(i) );
+				dcmAPI::SeriesIdVectorPtr seriesIdVector = studyData->SeriesIds();
+				if ( seriesIdVector->empty() )
+				{
+					// Series level
+					queryParams.retrieveLevel = PACS::SERIES;
+					queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::PatientRealID, patientID.c_str() ) );
+					const std::string studyInstanceUID = studyData->GetTagAsText(dcmAPI::tags::StudyInstanceUID);
+					queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::StudyInstanceUID, studyInstanceUID.c_str() ) );
+					pacsAPI->SetQueryParams( queryParams );
+					pacsAPI->Query();
+
+					// Read output information from file
+					DicomPlugin::PACSQueryFileReader::Pointer reader = DicomPlugin::PACSQueryFileReader::New();
+					reader->SetDataSet( m_DICOMTree->GetDcmData() );
+					reader->SetPath( pacsAPI->GetQueryResultsFileName() );
+					reader->SetQuery( pacsAPI->GetQueryParams().query );
+					reader->Update( );
+				}
+			}
+		}
+
+		// Update the TREE
+		m_DICOMTree->LoadPatientsIntoTree( );
+		// expand first Patient->Study->Series
+		wxTreeItemIdValue cookie;
+		wxTreeItemId timepointId = m_DICOMTree->GetFirstSpecifiedTreeItem( 
+			DICOMTree::TIMEPOINT, 
+			cookie, 
+			true);
 	}
 	coreCatchExceptionsReportAndNoThrowMacro(ConnectToPacsDialogWidget::OnRetrieve)
 
@@ -247,10 +303,8 @@
 		FillNetworkParams( networkParams );
 		pacsAPI->SetNetworkParams( networkParams );
 
-		// Create query
-
+		// Create study query
 		PACS::QueryParams queryParams;
-		
 		queryParams.retrieveLevel = PACS::SERIES;
 		FillQueryParamsFromTree(queryParams);
 		
@@ -288,7 +342,8 @@
 	PACS::PacsAPI* pacsAPI )
 {
 
-	dcmAPI::PACSQueryFileReader::Pointer reader = dcmAPI::PACSQueryFileReader::New();
+	m_DICOMTree->GetDcmData()->Clear();
+	DicomPlugin::PACSQueryFileReader::Pointer reader = DicomPlugin::PACSQueryFileReader::New();
 	reader->SetDataSet( m_DICOMTree->GetDcmData() );
 	reader->SetPath( pacsAPI->GetQueryResultsFileName() );
 	reader->SetQuery( pacsAPI->GetQueryParams().query );
@@ -356,6 +411,7 @@
 
 	wxString studyID = m_edStudyId->GetValue();
 	queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::StudyRealID, studyID.c_str() ) );
+	//queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::StudyInstanceUID, studyID.c_str() ) );
 
 	wxString modality = m_edModality->GetValue();
 	queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::Modality, modality.c_str() ) );
@@ -403,7 +459,6 @@
 
 		//checking if a patient item was selected
 		PatientItemTreeData* patientData = dynamic_cast<PatientItemTreeData*>(m_DICOMTree->GetItemData(treeItemId));
-		
 		if ( patientData != NULL ) 
 		{
 			patientId=patientData->GetPatientId();
@@ -438,9 +493,15 @@
 		//}
 	}
 
+	// Get study UID from study id
+	dcmAPI::DataSet::Pointer dataSet = m_DICOMTree->GetDcmData();
+	dcmAPI::Patient::Pointer patientData = dataSet->GetPatient( patientId );
+	dcmAPI::Study::Pointer studyData = patientData->Study( studyId );
+	const std::string studyInstanceUID = studyData->GetTagAsText(dcmAPI::tags::StudyInstanceUID);
+
 	queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::PatientRealID, patientId.c_str() ) );	
-	if(studyId.length()>0)
-		queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::StudyInstanceUID, studyId.c_str() ) );	
+	if(studyInstanceUID.length()>0)
+		queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::StudyInstanceUID, studyInstanceUID.c_str() ) );	
 	if(seriesId.length()>0)
 		queryParams.query.push_back( dcmAPI::Tag( dcmAPI::tags::SeriesInstanceUID, seriesId.c_str() ) );	
 
