wxSize(1200,800),
min_dim,
max_dim,
- // output_dim,
+ output_dim,
threads);
w.ShowModal();
{
std::cout << "$$$$ main : user clicked 'OK' $$$$"<<std::endl;
std::cout << "$$$$ selected files : "<<std::endl;
+ //Puts filenames
std::vector<std::string> s;
w.GetSelectedFiles(s);
std::vector<std::string>::iterator i;
}
std::cout << "$$$$ "<<std::endl;
+ //Puts images
std::vector<vtkImageData*> images;
- w.GetSelectedImages(images,3);
+ w.GetSelectedImages(images,output_dim);
+
crea::VtkBasicSlicer(images.front());
images.front()->Delete();
{
//======================================================================
// CTor
- GimmickView::GimmickView(Gimmick* gimmick)
- : mGimmick(gimmick)
+ GimmickView::GimmickView(Gimmick* gimmick, int threads)
+ : mGimmick(gimmick),
+ mReader(threads)
{
GimmickDebugMessage(1,"GimmickView::GimmickView"
<<std::endl);
+ // Start the threads ...
+ mReader.Start();
}
//======================================================================
i->second->UpdateLevel(l);
}
//======================================================================
+ ///Validates the dimension compliance of the images with the maximum and
+ ///minimum given, and between their sizes
+ bool GimmickView::ValidateSelected (std::vector<tree::Node*>& sel, int min_dim, int max_dim)
+ {
+ GimmickMessage(2,"Validating selected"<<std::endl);
+ bool valid=true;
+ int level;
+ std::string mMessage;
+ if(sel.size()>0)
+ {
+ std::vector<tree::Node*>::iterator i;
+ std::string row;
+ std::string col;
+ std::string plane;
+
+ //Validation between image sizes
+ for (i=sel.begin(); i!=sel.end() && valid; ++i)
+ {
+ if(i==sel.begin())
+ {
+ row=(*i)->GetAttribute("D0028_0010");
+ col=(*i)->GetAttribute("D0028_0011");
+ plane=(*i)->GetAttribute("D0028_0012");
+ level=(*i)->GetLevel();
+
+ }
+ else
+ {
+ if(((*i)->GetAttribute("D0028_0010"))!=row ||
+ ((*i)->GetAttribute("D0028_0011"))!=col ||
+ ((*i)->GetAttribute("D0028_0012"))!=plane)
+ {
+ mMessage="The selected images are not compatible.";
+ valid=false;
+ }
+ }
+ }
+
+ //Dimention validation
+ //Compatibility with maximum
+ if(valid)
+ {
+
+ int rows;
+ int cols;
+ int planes;
+ std::string s;
+ std::istringstream t(s);
+ s=row;
+ t >> rows;
+ if(row==""){rows=1;}
+ s=col;
+ t >> cols;
+ if(col==""){cols=1;}
+ s=plane;
+ t >> planes;
+ if(plane==""){planes=1;}
+
+ int dim = 0;
+ if (planes>1) dim=3;
+ else if (cols>1) dim=2;
+ else if (rows>1) dim=1;
+
+ if (dim == 0)
+ {
+ mMessage="Unknown image dimension : cannot select !";
+ valid= false;
+ }
+ else if (dim>max_dim)
+ {
+ mMessage="Selecting ";
+ mMessage+=dim;
+ mMessage+="D images is not allowed !";
+ valid= false;
+ }
+ if ( dim == max_dim )
+ {
+ mMessage="Cannot add this image to selection : would result in a ";
+ mMessage+=(dim+1);
+ mMessage+="D image!";
+
+ valid= false;
+ }
+ if ( dim < min_dim && sel.size()<2 )
+ {
+ GimmickDebugMessage(2, "State Check: Dim: "
+ <<dim
+ <<" Dim min:"
+ <<min_dim
+ <<std::endl);
+ mMessage="Cannot build the selection as it would result in a ";
+ mMessage+=dim;
+ mMessage+="D image, and the minimum is ";
+ mMessage+=min_dim;
+ mMessage+="D!";
+ valid= false;
+ }
+ }
+ }
+ else
+ {
+ mMessage="Cannot have 0 images selected";
+ valid=false;
+ }
+ if(valid)
+ {
+ mMessage="Selection OK !";
+ }
+ SetMessage(mMessage);
+ return valid;
+ }
+
+ //======================================================================
+
+ //======================================================================
+ ///Reads Images (Non Threaded)
+ void GimmickView::ReadImagesNotThreaded(std::vector<vtkImageData*>& s,std::vector<tree::Node*> im, int dimension)
+ {
+
+ // Create the output data
+ if (im.size()==1)
+ {
+
+ // Only one image : give it
+ vtkImageData* out = vtkImageData::New();
+ GimmickMessage(1, "State Check: Full Filename: "
+ <<im.front()->GetAttribute("FullFileName")
+ <<std::endl);
+ out->ShallowCopy(mReader.GetImage(im.front()->GetAttribute("FullFileName")));
+ s.push_back( out );
+ }
+
+ else if (im.size()>1)
+ {
+ vtkImageData* first = mReader.GetImage( im.front()->GetAttribute("FullFileName"));
+ if (dimension==2)
+ {
+ // n2D to 3D
+ vtkImageData* out = vtkImageData::New();
+ out->CopyStructure(first);
+ out->SetScalarType(first->GetScalarType());
+ int ext[6];
+ first->GetExtent(ext);
+ ext[5] = im.size();
+ out->SetExtent(ext);
+ // LG : TODO : Z Spacing ?
+
+ out->AllocateScalars();
+
+ //first->Print(std::cout);
+ // out->Print(std::cout);
+
+ int dim[3];
+ first->GetDimensions(dim);
+ unsigned long imsize =
+ ( (unsigned long)first->GetScalarPointer(0,1,0)
+ - (unsigned long)first->GetScalarPointer(0,0,0))
+ *dim[1];
+
+ int slice = 0;
+ std::vector<tree::Node*>::iterator it;
+ for (it=im.begin(); it!=im.end(); ++it)
+ {
+ //std::cout << "copying slice "<<slice <<std::endl;
+ vtkImageData* cur = mReader.GetImage( (*it)->GetAttribute("FullFileName"));
+
+ void* src = cur->GetScalarPointer(0,0,0);
+ void* dst = out->GetScalarPointer(0,0,slice);
+ // std::cout << "src="<<src<<std::endl;
+ // std::cout << "dst="<<dst<<std::endl;
+ // std::cout << "siz="<<imsize<<std::endl;
+ memcpy(dst,src,imsize);
+
+ slice++;
+ }
+ s.push_back(out);
+ }
+ else
+ {
+ // n3D
+ std::vector<tree::Node*>::iterator it;
+ for (it=im.begin(); it!=im.end(); ++it)
+ {
+ vtkImageData* out = vtkImageData::New();
+ out->ShallowCopy(mReader.GetImage((*it)->GetAttribute("FullFileName")));
+ s.push_back(out);
+ }
+ }
+ }
+
+ }
+
} // EO namespace creaImageIO
//#include <map>
#include <vtkImageData.h>
+#include <creaImageIOMultiThreadImageReader.h>
#define GIMMICK_NO_IMAGE_SELECTION 0
#define GIMMICK_2D_IMAGE_SELECTION 2
//=====================================================================
///Abstract class that handles views, attributes and previews (GUI) for Gimmick.
- class GimmickView
+ class GimmickView: public MultiThreadImageReaderUser
{
public:
/// Ctor
- GimmickView(Gimmick* );
+ GimmickView(Gimmick*, int number_of_threads = 0 );
/// Virtual destructor
virtual ~GimmickView();
/// Finalize
virtual void Finalize();
+
///Returns the selected Images and validates to see if they comply with the given parameter(<4D)
vtkImageData* GetSelectedImage(int dim);
///Adds the selected Images to the given vector and validates to see if they comply with the given parameter (4D)
- virtual void GetSelectedImages(std::vector<vtkImageData*>& s, int dim) {}
+ virtual void GetSelectedImages(std::vector<vtkImageData*>& s, int dim)
+ { GimmickError("INTERNAL ERROR : GetSelectedImages not implemented"); }
+
+ virtual void GetSelectedFiles(std::vector<std::string>& s)
+ { GimmickError("INTERNAL ERROR : GetSelectedFiles not implemented"); }
+
+ ///Validates the dimension compliance of the images with the maximum and minimum given, and between their sizes
+ bool ValidateSelected (std::vector<tree::Node*>& sel, int min_dim, int max_dim);
+
+ ///Reads the vector of nodes, builds images in the dimension required and returns them in the supplied vector.
+ void ReadImagesNotThreaded(std::vector<vtkImageData*>& s,std::vector<tree::Node*> im, int dim);
- virtual void GetSelectedFiles(std::vector<std::string>& s) {}
+ ///Obtains the message of the state
+ std::string GetMessage(){return mMess;}
+ ///Obtains the message of the state
+ void SetMessage(std::string mess){mMess=mess;}
/// Create the tree views
void CreateTreeViews();
Gimmick* mGimmick;
/// The views
TreeViewMapType mTreeViewMap;
+ /// The message that results from the validation
+ std::string mMess;
+ /// Multi-thread image reader
+ MultiThreadImageReader mReader;
+
};
// EO class GimmickView
///Validates the selected images
virtual void ValidateSelectedImages()
{ GimmickError("INTERNAL ERROR : TreeView::ValidateSelected not overloaded");}
- ///Returns the selected data as vtkImageData
- vtkImageData* GetSelectedImage(int dim)
- { GimmickError("INTERNAL ERROR : TreeView::GetSelectedImage not overloaded");}
- ///Returns the selected data as a vector of vtkImageData (4D)
- virtual void GetSelectedImages(std::vector<vtkImageData*>& s, int dim)
- { GimmickError("INTERNAL ERROR : TreeView::GetSelectedImages not overloaded");}
-
- ///Sets the maximum dimension allowed for selections
- void SetMaxDimension(int maxdim){ mSelectionMaxDimension=maxdim; }
- ///Sets the minimum dimension allowed for selections
- void SetMinDimension(int mindim){ mSelectionMinDimension=mindim; }
+ ///Returns the maximum number of levels
+ virtual int GetNumberOfLevels(){ GimmickError("INTERNAL ERROR : TreeView::GetLevels not overloaded"); }
+ ///Gets the current selections filenames
+ virtual void GetSelectedAsString(std::vector<std::string>&s){ GimmickError("INTERNAL ERROR : TreeView::GetSelectedAsString not overloaded"); }
+
+ /// Gets the user selected data from the level passed as a parameter
+ virtual std::vector<tree::Node*> GetSelected(int level){ GimmickError("INTERNAL ERROR : TreeView::GetSelected not overloaded"); }
+
protected:
TreeHandler* GetTreeHandler() { return mTreeHandler; }
- ///Gets the maximum dimension allowed for selections
- int GetMaxDimension(){ return mSelectionMaxDimension; }
- ///Gets the minimum dimension allowed for selections
- int GetMinDimension(){ return mSelectionMinDimension; }
private:
/// The TreeHandler with which it corresponds
TreeHandler* mTreeHandler;
- //The selection's maximum dimension
- int mSelectionMaxDimension;
- //The selection's minimum dimension
- int mSelectionMinDimension;
};
// EO class TreeView
//=====================================================================
///Callback method on a selection
void WxGimmickReaderDialog::OnValid(wxCommandEvent& event)
{
- mView->SetMessage(event.GetString());
- if (event.GetInt()==0)
- {mOkButton->Enable(true);}
- else
- {mOkButton->Enable(false);}
+ bool t=mView->ValidateSelection(event.GetClientData());
+ mOkButton->Enable(t);
}
-
+
+
//================================================================
BEGIN_EVENT_TABLE(WxGimmickReaderDialog, wxDialog)
EVT_COMMAND(wxID_ANY, 0, WxGimmickReaderDialog::OnValid)
int max_dim,
int number_of_threads)
: wxPanel(parent,id,pos,size),
- GimmickView(gimmick),
+ GimmickView(gimmick, number_of_threads),
mProgressDialog(0)
{
GimmickDebugMessage(1,"WxGimmickView::WxGimmickView"
//Gimmick
mGimmick=gimmick;
- mSelectionMaxDimension=max_dim;
- mSelectionMinDimension=min_dim;
+ mSelectionMaxDimension= max_dim;
+ mSelectionMinDimension= min_dim;
// Create the views
CreateTreeViews();
// Splitting
int hsize = size.GetHeight();
- int bottom_minsize = 20;
+ int bottom_minsize = 15;
mSplitter->SetMinimumPaneSize( bottom_minsize );
mSplitter->SplitHorizontally( mNotebook, mBottomPanel,
name<<"'"<<std::endl);
// Create the WxTreeView
WxTreeView* view = new WxTreeView(h,mNotebook,-1);
-
- view->SetMaxDimension(mSelectionMaxDimension);
- view->SetMinDimension(mSelectionMinDimension);
// TO DO : TEST THAT A VIEW WITH SAME NAME IS NOT
// ALREADY IN THE MAP
/// Returns the selected Image so that it complies with the given parameter(<4D)
vtkImageData* WxGimmickView::GetSelectedImage(int dim)
{
- return GetTreeViewMap()["Local database"]->GetSelectedImage(dim);
+ return NULL;
+ //GetTreeViewMap()["Local database"]->GetSelectedImage(dim);
}
//======================================================================
/// Returns the selected Images so that they comply with the given parameter(4D)
void WxGimmickView::GetSelectedImages(std::vector<vtkImageData*>& s, int dim)
{
- GetTreeViewMap()["Local database"]->GetSelectedImages(s,dim);
+ int level=GetTreeViewMap()["Local database"]->GetNumberOfLevels();
+ std::vector<tree::Node*> im=GetTreeViewMap()["Local database"]->GetSelected(level+1);
+ ReadImagesNotThreaded(s,im,dim);
+ }
+ //======================================================================
+ /// Returns the selected Images so that they comply with the given parameter(4D)
+ void WxGimmickView::GetSelectedFiles(std::vector<std::string>& s)
+ {
+ GetTreeViewMap()["Local database"]->GetSelectedAsString(s);
}
-
//=================================================
void WxGimmickView::CreateIconList()
{
//=================================================
//=================================================
- void WxGimmickView::SetMessage(const wxString& mess)
+ bool WxGimmickView::ValidateSelection(void * s)
{
wxBusyCursor busy;
+ std::vector<tree::Node*> sel=* (std::vector<tree::Node*> *) s;
+ bool valid=ValidateSelected(sel,mSelectionMinDimension,mSelectionMaxDimension );
+ mText->SetLabel(_T("Status: ")+GetMessage());
+ return valid;
- mText->SetLabel(_T("Status: ")+mess);
}
//=================================================
*/
wxMessageBox(std2wx(mess.str()),_T("Addition result"),wxOK,this);
}
+
//=================================================
//=================================================
/// Returns the selected Images so that they comply with the given parameter(<4D)
///(overloaded from GimmickView)
vtkImageData* GetSelectedImage(int dim);
+ /// Returns the selected files
+ ///(overloaded from GimmickView)
+ void GetSelectedFiles(std::vector<std::string>& s);
/// Returns the selected Images so that they comply with the given parameter(4D)
//(overloaded from GimmickView)
void GetSelectedImages(std::vector<vtkImageData*>& s, int dim);
- /// Sets the message state
- void SetMessage(const wxString& mess);
+ /// Validates the selected images
+ bool ValidateSelection(void *);
protected:
/// Creates the tool bar
void OnAddDir(wxCommandEvent& event);
/// Callback for removing files
void OnRemove(wxCommandEvent& event);
+
/// Display a message box with the last addition statistics
void DisplayAddSummary();
/// Progress dialog
wxProgressDialog* mProgressDialog;
- //The selection's maximum dimension
+ ///The selection's maximum dimension
int mSelectionMaxDimension;
- //The selection's minimum dimension
+ ///The selection's minimum dimension
int mSelectionMinDimension;
for (int k=1; k<GetCtrl(l)->GetColumnCount(); k++)
{
-
+
std::string val = (*j)->GetAttribute(mLevelList[l].key[k-1]);
if (val.size()==0) val = "?";
item.SetText( crea::std2wx(val));
void WxTreeView::ValidateSelectedImages()
{
- int level=mLevelList.size();
- std::vector<tree::Node*> sel=GetSelected(level+1);
- bool valid=true;
- std::string mess;
- if(sel.size()>0)
- {
- std::vector<tree::Node*>::iterator i;
- std::string row;
- std::string col;
- std::string plane;
-
-
- //Validation between image sizes
- for (i=sel.begin(); i!=sel.end() && valid; ++i)
- {
- if(i==sel.begin())
- {
- row=(*i)->GetAttribute(mLevelList[level-1].key[1]);
- col=(*i)->GetAttribute(mLevelList[level-1].key[2]);
- plane=(*i)->GetAttribute(mLevelList[level-1].key[3]);
- }
- else
- {
- if(((*i)->GetAttribute(mLevelList[level-1].key[1]))!=row ||
- ((*i)->GetAttribute(mLevelList[level-1].key[2]))!=col ||
- ((*i)->GetAttribute(mLevelList[level-1].key[3]))!=plane)
- {
- mess="The selected images are not compatible.";
- valid=false;
- }
- }
- }
-
- //Dimention validation
- //Compatibility with maximum
- if(valid)
- {
-
- int rows;
- int cols;
- int planes;
- std::string s;
- std::istringstream t(s);
- s=row;
- t >> rows;
- if(row==""){rows=1;}
- s=col;
- t >> cols;
- if(col==""){cols=1;}
- s=plane;
- t >> planes;
- if(plane==""){planes=1;}
-
- int dim = 0;
- if (planes>1) dim=3;
- else if (cols>1) dim=2;
- else if (rows>1) dim=1;
-
- if (dim == 0)
- {
- mess="Unknown image dimension : cannot select !";
- valid= false;
- }
- else if (dim>GetMaxDimension())
- {
- mess="Selecting ";
- mess+=dim;
- mess+="D images is not allowed !";
- valid= false;
- }
- if ( dim == GetMaxDimension() )
- {
- mess="Cannot add this image to selection : would result in a ";
- mess+=(dim+1);
- mess+="D image!";
-
- valid= false;
- }
- if ( dim < GetMinDimension() && sel.size()<2 )
- {
- mess="Cannot build the selection as it would result in a ";
- mess+=dim;
- mess+="D image, and the minimum is ";
- mess+=GetMinDimension();
- mess+="D!";
- valid= false;
- }
- }
- }
- else
- {
- mess="Cannot have 0 images selected";
- valid=false;
- }
-
//Send an event telling wether the selection is valid or not
wxCommandEvent event( 0, GetId() );
event.SetEventObject( this );
- if(valid)
- {
- mess="Selection OK !";
- event.SetInt(0);
- }
- else
- {event.SetInt(1);}
- event.SetString(crea::std2wx(mess));
+ std::vector<tree::Node*> sel=GetSelected((mLevelList.size()+1));
+ event.SetClientData(&sel);
GetEventHandler()->ProcessEvent( event );
-
-
}
-
//================================================================
- vtkImageData* WxTreeView::GetSelectedImage(int dim)
- {
-
- return NULL;
- }
-
- void WxTreeView::GetSelectedImages(std::vector<vtkImageData*>& f, int dim)
+ void WxTreeView::GetSelectedAsString(std::vector<std::string>&s)
{
- /*
- std::vector<tree::Node*> im=GetSelected(level+1);
+ int level=mLevelList.size();
+ std::vector<tree::Node*> sel=GetSelected(level+1);
+ std::vector<tree::Node*>::iterator i;
- // Create the output data
- if (im.size()==1)
- {
- // Only one image : give it
- vtkImageData* out = vtkImageData::New();
- out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
- f.push_back( out );
- }
- else if (im.size()>1)
+ for (i=sel.begin(); i!=sel.end(); ++i)
{
- vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
- if (first->GetDataDimension()==2)
- {
- // n2D to 3D
- vtkImageData* out = vtkImageData::New();
- out->CopyStructure(first);
- out->SetScalarType(first->GetScalarType());
- int ext[6];
- first->GetExtent(ext);
- ext[5] = im.size();
- out->SetExtent(ext);
- // LG : TODO : Z Spacing ?
-
- out->AllocateScalars();
-
- //first->Print(std::cout);
- // out->Print(std::cout);
-
- int dim[3];
- first->GetDimensions(dim);
- unsigned long imsize =
- ( (unsigned long)first->GetScalarPointer(0,1,0)
- - (unsigned long)first->GetScalarPointer(0,0,0))
- *dim[1];
-
- int slice = 0;
- std::vector<DicomNode*>::iterator it;
- for (it=im.begin(); it!=im.end(); ++it)
- {
- //std::cout << "copying slice "<<slice <<std::endl;
- vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
-
- void* src = cur->GetScalarPointer(0,0,0);
- void* dst = out->GetScalarPointer(0,0,slice);
- // std::cout << "src="<<src<<std::endl;
- // std::cout << "dst="<<dst<<std::endl;
- // std::cout << "siz="<<imsize<<std::endl;
- memcpy(dst,src,imsize);
-
- slice++;
- }
- f.push_back(out);
+ std::string filename=(*i)->GetAttribute("FullFileName");
+ s.push_back(filename);
}
- else
- {
- // n3D
- std::vector<DicomNode*>::iterator it;
- for (it=im.begin(); it!=im.end(); ++it)
- {
- vtkImageData* out = vtkImageData::New();
- out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
- f.push_back(out);
- }
- }
- }
- */
}
+ //================================================================
BEGIN_EVENT_TABLE(WxTreeView, wxPanel)
/*
EVT_SIZE(MyFrame::OnSize)
wxListCtrl* GetCtrl(int l) { return mLevelList[l].wxCtrl; }
/// return the wxSplitter of one level
wxSplitterWindow* GetSplitter(int l) { return mLevelList[l].wxSplitter; }
+ //Returns the maximum number of levels
+ int GetNumberOfLevels(){ return mLevelList.size(); }
/// Gets the user selected data from the level passed as a parameter
std::vector<tree::Node*> GetSelected(int level);
///Validates the selected images
- void ValidateSelectedImages();
- ///Returns the selected data as vtkImageData
- vtkImageData* GetSelectedImage(int dim);
- ///Returns the selected data as vtkImageData
- void GetSelectedImages(std::vector<vtkImageData*>& s, int dim);
-
+ void ValidateSelectedImages();
+ ///Gets selected filenames
+ void GetSelectedAsString(std::vector<std::string>&s);
// Updates the view of a level given the selected items of upper level
// Recursive method
virtual void RecursiveUpdateLevel( int );