tutorials/medical/viewer.cc

00001 // RedGRID by Orel & Mick
00002 // Parallel VTK Viewer for Medical Tutorial
00003 
00004 #include "vtkImageData.h"
00005 #include "vtkPointData.h"
00006 #include "vtkDataArray.h"
00007 #include "vtkUnsignedShortArray.h"
00008 #include "vtkMath.h"
00009 #include "vtkPolyData.h"
00010 #include "vtkPolyDataMapper.h"
00011 #include "vtkRenderWindow.h"
00012 #include "vtkRenderWindowInteractor.h"
00013 #include "vtkRenderer.h"
00014 #include "vtkCamera.h"
00015 #include "vtkContourFilter.h"
00016 #include "vtkDataSet.h"
00017 #include "vtkMultiProcessController.h"
00018 #include "vtkMPIController.h"
00019 #include "vtkAppendPolyData.h"
00020 #include "vtkTimerLog.h"
00021 #include "vtkProperty.h"
00022 #include "vtkLookupTable.h"
00023 
00024 #include <mpi.h>
00025 #include <cassert>
00026 #include <unistd.h>
00027 #include <iostream>
00028 #include "RedCORBA.hh"
00029 #include "RedSYM.hh"
00030 #include "CorbaTools.hh"
00031 using namespace std;
00032 
00033 //===========================================================================//
00034 
00035 RedCORBA::Proxy * proxy;;
00036 RedCORBA::Node * node;
00037 RedSYM::Grid * grid;
00038 RedSYM::DistributionInt * distribution; 
00039 int prank, psize;
00040 string sourceID, dataID;
00041 RedSYM::TypeCode rs_typecode;
00042 int vtk_typecode, sizeoftype;
00043 CORBA::ORB_ptr orb;
00044 RedCORBA::ConnectionID connection;
00045 RedCORBA::ProxyChannel * channel;
00046 static const int NODE_TAG=999;
00047 float dx, dy, dz;
00048 float ISO_VALUE = 900.0; // default
00049 
00050 //===========================================================================//
00051 
00052 // This will be called by all processes
00053 void MyMain( vtkMultiProcessController *controller, void *arg )
00054 {
00055   vtkImageData * imagedata;
00056   
00057   try {
00058     
00059     // ==== create node & proxy ==== //    
00060     if(prank == 0) 
00061       proxy =  new RedCORBA::Proxy("viewer3D",psize,orb,RedCORBA::_non_blocking); 
00062     node = new RedCORBA::Node("viewer3D",prank,psize,orb,RedCORBA::_blocking);
00063     if(prank == 0) proxy->waitActivation();  
00064     
00065     // ==== connection  ==== //    
00066     if(prank == 0) 
00067       connection = proxy->connect(sourceID);
00068     node->waitConnection(sourceID); 
00069     controller->Barrier();
00070     
00071     // ==== get remote domain ==== //
00072     connection = node->getConnectionID(sourceID);
00073     RedSYM::ParallelGrid * remote_grid = 
00074       (RedSYM::ParallelGrid *) node->getRemoteParallelObjectFromProxy(connection,dataID,RedSYM::_grid);
00075     RedSYM::BlockInt domain = remote_grid->getDomain();
00076     assert(domain.getNumberOfDimensions() == 3);
00077 
00078     // get grid spacing
00079     double dx = remote_grid->getGridSpacing(0);
00080     double dy = remote_grid->getGridSpacing(1);
00081     double dz = remote_grid->getGridSpacing(2);
00082     cout << "dx = " << dx << "  dy = " << dy << "  dz = " << dz << endl;
00083 
00084     // ==== create distribution ==== //
00085     
00086     // define topology
00087     RedSYM::AxisProc axisproc[3] = {0, 0, 0};
00088     RedSYM::AxisType axistype[3] = {RedSYM::_collapsed, RedSYM::_collapsed, RedSYM::_collapsed} ;
00089     RedSYM::AxisInfo axisinfo[3] = {0, 0, 0};
00090     
00091     if ((psize%4 == 0)&&(psize > 4)){
00092       axisproc[0] = psize/4; 
00093       axisproc[1] = 2; 
00094       axisproc[2] = 2;
00095       axistype[0] = RedSYM::_block; 
00096       axistype[1] = RedSYM::_block; 
00097       axistype[2] = RedSYM::_block;
00098     }
00099     else if ((psize%3 == 0)&&(psize > 3)){
00100       axisproc[0] = psize/3; 
00101       axisproc[1] = 3;
00102       axistype[0] = RedSYM::_block; 
00103       axistype[1] = RedSYM::_block;
00104     }
00105     else if ((psize%2 == 0)&&(psize > 3)){
00106       axisproc[0] = psize/2; 
00107       axisproc[1] = 2;
00108       axistype[0] = RedSYM::_block; 
00109       axistype[1] = RedSYM::_block;
00110     }
00111     else {
00112       axisproc[0] = psize;
00113       axistype[0] = RedSYM::_block;
00114     }
00115 
00116     // compute grid spacing
00117     // dx = 200.0/(domain[0].upperbound() - domain[0].lowerbound() + 1);
00118     // dy = 200.0/(domain[1].upperbound() - domain[1].lowerbound() + 1);
00119     // dz = 200.0/(domain[2].upperbound() - domain[2].lowerbound() + 1);
00120     // cout << "dx = " << dx << "  dy = " << dy << "  dz = " << dz << endl;
00121 
00122     // the distribution
00123     distribution = RedSYM::DistributionFactoryInt::createBlockCyclic(domain, 
00124                                                                      prank, 
00125                                                                      axisproc, 
00126                                                                      axistype, 
00127                                                                      axisinfo);
00128     
00129     // overlap
00130     assert(distribution->size() == 1);
00131     if ((*distribution)[0][0].lowerbound() != 0) (*distribution)[0][0].lowerbound()--;
00132     if ((*distribution)[0][1].lowerbound() != 0) (*distribution)[0][1].lowerbound()--;
00133     if ((*distribution)[0][2].lowerbound() != 0) (*distribution)[0][2].lowerbound()--;
00134     int x0, x1, y0, y1, z0, z1;
00135     x0 = (*distribution)[0][0].lowerbound(); 
00136     x1 = (*distribution)[0][0].upperbound();
00137     y0 = (*distribution)[0][1].lowerbound(); 
00138     y1 = (*distribution)[0][1].upperbound();     
00139     z0 = (*distribution)[0][2].lowerbound(); 
00140     z1 = (*distribution)[0][2].upperbound(); 
00141 
00142     // the typecode
00143     rs_typecode = remote_grid->getTypeCode(); 
00144     
00145     sizeoftype =  RedSYM::SizeOfType[rs_typecode];
00146     switch(rs_typecode) {
00147     case RedSYM::_octet : 
00148       vtk_typecode = VTK_CHAR;
00149       break;
00150     case RedSYM::_short : 
00151       vtk_typecode = VTK_SHORT;
00152       break;
00153     case RedSYM::_long : 
00154       vtk_typecode = VTK_LONG;
00155       break;
00156     case RedSYM::_unsigned_short : 
00157       vtk_typecode = VTK_UNSIGNED_SHORT;
00158       break;
00159     case RedSYM::_unsigned_long :
00160       vtk_typecode = VTK_UNSIGNED_LONG;
00161       break;
00162     case RedSYM::_float : 
00163       vtk_typecode = VTK_FLOAT;
00164       break;
00165     case RedSYM::_double : 
00166       vtk_typecode = VTK_DOUBLE;
00167       break;
00168     default:
00169       cerr << "unknown type code !!!" << endl;
00170     }
00171     
00172     // ==== image data ==== //    
00173     imagedata = vtkImageData::New();
00174     imagedata->SetDimensions(x1-x0+1, y1-y0+1, z1-z0+1)  ;
00175     imagedata->SetSpacing(dx, dy, dz);
00176     imagedata->SetOrigin(x0*dx,y0*dy,z0*dz);
00177     imagedata->SetScalarType(vtk_typecode)  ;
00178     imagedata->AllocateScalars()  ;
00179     
00180     // ==== create grid 3D ==== //
00181     grid = new RedSYM::Grid(dataID,prank,psize,3); // 3D 
00182     int serie0 = grid->addSerie("serie0",rs_typecode);
00183     grid->setDistribution(*distribution);
00184     grid->wrap(serie0, 0, imagedata->GetScalarPointer());
00185     node->addData(grid); 
00186     
00187     //  ==== set ready ==== //
00188     if(prank == 0) 
00189       proxy->ready(RedCORBA::_non_blocking); 
00190     node->ready(RedCORBA::_blocking); 
00191     cout << "Node " << prank << " Ready" << endl;
00192     controller->Barrier();  
00193     
00194     // ==== create channel ==== //
00195     if(prank == 0) {      
00196       cout << "create channel for " << dataID << "... " << flush;
00197       channel = proxy->createChannel(connection,dataID);
00198       cout << "done" << endl;
00199     }    
00200     controller->Barrier();  
00201     
00202     // get request
00203     if(prank == 0) {
00204       cout << "get data from reader... " << flush;
00205       channel->get(0,RedCORBA::_blocking);
00206       cout << "done" << endl;
00207     }
00208     controller->Barrier(); 
00209     
00210   }
00211   catch(RedCORBA::Exception & ex) { 
00212     cout << "RedCORBA Exception: " << ex <<  endl; 
00213     exit(EXIT_FAILURE);
00214   }
00215   catch(ColCOWS::ColCOWSException & ex) { 
00216     cout << "ColCOWS Exception: " << ex <<  endl; 
00217     exit(EXIT_FAILURE);
00218   }
00219   catch(...) { 
00220     cout << "Unknown Exception!" << endl; exit(EXIT_FAILURE);
00221   }
00222   
00223   // Iso-surface Filter
00224   vtkContourFilter * iso = vtkContourFilter::New();
00225   iso->SetInput(imagedata);
00226   iso->SetValue(0, ISO_VALUE);
00227   iso->ComputeScalarsOff();
00228   iso->ComputeGradientsOff();
00229   
00230   // ==== slave processes ==== //
00231   if (prank != 0) {
00232     controller->Send(iso->GetOutput(), 0, NODE_TAG);
00233   }
00234 
00235   // ==== master process ==== //
00236   else {
00237 
00238     vtkActor * isoActors[psize];   
00239     vtkPolyDataMapper * isoMappers[psize];
00240 
00241     vtkRenderer *ren = vtkRenderer::New();
00242     vtkRenderWindow *renWindow = vtkRenderWindow::New();
00243     vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
00244     vtkTimerLog *timer = vtkTimerLog::New();
00245     vtkCamera *cam = vtkCamera::New();
00246 
00247     isoMappers[0] = vtkPolyDataMapper::New();
00248     isoMappers[0]->SetInput(iso->GetOutput());
00249     isoActors[0] = vtkActor::New();
00250     isoActors[0]->SetMapper(isoMappers[0]); 
00251     ren->AddActor(isoActors[0]);
00252     
00253     // Collect the data from slaves and render it.
00254     for (int i = 1; i < psize; ++i) {
00255       vtkPolyData *pd;
00256       controller->Receive(pd, i, NODE_TAG);
00257       isoMappers[i] = vtkPolyDataMapper::New();
00258       isoMappers[i]->SetInput(pd);
00259       isoActors[i] = vtkActor::New();
00260       isoActors[i]->SetMapper(isoMappers[i]);
00261       ren->AddActor(isoActors[i]);
00262     }
00263 
00264     // Create Lookup Table
00265     vtkLookupTable *lookupTable = vtkLookupTable::New();
00266     lookupTable->SetTableRange (0, psize-1);
00267     lookupTable->SetHueRange (.70, 0);
00268     lookupTable->SetSaturationRange (1, 1);
00269     lookupTable->SetValueRange (1, 1);
00270     lookupTable->Build();
00271 
00272 
00273     // set one color per processor
00274     for (int i = 0; i < psize; ++i) {
00275       double procColor[3];
00276       lookupTable->GetColor(i,procColor);
00277       isoActors[i]->GetProperty()->SetColor(procColor); 
00278     }
00279 
00280     
00281     // Create the rendering part of the pipeline
00282     iren->SetRenderWindow(renWindow);
00283     renWindow->AddRenderer(ren);
00284     ren->SetBackground(0.9, 0.9, 0.9);
00285     renWindow->SetSize( 400, 400);
00286     cam->SetFocalPoint(100, 100, 100);
00287     cam->SetPosition(100, 450, 100);
00288     cam->SetViewUp(0, 0, -1);
00289     cam->SetViewAngle(30);
00290     cam->SetClippingRange(177.0, 536.0);
00291     ren->SetActiveCamera(cam);
00292 
00293     // Initialize the event loop and then start it.
00294     iren->Initialize();
00295     cout << "start parallel iso-surface calculation, wait few seconds..." << endl;
00296     iren->Start(); 
00297 
00298     // nb triangles
00299     for (int i = 0; i < psize; ++i) {
00300       int nb_triangles = isoMappers[i]->GetInput()->GetNumberOfCells();
00301       cerr << nb_triangles << " triangles on process " << i << endl;
00302     }
00303     
00304     // Tell the other processors to stop processing RMIs.
00305     for (int i = 1; i < psize; ++i) {
00306       controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG); 
00307     }
00308     
00309     // Clean up
00310     ren->Delete();
00311     renWindow->Delete();
00312     iren->Delete();
00313     cam->Delete();
00314     timer->Delete();
00315   }
00316   
00317   try {
00318     
00319     // ==== shutdown ==== //    
00320     if(prank == 0) {
00321       proxy->disconnect(connection);
00322       proxy->deactivate();
00323     }
00324     controller->Barrier();  
00325 
00326     // if(prank == 0) delete proxy;
00327     // delete node;    
00328     // delete grid;
00329     // delete distribution;    
00330   }
00331   catch(RedCORBA::Exception & ex) { 
00332     cout << "RedCORBA Exception: " << ex <<  endl; 
00333     exit(EXIT_FAILURE);
00334   }
00335   catch(ColCOWS::ColCOWSException & ex) { 
00336     cout << "ColCOWS Exception: " << ex <<  endl; 
00337   }
00338   catch(...) { 
00339     cout << "Unknown Exception!" << endl; 
00340     exit(EXIT_FAILURE);
00341   }
00342   
00343   controller->Barrier();  
00344 }
00345 
00346 //===========================================================================//
00347 
00348 int main(int argc, char** argv) 
00349 {
00350   sourceID = "reader3D";
00351   dataID = "mygrid";
00352 
00353   if (argc >= 2) { 
00354     ISO_VALUE = atof(argv[1]);
00355   }
00356   else {
00357     cout << "Usage: " << " [iso_value] [ORB options]" << endl;
00358     return 0;
00359   }
00360   
00361   vtkMultiProcessController *controller;
00362   controller = vtkMPIController::New();
00363   controller->Initialize(&argc, &argv);
00364   
00365   if (controller->IsA("vtkThreadedController"))
00366     controller->SetNumberOfProcesses(2);
00367   
00368   prank = controller->GetLocalProcessId();
00369   psize = controller->GetNumberOfProcesses();
00370   cout << "prank = " << prank << endl;
00371   cout << "psize = " << psize << endl;
00372   
00373   controller->SetSingleMethod(MyMain, reinterpret_cast<void*>(argv[1]));
00374   
00375   // ====  start ORB ==== //
00376   orb = CorbaTools::startORB(argc,argv);
00377   
00378   // ====  start Controller ==== //
00379   controller->SingleMethodExecute();
00380   controller->Barrier(); 
00381   
00382   // ==== goodbye ==== //    
00383   CorbaTools::killORB();
00384   controller->Finalize();
00385   controller->Delete();
00386   cout << "return OK" << endl;
00387   
00388   return 0;
00389 }
00390 
00391 //===========================================================================//
00392 
00393 // EOF
00394 
00395 

Generated on Mon Sep 25 14:55:54 2006 for RedGRID by  doxygen 1.4.6