Xmipp  v3.23.11-Nereus
Public Member Functions | Public Attributes | List of all members

#include <mpi_classify_CL2D.h>

Collaboration diagram for CL2D:
Collaboration graph
[legend]

Public Member Functions

 CL2D ()
 
 ~CL2D ()
 
 CL2D (const CL2D &)=delete
 
 CL2D (const CL2D &&)=delete
 
CL2Doperator= (const CL2D &)=delete
 
CL2Doperator= (const CL2D &&)=delete
 
void readImage (Image< double > &I, size_t objId, bool applyGeo) const
 Read Image. More...
 
void initialize (MetaDataDb &_SF, std::vector< MultidimArray< double > > &_codes0)
 Initialize. More...
 
void shareAssignments (bool shareAssignment, bool shareUpdates, bool shareNonCorr)
 Share assignments. More...
 
void shareSplitAssignments (Matrix1D< int > &assignment, CL2DClass *node1, CL2DClass *node2) const
 Share split assignment. More...
 
void write (const FileName &fnODir, const FileName &fnRoot, int level) const
 Write the nodes. More...
 
void lookNode (MultidimArray< double > &I, int oldnode, int &newnode, CL2DAssignment &bestAssignment)
 
void transferUpdates ()
 
void run (const FileName &fnODir, const FileName &fnOut, int level)
 
int cleanEmptyNodes ()
 
void splitNode (CL2DClass *node, CL2DClass *&node1, CL2DClass *&node2, std::vector< size_t > &finalAssignment) const
 
void splitFirstNode ()
 

Public Attributes

size_t Nimgs =0
 Number of images. More...
 
MetaDataDbSF =nullptr
 Pointer to input metadata. More...
 
std::vector< CL2DClass * > P
 List of nodes. More...
 

Detailed Description

Class for a CL2D

Definition at line 160 of file mpi_classify_CL2D.h.

Constructor & Destructor Documentation

◆ CL2D() [1/3]

CL2D::CL2D ( )
inline

Empty constructor

Definition at line 172 of file mpi_classify_CL2D.h.

172 {}

◆ ~CL2D()

CL2D::~CL2D ( )

Destructor

Definition at line 723 of file mpi_classify_CL2D.cpp.

724 {
725  int qmax=P.size();
726  for (int q=0; q<qmax; q++)
727  delete P[q];
728 }
std::vector< CL2DClass * > P
List of nodes.

◆ CL2D() [2/3]

CL2D::CL2D ( const CL2D )
delete

◆ CL2D() [3/3]

CL2D::CL2D ( const CL2D &&  )
delete

Member Function Documentation

◆ cleanEmptyNodes()

int CL2D::cleanEmptyNodes ( )

Clean empty nodes. The number of nodes removed is returned.

Definition at line 1255 of file mpi_classify_CL2D.cpp.

1256 {
1257  int retval = 0;
1258  std::vector<CL2DClass *>::iterator ptr = P.begin();
1259  while (ptr != P.end())
1260  if ((*ptr)->currentListImg.size() == 0)
1261  {
1262  ptr = P.erase(ptr);
1263  retval++;
1264  }
1265  else
1266  ptr++;
1267  return retval;
1268 }
std::vector< CL2DClass * > P
List of nodes.

◆ initialize()

void CL2D::initialize ( MetaDataDb _SF,
std::vector< MultidimArray< double > > &  _codes0 
)

Initialize.

Definition at line 748 of file mpi_classify_CL2D.cpp.

750 {
751  if (prm->node->rank == 1)
752  std::cout << "Initializing ...\n";
753 
754  SF = &_SF;
755  Nimgs = SF->size();
756 
757  // Start with _Ncodes0 codevectors
758  CL2DAssignment assignment;
759  assignment.corr = 1;
760  bool initialCodesGiven = _codes0.size() > 0;
761  for (int q = 0; q < prm->Ncodes0; q++)
762  {
763  P.push_back(new CL2DClass());
764  if (initialCodesGiven)
765  {
766  P[q]->Pupdate = _codes0[q];
767  P[q]->nextListImg.push_back(assignment);
768  P[q]->transferUpdate(false);
769  }
770  }
771 
772  // Estimate sigma and if no previous classes have been given,
773  // assign randomly
774  prm->sigma = 0;
775  if (prm->node->rank == 1)
777  Image<double> I;
778  MultidimArray<double> Iaux, Ibest;
779  bool oldUseCorrelation = prm->useCorrelation;
780  prm->useCorrelation = true; // Since we cannot make the assignment before calculating sigma
781  CL2DAssignment bestAssignment;
782  size_t idx=0;
783  SF->fillConstant(MDL_REF,"-1");
784  for (size_t _ : prm->SF.ids())
785  {
786  if ((idx+1)%prm->node->size==prm->node->rank)
787  {
788  int q = -1;
789  if (!initialCodesGiven)
790  q = idx % (prm->Ncodes0);
791  size_t objId = prm->objId[idx];
792  readImage(I, objId, true);
793 
794  // Measure the variance of the signal outside a circular mask
795  double avg, stddev;
796  I().computeAvgStdev_within_binary_mask(prm->mask, avg, stddev);
797  prm->sigma += stddev;
798 
799  // Put it randomly in one of the classes
800  bestAssignment.objId = assignment.objId = objId;
801  if (!initialCodesGiven)
802  {
803  bestAssignment.corr = 1;
804  P[q]->updateProjection(I(), bestAssignment);
805  }
806  else
807  {
808  bestAssignment.corr = 0;
809  q = -1;
810  for (int qp = 0; qp < prm->Ncodes0; qp++)
811  {
812  Iaux = I();
813  P[qp]->fit(Iaux, assignment);
814  if (assignment.corr > bestAssignment.corr)
815  {
816  bestAssignment = assignment;
817  Ibest = Iaux;
818  q = qp;
819  }
820  }
821  if (q != -1)
822  P[q]->updateProjection(Ibest, bestAssignment);
823  }
824  SF->setValue(MDL_REF, q + 1, objId);
825  if (idx % 100 == 0 && prm->node->rank == 1)
826  progress_bar(idx);
827  }
828  idx++;
829  }
830  prm->node->barrierWait();
831  if (prm->node->rank == 1)
833  prm->useCorrelation = oldUseCorrelation;
834 
835  // Put sigma in common
836  MPI_Allreduce(MPI_IN_PLACE, &(prm->sigma), 1, MPI_DOUBLE, MPI_SUM,
837  MPI_COMM_WORLD);
838  prm->sigma *= sqrt(2.0) / Nimgs;
839 
840  // Share all assignments
841  shareAssignments(true, true, false);
842 
843  // Now compute the histogram of corr values
844  if (!prm->classicalMultiref)
845  {
846  if (prm->node->rank == 1)
847  {
848  std::cout << "Computing histogram of correlation values\n";
850  }
851 
852  CL2DAssignment inClass, outClass;
853  size_t idx=0;
854  for (size_t _ : prm->SF.ids())
855  {
856  if ((idx+1)%prm->node->size==prm->node->rank)
857  {
858  size_t objId = prm->objId[idx];
859  readImage(I, objId, false);
860 
861  int q;
862  SF->getValue(MDL_REF, q, objId);
863  if (q == -1)
864  continue;
865  q -= 1;
866 
867  outClass.objId = inClass.objId = objId;
868  if (q != -1)
869  {
870  Iaux = I();
871  P[q]->fit(Iaux, inClass);
872  P[q]->updateProjection(Iaux, inClass);
873  if (prm->Ncodes0 > 1)
874  for (int qp = 0; qp < prm->Ncodes0; qp++)
875  {
876  if (qp == q)
877  continue;
878  Iaux = I();
879  P[qp]->fit(Iaux, outClass);
880  P[qp]->updateNonProjection(outClass.corr);
881  }
882  }
883  if (prm->node->rank == 1 && idx % 100 == 0)
884  progress_bar(idx);
885  }
886  idx++;
887  }
888  prm->node->barrierWait();
889  if (prm->node->rank == 1)
891 
892  shareAssignments(false, true, true);
893  }
894 }
size_t size
Definition: xmipp_mpi.h:52
void init_progress_bar(long total)
void sqrt(Image< double > &op)
bool getValue(MDObject &mdValueOut, size_t id) const override
int Ncodes0
Initial number of code vectors.
size_t Nimgs
Number of images.
virtual IdIteratorProxy< false > ids()
bool classicalMultiref
Classical Multiref.
void barrierWait()
Definition: xmipp_mpi.cpp:171
void shareAssignments(bool shareAssignment, bool shareUpdates, bool shareNonCorr)
Share assignments.
void fillConstant(MDLabel label, const String &value) override
std::vector< size_t > objId
MetaDataDb * SF
Pointer to input metadata.
void progress_bar(long rlen)
double sigma
Noise in the images.
bool useCorrelation
Use Correlation instead of Correntropy.
size_t size() const override
size_t rank
Definition: xmipp_mpi.h:52
Class to which the image belongs (int)
void readImage(Image< double > &I, size_t objId, bool applyGeo) const
Read Image.
bool setValue(const MDObject &mdValueIn, size_t id) override
Definition: metadata_db.cpp:90
ProgClassifyCL2D * prm
std::vector< CL2DClass * > P
List of nodes.
MultidimArray< int > mask
Mask for the background.

◆ lookNode()

void CL2D::lookNode ( MultidimArray< double > &  I,
int  oldnode,
int &  newnode,
CL2DAssignment bestAssignment 
)

Look for a node suitable for this image. The image is rotationally and translationally aligned with the best node.

Definition at line 944 of file mpi_classify_CL2D.cpp.

946 {
947 #ifdef DEBUG
948  std::cout << "Looking for node. Oldnode=" << oldnode << std::endl;
949 #endif
950  int Q = P.size();
951  int bestq = -1;
952  MultidimArray<double> bestImg, Iaux;
953  Matrix1D<double> corrList;
954  corrList.resizeNoCopy(Q);
955  CL2DAssignment assignment;
956  bestAssignment.likelihood = bestAssignment.corr = 0;
957  size_t objId = bestAssignment.objId;
958  for (int q = 0; q < Q; q++)
959  {
960  // Check if q is neighbour of the oldnode
961  bool proceed = false;
962  if (oldnode >= 0)
963  {
964  if (oldnode<Q)
965  {
966  int imax = P[oldnode]->neighboursIdx.size();
967  for (int i = 0; i < imax; i++)
968  {
969  if (P[oldnode]->neighboursIdx[i] == q)
970  {
971  proceed = true;
972  break;
973  }
974  }
975  if (!proceed)
976  {
977  double threshold = 3.0 * P[oldnode]->currentListImg.size();
978  threshold = XMIPP_MAX(threshold,1000);
979  threshold = (double) (XMIPP_MIN(threshold,Nimgs)) / Nimgs;
980  proceed = (rnd_unif(0, 1) < threshold);
981  }
982  }
983  else
984  {
985  // In some strange conditions we may loose the reference to its neighbours
986  proceed = true;
987  }
988  }
989  else
990  proceed = true;
991 
992  if (proceed) {
993  // Try this image
994  Iaux = I;
995  P[q]->fit(Iaux, assignment);
996  VEC_ELEM(corrList,q) = assignment.corr;
997 #ifdef DEBUG
998  std::cout << " Proceeding with node " << q << " corr=" << assignment.corr << std::endl;
999 #endif
1000  if ((!prm->classicalMultiref && assignment.likelihood > bestAssignment.likelihood) ||
1001  (prm->classicalMultiref && assignment.corr > bestAssignment.corr) ||
1002  prm->classifyAllImages && bestAssignment.corr==0) {
1003  bestq = q;
1004  bestImg = Iaux;
1005  bestAssignment = assignment;
1006  }
1007  }
1008  }
1009 
1010  I = bestImg;
1011  newnode = bestq;
1012  bestAssignment.objId = objId;
1013 
1014  // Assign it to the new node and remove it from the rest
1015  // of nodes if it was among the best
1016 #ifdef DEBUG
1017  std::cout << " New node=" << newnode << std::endl;
1018 #endif
1019  if (newnode != -1)
1020  {
1021  P[newnode]->updateProjection(I, bestAssignment);
1022  if (!prm->classicalMultiref)
1023  for (int q = 0; q < Q; q++)
1024  if (q != newnode && corrList(q) > 0)
1025  P[q]->updateNonProjection(corrList(q));
1026  }
1027 }
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
size_t Nimgs
Number of images.
bool classicalMultiref
Classical Multiref.
bool classifyAllImages
Clasify all images.
#define i
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
double rnd_unif()
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
ProgClassifyCL2D * prm
std::vector< CL2DClass * > P
List of nodes.

◆ operator=() [1/2]

CL2D& CL2D::operator= ( const CL2D )
delete

◆ operator=() [2/2]

CL2D& CL2D::operator= ( const CL2D &&  )
delete

◆ readImage()

void CL2D::readImage ( Image< double > &  I,
size_t  objId,
bool  applyGeo 
) const

Read Image.

Definition at line 731 of file mpi_classify_CL2D.cpp.

732 {
733  if (applyGeo)
734  I.readApplyGeo(*SF, objId);
735  else
736  {
737  FileName fnImg;
738  SF->getValue(MDL_IMAGE, fnImg, objId);
739  I.read(fnImg);
740  }
741  I().setXmippOrigin();
742  if (prm->normalizeImages)
743  I().statisticsAdjust(0., 1.);
744 }
bool getValue(MDObject &mdValueOut, size_t id) const override
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams &params=DefaultApplyGeoParams)
bool normalizeImages
Normalize input images.
MetaDataDb * SF
Pointer to input metadata.
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
ProgClassifyCL2D * prm
Name of an image (std::string)

◆ run()

void CL2D::run ( const FileName fnODir,
const FileName fnOut,
int  level 
)

Quantize with the current number of codevectors

Definition at line 1039 of file mpi_classify_CL2D.cpp.

1040 {
1041  size_t Q = P.size();
1042 
1043  if (prm->node->rank == 1)
1044  std::cout << "Quantizing with " << Q << " codes...\n";
1045 #ifdef DEBUG
1046  Image<double> save;
1047  for (int q=0; q<Q; q++)
1048  {
1049  save()=P[q]->P;
1050  save.write(formatString("PPPclass%04d.xmp",q));
1051  }
1052  std::cout << "Classes written. Press any key" << std::endl;
1053  char c; std::cin >> c;
1054 #endif
1055 
1056  std::vector<int> oldAssignment, newAssignment;
1057 
1058  int iter = 1;
1059  bool goOn = true;
1060  MetaDataVec MDChanges;
1061  Image<double> I;
1062  int progressStep = XMIPP_MAX(1,Nimgs/60);
1063  CL2DAssignment assignment;
1064  FileName fnResultsDir=formatString("%s/level_%02d",fnODir.c_str(),level);
1065  fnResultsDir.makePath(0755);
1066  while (goOn)
1067  {
1068  if (prm->node->rank == 1)
1069  {
1070  std::cout << "Iteration " << iter << " ...\n";
1072  }
1073 
1074  size_t K = std::min((size_t)prm->Nneighbours+1,Q);
1075  if (K == 0)
1076  K = Q;
1077  for (size_t q = 0; q < Q; q++)
1078  P[q]->lookForNeighbours(P, K);
1079 
1080  int node;
1081  double corrSum = 0;
1082  SF->getColumnValues(MDL_REF, oldAssignment);
1083  int *ptrOld = &(oldAssignment[0]);
1084  for (size_t n = 0; n < Nimgs; ++n, ++ptrOld)
1085  *ptrOld -= 1;
1086  SF->fillConstant(MDL_REF, "-1");
1087  size_t idx=0;
1088  for (size_t _ : prm->SF.ids())
1089  {
1090  if ((idx+1)%prm->node->size==prm->node->rank)
1091  {
1092  size_t objId = prm->objId[idx];
1093  readImage(I, objId, false);
1094  LOG(((String)"Processing image: "+I.name()).c_str());
1095 
1096  assignment.objId = objId;
1097  lookNode(I(), oldAssignment[idx], node, assignment);
1098  SF->setValue(MDL_REF, node + 1, objId);
1099  corrSum += assignment.corr;
1100  if (prm->node->rank == 1 && idx % progressStep == 0)
1101  progress_bar(idx);
1102  }
1103  idx++;
1104  }
1105  prm->node->barrierWait();
1106 
1107  // Gather all pieces computed by nodes
1108  MPI_Allreduce(MPI_IN_PLACE, &corrSum, 1, MPI_DOUBLE, MPI_SUM,
1109  MPI_COMM_WORLD);
1110  shareAssignments(true, true, true);
1111 
1112  // Some report
1113  size_t idMdChanges=0;
1114  int finish=0;
1115  if (prm->node->rank == 1)
1116  {
1117  progress_bar(Nimgs);
1118  double avgSimilarity = corrSum / Nimgs;
1119  if (avgSimilarity==0)
1120  {
1121  std::cerr << "The average correlation is 0.0, make sure that the maximum allowed shift is enough\n";
1122 
1123  //MPI_Abort(MPI_COMM_WORLD,ERR_UNCLASSIFIED);
1124  finish=1;
1125  }
1126  std::cout << "\nAverage correlation with input vectors=" << avgSimilarity << std::endl;
1127  idMdChanges = MDChanges.addObject();
1128  MDChanges.setValue(MDL_ITER, iter, idMdChanges);
1129  MDChanges.setValue(MDL_CL2D_SIMILARITY, avgSimilarity, idMdChanges);
1130  }
1131  MPI_Bcast(&finish,1, MPI_INT, 1, MPI_COMM_WORLD);
1132  if (finish)
1133  {
1134  MPI_Finalize();
1135  exit(ERR_UNCLASSIFIED);
1136  }
1137 
1138 
1139  // Count changes
1140  SF->getColumnValues(MDL_REF, newAssignment);
1141  int *ptrNew = &(newAssignment[0]);
1142  for (size_t n = 0; n < Nimgs; ++n, ++ptrNew)
1143  *ptrNew -= 1;
1144  size_t Nchanges = 0;
1145  if (iter > 1)
1146  {
1147  int *ptrNew = &(newAssignment[0]);
1148  ptrOld = &(oldAssignment[0]);
1149  for (size_t n = 0; n < Nimgs; ++n, ++ptrNew, ++ptrOld)
1150  if (*ptrNew != *ptrOld)
1151  ++Nchanges;
1152  }
1153  if (prm->node->rank == 1)
1154  {
1155  FileName fnClasses=formatString("%s/%s_classes.xmd",fnResultsDir.c_str(),fnOut.c_str());
1156  if (iter==1)
1157  {
1159  dummy.write(formatString("classes@%s",fnClasses.c_str()));
1160  }
1161 
1162  std::cout << "Number of assignment changes=" << Nchanges
1163  << std::endl;
1164  MDChanges.setValue(MDL_CL2D_CHANGES, (int)Nchanges, idMdChanges);
1165  MDChanges.write(formatString("info@%s",fnClasses.c_str()),MD_APPEND);
1166  }
1167 
1168  // Check if there are empty nodes
1169  if (Q > 1)
1170  {
1171  bool smallNodes;
1172  do
1173  {
1174  smallNodes = false;
1175  int largestNode = -1, sizeLargestNode = -1, smallNode = -1;
1176  size_t sizeSmallestNode = Nimgs + 1;
1177  for (size_t q = 0; q < Q; q++)
1178  {
1179  if (P[q]->currentListImg.size() < sizeSmallestNode)
1180  {
1181  smallNode = q;
1182  sizeSmallestNode = P[q]->currentListImg.size();
1183  }
1184  if ((int) (P[q]->currentListImg.size()) > sizeLargestNode)
1185  {
1186  sizeLargestNode = P[q]->currentListImg.size();
1187  largestNode = q;
1188  }
1189  }
1190  if (sizeLargestNode==0)
1191  REPORT_ERROR(ERR_UNCLASSIFIED,"All classes are of size 0: normally this happens when images are too noisy");
1192  if (largestNode == -1 || smallNode == -1)
1193  break;
1194  if (sizeSmallestNode < prm->PminSize * Nimgs / Q * 0.01 && sizeSmallestNode<0.25*sizeLargestNode)
1195  {
1196  if (prm->node->rank == 1 && prm->verbose)
1197  std::cout << "Splitting node " << largestNode << " (size=" << sizeLargestNode << ") "
1198  << " by overwriting " << smallNode << " (size=" << sizeSmallestNode << ")" << std::endl;
1199  smallNodes = true;
1200 
1201  // Clear the old assignment of the images in the small node
1202  std::vector<CL2DAssignment> &currentListImgSmall =
1203  P[smallNode]->currentListImg;
1204  size_t iimax = currentListImgSmall.size();
1205  for (size_t ii = 0; ii < iimax; ii++)
1206  SF->setValue(MDL_REF, -1, currentListImgSmall[ii].objId);
1207  delete P[smallNode];
1208 
1209  // Clear the old assignment of the images in the large node
1210  std::vector<CL2DAssignment> &currentListImgLargest =
1211  P[largestNode]->currentListImg;
1212  iimax = currentListImgLargest.size();
1213  for (size_t ii = 0; ii < iimax; ii++)
1214  SF->setValue(MDL_REF, -1,
1215  currentListImgLargest[ii].objId);
1216 
1217  // Now split the largest node
1218  auto *node1 = new CL2DClass();
1219  auto *node2 = new CL2DClass();
1220  std::vector<size_t> splitAssignment;
1221  splitNode(P[largestNode], node1, node2, splitAssignment);
1222  delete P[largestNode];
1223 
1224  // Keep the results of the split
1225  P[largestNode] = node1;
1226  P[smallNode] = node2;
1227  iimax = splitAssignment.size();
1228  for (size_t ii = 0; ii < iimax; ii += 2)
1229  {
1230  if (splitAssignment[ii + 1] == 1)
1231  SF->setValue(MDL_REF, largestNode + 1,
1232  splitAssignment[ii]);
1233  else
1234  SF->setValue(MDL_REF, smallNode + 1,
1235  splitAssignment[ii]);
1236  }
1237  }
1238  }
1239  while (smallNodes);
1240  }
1241 
1242  if (prm->node->rank == 1)
1243  write(fnODir,fnOut,level);
1244 
1245  if ((iter > 1 && Nchanges < 0.005 * Nimgs && Q > 1) || iter >= prm->Niter)
1246  goOn = false;
1247  iter++;
1248  }
1249 
1250  std::sort(P.begin(), P.end(), SDescendingClusterSort());
1251 }
size_t size
Definition: xmipp_mpi.h:52
Just to locate unclassified errors.
Definition: xmipp_error.h:192
void init_progress_bar(long total)
void min(Image< double > &op1, const Image< double > &op2)
int Nneighbours
Number of neighbours.
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
int Niter
Number of iterations.
doublereal * c
void write(const FileName &fnODir, const FileName &fnRoot, int level) const
Write the nodes.
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
const FileName & name() const
size_t Nimgs
Number of images.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
void splitNode(CL2DClass *node, CL2DClass *&node1, CL2DClass *&node2, std::vector< size_t > &finalAssignment) const
glob_prnt iter
virtual IdIteratorProxy< false > ids()
void barrierWait()
Definition: xmipp_mpi.cpp:171
void shareAssignments(bool shareAssignment, bool shareUpdates, bool shareNonCorr)
Share assignments.
void fillConstant(MDLabel label, const String &value) override
std::vector< size_t > objId
MpiNode * node
bool setValue(const MDObject &mdValueIn, size_t id)
void getColumnValues(const MDLabel label, std::vector< MDObject > &valuesOut) const override
size_t addObject() override
MetaDataDb * SF
Pointer to input metadata.
void lookNode(MultidimArray< double > &I, int oldnode, int &newnode, CL2DAssignment &bestAssignment)
void progress_bar(long rlen)
Number of changes between iterations.
int makePath(mode_t mode=0755) const
int verbose
Verbosity level.
double dummy
Average cross-correlation for the image (double)
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
size_t rank
Definition: xmipp_mpi.h:52
Class to which the image belongs (int)
void readImage(Image< double > &I, size_t objId, bool applyGeo) const
Read Image.
bool setValue(const MDObject &mdValueIn, size_t id) override
Definition: metadata_db.cpp:90
std::string String
Definition: xmipp_strings.h:34
String formatString(const char *format,...)
#define LOG(msg)
constexpr int K
ProgClassifyCL2D * prm
std::vector< CL2DClass * > P
List of nodes.
Current iteration number (int)
int * n

◆ shareAssignments()

void CL2D::shareAssignments ( bool  shareAssignment,
bool  shareUpdates,
bool  shareNonCorr 
)

Share assignments.

Definition at line 536 of file mpi_classify_CL2D.cpp.

538 {
539  if (shareAssignment)
540  {
541  // Put assignment in common
542  std::vector<int> nodeRef;
543  if (SF->containsLabel(MDL_REF))
544  SF->getColumnValues(MDL_REF, nodeRef);
545  else
546  nodeRef.resize(SF->size(), -1);
547 
548  MPI_Allreduce(MPI_IN_PLACE, &(nodeRef[0]), nodeRef.size(), MPI_INT,
549  MPI_MAX, MPI_COMM_WORLD);
550  SF->setColumnValues(MDL_REF, nodeRef);
551 #ifdef DEBUG_WITH_LOG
552  FileName fnImg;
553  for (size_t objId : SF->id())
554  {
555  int classRef;
556  SF->getValue(MDL_IMAGE,fnImg,objId);
557  SF->getValue(MDL_REF,classRef,objId);
558  LOG(formatString("Image %s: class: %d",fnImg.c_str(),classRef).c_str());
559  }
560 #endif
561  }
562 
563  // Share code updates
564  if (shareUpdates)
565  {
566  std::vector<CL2DAssignment> auxList;
567  std::vector<double> auxList2;
568  int Q = P.size();
569  for (int q = 0; q < Q; q++)
570  {
571  MPI_Allreduce(MPI_IN_PLACE, MULTIDIM_ARRAY(P[q]->Pupdate),
572  MULTIDIM_SIZE(P[q]->Pupdate), MPI_DOUBLE, MPI_SUM,
573  MPI_COMM_WORLD);
574 
575  // Share nextClassCorr and nextNonClassCorr
576  std::vector<double> receivedNonClassCorr;
577  std::vector<CL2DAssignment> receivedNextListImage;
578  int listSize;
579  for (size_t rank = 0; rank < prm->node->size; rank++)
580  {
581  if (rank == prm->node->rank)
582  {
583  listSize = P[q]->nextListImg.size();
584  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
585  MPI_Bcast(&(P[q]->nextListImg[0]),
586  P[q]->nextListImg.size() * sizeof(CL2DAssignment),
587  MPI_CHAR, rank, MPI_COMM_WORLD);
588  if (shareNonCorr)
589  {
590  listSize = P[q]->nextNonClassCorr.size();
591  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
592  MPI_Bcast(&(P[q]->nextNonClassCorr[0]),
593  P[q]->nextNonClassCorr.size(), MPI_DOUBLE,
594  rank, MPI_COMM_WORLD);
595  }
596  }
597  else
598  {
599  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
600  auxList.resize(listSize);
601  MPI_Bcast(&(auxList[0]), listSize * sizeof(CL2DAssignment),
602  MPI_CHAR, rank, MPI_COMM_WORLD);
603  receivedNextListImage.reserve(
604  receivedNextListImage.size() + listSize);
605  for (int j = 0; j < listSize; j++)
606  receivedNextListImage.push_back(auxList[j]);
607  if (shareNonCorr)
608  {
609  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
610  auxList2.resize(listSize);
611  MPI_Bcast(&(auxList2[0]), listSize, MPI_DOUBLE, rank,
612  MPI_COMM_WORLD);
613  receivedNonClassCorr.reserve(
614  receivedNonClassCorr.size() + listSize);
615  for (int j = 0; j < listSize; j++)
616  receivedNonClassCorr.push_back(auxList2[j]);
617  }
618  }
619  }
620  // This is important to ensure that all nodes have all images in the same order
621  std::sort(receivedNextListImage.begin(),receivedNextListImage.end(),CL2DAssignmentComparator);
622 
623  // Copy the received elements
624  listSize = receivedNextListImage.size();
625  P[q]->nextListImg.reserve(P[q]->nextListImg.size() + listSize);
626  for (int j = 0; j < listSize; j++)
627  P[q]->nextListImg.push_back(receivedNextListImage[j]);
628  listSize = receivedNonClassCorr.size();
629  P[q]->nextNonClassCorr.reserve(
630  P[q]->nextNonClassCorr.size() + listSize);
631  for (int j = 0; j < listSize; j++)
632  P[q]->nextNonClassCorr.push_back(receivedNonClassCorr[j]);
633  }
634 
635  transferUpdates();
636  }
637 }
size_t size
Definition: xmipp_mpi.h:52
bool CL2DAssignmentComparator(const CL2DAssignment &d1, const CL2DAssignment &d2)
#define MULTIDIM_SIZE(v)
bool getValue(MDObject &mdValueOut, size_t id) const override
#define MULTIDIM_ARRAY(v)
void getColumnValues(const MDLabel label, std::vector< MDObject > &valuesOut) const override
MetaDataDb * SF
Pointer to input metadata.
void transferUpdates()
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
size_t size() const override
void setColumnValues(const std::vector< MDObject > &valuesIn) override
#define j
size_t rank
Definition: xmipp_mpi.h:52
Class to which the image belongs (int)
String formatString(const char *format,...)
#define LOG(msg)
ProgClassifyCL2D * prm
std::vector< CL2DClass * > P
List of nodes.
Name of an image (std::string)
bool containsLabel(const MDLabel label) const override
Definition: metadata_db.h:305

◆ shareSplitAssignments()

void CL2D::shareSplitAssignments ( Matrix1D< int > &  assignment,
CL2DClass node1,
CL2DClass node2 
) const

Share split assignment.

Definition at line 639 of file mpi_classify_CL2D.cpp.

641 {
642  // Share assignment
643  int imax = VEC_XSIZE(assignment);
644  MPI_Allreduce(MPI_IN_PLACE, MATRIX1D_ARRAY(assignment), imax, MPI_INT,
645  MPI_MAX, MPI_COMM_WORLD);
646 
647  // Share code updates
648  std::vector<CL2DAssignment> auxList;
649  std::vector<double> auxList2;
650  CL2DClass *node = NULL;
651  for (int q = 0; q < 2; q++)
652  {
653  if (q == 0)
654  node = node1;
655  else
656  node = node2;
657  MPI_Allreduce(MPI_IN_PLACE, MULTIDIM_ARRAY(node->Pupdate),
658  MULTIDIM_SIZE(node->Pupdate), MPI_DOUBLE, MPI_SUM,
659  MPI_COMM_WORLD);
660 
661  // Share nextClassCorr and nextNonClassCorr
662  std::vector<double> receivedNonClassCorr;
663  std::vector<CL2DAssignment> receivedNextListImage;
664  int listSize;
665  for (size_t rank = 0; rank < prm->node->size; rank++)
666  {
667  if (rank == prm->node->rank)
668  {
669  // Transmit node 1 next list of images
670  listSize = node->nextListImg.size();
671  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
672  MPI_Bcast(&(node->nextListImg[0]),
673  node->nextListImg.size() * sizeof(CL2DAssignment),
674  MPI_CHAR, rank, MPI_COMM_WORLD);
675  // Transmit node 1 non class corr
676  listSize = node->nextNonClassCorr.size();
677  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
678  MPI_Bcast(&(node->nextNonClassCorr[0]),
679  node->nextNonClassCorr.size(), MPI_DOUBLE, rank,
680  MPI_COMM_WORLD);
681  }
682  else
683  {
684  // Receive node 1 next list of images
685  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
686  auxList.resize(listSize);
687  MPI_Bcast(&(auxList[0]), listSize * sizeof(CL2DAssignment),
688  MPI_CHAR, rank, MPI_COMM_WORLD);
689  receivedNextListImage.reserve(
690  receivedNextListImage.size() + listSize);
691  for (int j = 0; j < listSize; j++)
692  receivedNextListImage.push_back(auxList[j]);
693  // Receive node 1 non class corr
694  MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
695  auxList2.resize(listSize);
696  MPI_Bcast(&(auxList2[0]), listSize, MPI_DOUBLE, rank,
697  MPI_COMM_WORLD);
698  receivedNonClassCorr.reserve(
699  receivedNonClassCorr.size() + listSize);
700  for (int j = 0; j < listSize; j++)
701  receivedNonClassCorr.push_back(auxList2[j]);
702  }
703  }
704  // This is important to ensure that all nodes have all images in the same order
705  std::sort(receivedNextListImage.begin(),receivedNextListImage.end(),CL2DAssignmentComparator);
706 
707  // Copy the received elements
708  listSize = receivedNextListImage.size();
709  node->nextListImg.reserve(node->nextListImg.size() + listSize);
710  for (int j = 0; j < listSize; j++)
711  node->nextListImg.push_back(receivedNextListImage[j]);
712  listSize = receivedNonClassCorr.size();
713  node->nextNonClassCorr.reserve(node->nextNonClassCorr.size() + listSize);
714  for (int j = 0; j < listSize; j++)
715  node->nextNonClassCorr.push_back(receivedNonClassCorr[j]);
716  }
717 
718  node1->transferUpdate();
719  node2->transferUpdate();
720 }
size_t size
Definition: xmipp_mpi.h:52
std::vector< CL2DAssignment > nextListImg
bool CL2DAssignmentComparator(const CL2DAssignment &d1, const CL2DAssignment &d2)
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
#define MULTIDIM_SIZE(v)
#define MULTIDIM_ARRAY(v)
MultidimArray< double > Pupdate
MpiNode * node
std::vector< double > nextNonClassCorr
void transferUpdate(bool centerReference=true)
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
#define j
size_t rank
Definition: xmipp_mpi.h:52
#define MATRIX1D_ARRAY(v)
Definition: matrix1d.h:58
ProgClassifyCL2D * prm

◆ splitFirstNode()

void CL2D::splitFirstNode ( )

Split the widest node

Definition at line 1633 of file mpi_classify_CL2D.cpp.

1634 {
1635  std::sort(P.begin(), P.end(), SDescendingClusterSort());
1636  int Q = P.size();
1637  P.push_back(new CL2DClass());
1638  P.push_back(new CL2DClass());
1639  std::vector<size_t> splitAssignment;
1640  splitNode(P[0], P[Q], P[Q + 1], splitAssignment);
1641  delete P[0];
1642  P[0] = NULL;
1643  P.erase(P.begin());
1644 }
void splitNode(CL2DClass *node, CL2DClass *&node1, CL2DClass *&node2, std::vector< size_t > &finalAssignment) const
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
std::vector< CL2DClass * > P
List of nodes.

◆ splitNode()

void CL2D::splitNode ( CL2DClass node,
CL2DClass *&  node1,
CL2DClass *&  node2,
std::vector< size_t > &  finalAssignment 
) const

Split node

Definition at line 1272 of file mpi_classify_CL2D.cpp.

1274 {
1275  const CL2DClass* firstNode=node;
1276  std::vector<CL2DClass *> toDelete;
1277  Matrix1D<int> newAssignment, oldAssignment, firstSplitAssignment;
1278  Image<double> I;
1279  MultidimArray<double> Iaux1, Iaux2, corrList;
1280  MultidimArray<int> idx;
1281  CL2DAssignment assignment, assignment1, assignment2;
1282  CL2DClass *firstSplitNode1 = NULL;
1283  CL2DClass *firstSplitNode2 = NULL;
1284  size_t minAllowedSize = 0;
1285 
1286  bool oldclassicalMultiref = prm->classicalMultiref;
1287  prm->classicalMultiref = false;
1288  bool finish;
1289  bool success = true;
1290  int splitTrials=0;
1291  do
1292  {
1293  minAllowedSize = (size_t)(prm->PminSize/2 * 0.01 * node->currentListImg.size());
1294 
1295  // Sort the currentListImg to make sure that all nodes have the same order
1297 #ifdef DEBUG
1298  std::cout << "Splitting node " << node << "(" << node->currentListImg.size() << ") into " << node1 << " and " << node2 << std::endl;
1299  Image<double> save;
1300  save()=node->P;
1301  save.write("PPPnodeToSplit.xmp");
1302 #endif
1303  finish = true;
1304  node2->neighboursIdx = node1->neighboursIdx = node->neighboursIdx;
1305  node2->P = node1->P = node->P;
1306 
1307  size_t imax = node->currentListImg.size();
1308  if (imax < minAllowedSize)
1309  {
1310  toDelete.push_back(node1);
1311  toDelete.push_back(node2);
1312 #ifdef DEBUG
1313  std::cout << "Pushing to delete " << node1 << std::endl;
1314  std::cout << "Pushing to delete " << node2 << std::endl;
1315 #endif
1316  success = false;
1317  break;
1318  }
1319 
1320  // Compute the corr histogram
1321  if (prm->node->rank == 1 && prm->verbose >= 2)
1322  std::cerr << "Calculating corr distribution at split ..."
1323  << std::endl;
1324  corrList.initZeros(imax);
1325  for (size_t i = 0; i < imax; i++)
1326  {
1327  if ((i + 1) % (prm->node->size) == prm->node->rank)
1328  {
1329  readImage(I, node->currentListImg[i].objId, false);
1330  node->fit(I(), assignment);
1331  A1D_ELEM(corrList,i) = assignment.corr;
1332  }
1333  if (prm->node->rank == 1 && i % 25 == 0 && prm->verbose >= 2)
1334  progress_bar(i);
1335  }
1336  if (prm->node->rank == 1 && prm->verbose >= 2)
1337  progress_bar(imax);
1338  MPI_Allreduce(MPI_IN_PLACE, MULTIDIM_ARRAY(corrList), imax, MPI_DOUBLE,
1339  MPI_MAX, MPI_COMM_WORLD);
1340  newAssignment.initZeros(imax);
1341 
1342  // Compute threshold
1343  corrList.indexSort(idx);
1344  double corrThreshold = corrList(idx(XSIZE(idx)/2)-1);
1345 #ifdef DEBUG
1346  corrList.printStats();
1347  std::cout << " corrThreshold= " << corrThreshold << std::endl;
1348 #endif
1349  if (corrThreshold == 0)
1350  {
1351  if (firstSplitNode1 != NULL)
1352  {
1353  toDelete.push_back(node1);
1354  toDelete.push_back(node2);
1355 #ifdef DEBUG
1356  std::cout << "Pushing to delete " << node1 << std::endl;
1357  std::cout << "Pushing to delete " << node2 << std::endl;
1358 #endif
1359  success = false;
1360  break;
1361  }
1362  else
1363  {
1364  // Split at random
1365  for (size_t i = 0; i < imax; i++)
1366  {
1367  assignment.objId = node->currentListImg[i].objId;
1368  readImage(I, assignment.objId, false);
1369  node->fit(I(), assignment);
1370  if ((i + 1) % 2 == 0)
1371  {
1372  node1->updateProjection(I(), assignment,true);
1373  VEC_ELEM(newAssignment,i) = 1;
1374  node2->updateNonProjection(assignment.corr, true);
1375  }
1376  else
1377  {
1378  node2->updateProjection(I(), assignment,true);
1379  VEC_ELEM(newAssignment,i) = 2;
1380  node1->updateNonProjection(assignment.corr, true);
1381  }
1382  }
1383  node1->transferUpdate();
1384  node2->transferUpdate();
1385 #ifdef DEBUG
1386  std::cout << "Splitting at random " << node1->currentListImg.size() << " " << node2->currentListImg.size() << std::endl;
1387  save()=node1->P;
1388  save.write("PPPnode1.xmp");
1389  save()=node2->P;
1390  save.write("PPPnode2.xmp");
1391  std::cout << "Press any key" << std::endl;
1392  char c; std::cin >> c;
1393 #endif
1394  success = true;
1395  break;
1396  }
1397  }
1398  else
1399  {
1400  // Split according to corr
1401  if (prm->node->rank == 1 && prm->verbose >= 2)
1402  std::cerr << "Splitting by corr threshold ..." << std::endl;
1403  for (size_t i = 0; i < imax; i++)
1404  {
1405  if ((i + 1) % (prm->node->size) == prm->node->rank)
1406  {
1407  assignment.objId = node->currentListImg[i].objId;
1408  readImage(I, assignment.objId, false);
1409  node->fit(I(), assignment);
1410  if (assignment.corr < corrThreshold)
1411  {
1412  node1->updateProjection(I(), assignment);
1413  VEC_ELEM(newAssignment,i) = 1;
1414  node2->updateNonProjection(assignment.corr);
1415  }
1416  else
1417  {
1418  node2->updateProjection(I(), assignment);
1419  VEC_ELEM(newAssignment,i) = 2;
1420  node1->updateNonProjection(assignment.corr);
1421  }
1422  }
1423  if (prm->node->rank == 1 && i % 25 == 0 && prm->verbose >= 2)
1424  progress_bar(i);
1425  }
1426  if (prm->node->rank == 1 && prm->verbose >= 2)
1427  progress_bar(imax);
1428  shareSplitAssignments(newAssignment, node1, node2);
1429  }
1430 
1431 #ifdef DEBUG
1432  std::cout << "After first split Node1: " << node1->currentListImg.size() << " Node2 " << node2->currentListImg.size() << std::endl;
1433  save()=node1->P;
1434  save.write("PPPnode1.xmp");
1435  save()=node2->P;
1436  save.write("PPPnode2.xmp");
1437  std::cout << "Press any key" << std::endl;
1438  char c; std::cin >> c;
1439 #endif
1440 
1441  // Backup the first split in case it fails
1442  if (firstSplitNode1 == NULL)
1443  {
1444 #ifdef DEBUG
1445  std::cout << "Creating backup\n";
1446 #endif
1447  firstSplitAssignment = newAssignment;
1448  firstSplitNode1 = new CL2DClass(*node1);
1449  firstSplitNode2 = new CL2DClass(*node2);
1450  }
1451 
1452  // Split iterations
1453  for (int it = 0; it < prm->Niter; it++)
1454  {
1455  if (prm->node->rank == 1 && prm->verbose >= 2)
1456  {
1457  init_progress_bar(imax);
1458  }
1459 
1460  oldAssignment = newAssignment;
1461  newAssignment.initZeros();
1462  for (size_t i = 0; i < imax; i++)
1463  {
1464  if ((i + 1) % (prm->node->size) == prm->node->rank)
1465  {
1466  // Read image
1467  assignment1.objId = assignment2.objId = assignment.objId
1468  = node->currentListImg[i].objId;
1469  readImage(I, assignment.objId, false);
1470 
1471  Iaux1 = I();
1472  node1->fit(Iaux1, assignment1);
1473  Iaux2 = I();
1474  node2->fit(Iaux2, assignment2);
1475 
1476  //std::cout << "Image " << i << " Likelihood: " << assignment1.likelihood << " " << assignment2.likelihood << std::endl;
1477  //std::cout << "Image " << i << " Corr: " << assignment1.corr << " " << assignment2.corr << std::endl;
1478  if (assignment1.likelihood > assignment2.likelihood && !prm->classicalSplit)
1479  {
1480  node1->updateProjection(Iaux1, assignment1);
1481  VEC_ELEM(newAssignment,i) = 1;
1482  node2->updateNonProjection(assignment2.corr);
1483  //std::cout << "Assigned to 1" << std::endl;
1484  }
1485  else if (assignment2.likelihood > assignment1.likelihood && !prm->classicalSplit)
1486  {
1487  node2->updateProjection(Iaux2, assignment2);
1488  VEC_ELEM(newAssignment,i) = 2;
1489  node1->updateNonProjection(assignment1.corr);
1490  //std::cout << "Assigned to 2" << std::endl;
1491  }
1492  else if (prm->classifyAllImages || prm->classicalSplit)
1493  {
1494  if (assignment1.corr > assignment2.corr)
1495  {
1496  node1->updateProjection(Iaux1, assignment1);
1497  VEC_ELEM(newAssignment,i) = 1;
1498  node2->updateNonProjection(assignment2.corr);
1499  //std::cout << "Assigned to 1" << std::endl;
1500  }
1501  else if (assignment2.corr > assignment1.corr)
1502  {
1503  node2->updateProjection(Iaux2, assignment2);
1504  VEC_ELEM(newAssignment,i) = 2;
1505  node1->updateNonProjection(assignment1.corr);
1506  //std::cout << "Assigned to 2" << std::endl;
1507  }
1508  }
1509  }
1510  if (prm->node->rank == 1 && i % 25 == 0 && prm->verbose >= 2)
1511  progress_bar(i);
1512  }
1513  if (prm->node->rank == 1 && prm->verbose >= 2)
1514  progress_bar(imax);
1515  shareSplitAssignments(newAssignment, node1, node2);
1516 
1517 #ifdef DEBUG
1518  std::cout << "After refinement iteration: " << it << " Node1: " << node1->currentListImg.size() << " Node2 " << node2->currentListImg.size() << std::endl;
1519  save()=node1->P;
1520  save.write("PPPnode1.xmp");
1521  save()=node2->P;
1522  save.write("PPPnode2.xmp");
1523  std::cout << "Press any key" << std::endl;
1524  std::cin >> c;
1525 #endif
1526 
1527  int Nchanges = 0;
1528  FOR_ALL_ELEMENTS_IN_MATRIX1D(newAssignment)
1529  if (newAssignment(i) != oldAssignment(i))
1530  Nchanges++;
1531  if (prm->node->rank == 1 && prm->verbose >= 2)
1532  std::cout << "Number of assignment split changes=" << Nchanges
1533  << std::endl;
1534 
1535  // Check if one of the nodes is too small
1536  if (node1->currentListImg.size() < minAllowedSize
1537  || node2->currentListImg.size() < minAllowedSize
1538  || Nchanges < 0.005 * imax)
1539  break;
1540  }
1541 
1542  if (node1->currentListImg.size() < minAllowedSize && node2->currentListImg.size() < minAllowedSize)
1543  {
1544  if (prm->node->rank == 1 && prm->verbose >= 2)
1545  std::cout << "Removing both nodes, they are too small. Current size: "
1546  << node1->currentListImg.size() << " Minimum allowed: "
1547  << minAllowedSize << "...\n";
1548  if (node1 != node)
1549  delete node1;
1550  if (node2 != node)
1551  delete node2;
1552  success = false;
1553  finish = true;
1554  }
1555  else if (node1->currentListImg.size() < minAllowedSize)
1556  {
1557  if (prm->node->rank == 1 && prm->verbose >= 2)
1558  std::cout << "Removing node1, it's too small "
1559  << node1->currentListImg.size() << " "
1560  << minAllowedSize << "...\n";
1561  if (node1 != node)
1562  delete node1;
1563  node1 = new CL2DClass();
1564  toDelete.push_back(node2);
1565 #ifdef DEBUG
1566  std::cout << "Pushing to delete " << node2 << std::endl;
1567 #endif
1568  node = node2;
1569  node2 = new CL2DClass();
1570  finish = false;
1571  }
1572  else if (node2->currentListImg.size() < minAllowedSize)
1573  {
1574  if (prm->node->rank == 1 && prm->verbose >= 2)
1575  std::cout << "Removing node2, it's too small "
1576  << node2->currentListImg.size() << " "
1577  << minAllowedSize << "...\n";
1578  if (node2 != node)
1579  delete node2;
1580  node2 = new CL2DClass();
1581  toDelete.push_back(node1);
1582 #ifdef DEBUG
1583  std::cout << "Pushing to delete " << node1 << std::endl;
1584 #endif
1585  node = node1;
1586  node1 = new CL2DClass();
1587  finish = false;
1588  }
1589  splitTrials++;
1590  if (splitTrials>=prm->NSplitTrials)
1591  {
1592  success = false;
1593  finish = true;
1594  }
1595  }
1596  while (!finish);
1597  for (size_t i = 0; i < toDelete.size(); i++)
1598  if (toDelete[i] != firstNode)
1599  {
1600 #ifdef DEBUG
1601  std::cout << "deleting from list " << toDelete[i] << std::endl;
1602 #endif
1603  delete toDelete[i];
1604  }
1605 
1606  if (success)
1607  {
1608  for (size_t i = 0; i < node1->currentListImg.size(); i++)
1609  {
1610  splitAssignment.push_back(node1->currentListImg[i].objId);
1611  splitAssignment.push_back(1);
1612  }
1613  for (size_t i = 0; i < node2->currentListImg.size(); i++)
1614  {
1615  splitAssignment.push_back(node2->currentListImg[i].objId);
1616  splitAssignment.push_back(2);
1617  }
1618  delete firstSplitNode1;
1619  delete firstSplitNode2;
1620  }
1621  else
1622  {
1623  node1 = firstSplitNode1;
1624  node2 = firstSplitNode2;
1625  splitAssignment.reserve(VEC_XSIZE(firstSplitAssignment));
1626  FOR_ALL_ELEMENTS_IN_MATRIX1D(firstSplitAssignment)
1627  splitAssignment.push_back(VEC_ELEM(firstSplitAssignment,i));
1628  }
1629  prm->classicalMultiref = oldclassicalMultiref;
1630 }
size_t size
Definition: xmipp_mpi.h:52
void init_progress_bar(long total)
MultidimArray< double > P
bool CL2DAssignmentComparator(const CL2DAssignment &d1, const CL2DAssignment &d2)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
void updateProjection(const MultidimArray< double > &I, const CL2DAssignment &assigned, bool force=false)
int Niter
Number of iterations.
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
doublereal * c
int NSplitTrials
MaxTrials to split.
double PminSize
Minimum size of a node.
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define A1D_ELEM(v, i)
#define MULTIDIM_ARRAY(v)
bool classicalMultiref
Classical Multiref.
bool classifyAllImages
Clasify all images.
#define i
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
void fit(MultidimArray< double > &I, CL2DAssignment &result)
MpiNode * node
void shareSplitAssignments(Matrix1D< int > &assignment, CL2DClass *node1, CL2DClass *node2) const
Share split assignment.
#define XSIZE(v)
void progress_bar(long rlen)
void updateNonProjection(double corr, bool force=false)
int verbose
Verbosity level.
void transferUpdate(bool centerReference=true)
void initZeros()
Definition: matrix1d.h:592
void printStats(std::ostream &out=std::cout) const
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
size_t rank
Definition: xmipp_mpi.h:52
void readImage(Image< double > &I, size_t objId, bool applyGeo) const
Read Image.
std::vector< CL2DAssignment > currentListImg
bool classicalSplit
Use ClassicalCriterion at split.
ProgClassifyCL2D * prm
void initZeros(const MultidimArray< T1 > &op)
std::vector< int > neighboursIdx
void indexSort(MultidimArray< int > &indx) const

◆ transferUpdates()

void CL2D::transferUpdates ( )

Transfer all updates

Definition at line 1030 of file mpi_classify_CL2D.cpp.

1031 {
1032  int Q = P.size();
1033  for (int q = 0; q < Q; q++)
1034  P[q]->transferUpdate();
1035 }
std::vector< CL2DClass * > P
List of nodes.

◆ write()

void CL2D::write ( const FileName fnODir,
const FileName fnRoot,
int  level 
) const

Write the nodes.

Definition at line 898 of file mpi_classify_CL2D.cpp.

899 {
900  int Q = P.size();
901  MetaDataVec SFout;
902  Image<double> I;
903  FileName fnResultsDir=formatString("%s/level_%02d",fnODir.c_str(),level);
904  FileName fnOut = formatString("%s/%s_classes.stk",fnResultsDir.c_str(),fnRoot.c_str()), fnClass;
905  fnOut.deleteFile();
906  for (int q = 0; q < Q; q++)
907  {
908  fnClass.compose(q + 1, fnOut);
909  I() = P[q]->P;
910  I.write(fnClass, q, true, WRITE_APPEND);
911  size_t id = SFout.addObject();
912  SFout.setValue(MDL_REF, q + 1, id);
913  SFout.setValue(MDL_IMAGE, fnClass, id);
914  SFout.setValue(MDL_CLASS_COUNT,P[q]->currentListImg.size(), id);
915  }
916  FileName fnSFout = formatString("%s/%s_classes.xmd",fnResultsDir.c_str(),fnRoot.c_str());
917  SFout.write("classes@"+fnSFout, MD_APPEND);
918 
919  // Make the selfiles of each class
920  FileName fnImg;
921 
922  for (int q = 0; q < Q; q++)
923  {
924  MetaDataVec SFq;
925  std::vector<CL2DAssignment> &currentListImg = P[q]->currentListImg;
926  int imax = currentListImg.size();
927  for (int i = 0; i < imax; i++)
928  {
929  const CL2DAssignment &assignment = currentListImg[i];
930  MDRowSql row = SF->getRowSql(assignment.objId);
931  row.setValue(MDL_FLIP, assignment.flip);
932  row.setValue(MDL_SHIFT_X, assignment.shiftx);
933  row.setValue(MDL_SHIFT_Y, assignment.shifty);
934  row.setValue(MDL_ANGLE_PSI, assignment.psi);
935  SFq.addRow(row);
936  }
937  MetaDataVec SFq_sorted;
938  SFq_sorted.sort(SFq, MDL_IMAGE);
939  SFq_sorted.write(formatString("class%06d_images@%s",q+1,fnSFout.c_str()),MD_APPEND);
940  }
941 }
void sort(const MetaDataVec &MDin, const MDLabel sortLabel, bool asc=true, int limit=-1, int offset=0)
Shift for the image in the X axis (double)
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
Special label to be used when gathering MDs in MpiMetadataPrograms.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
#define i
size_t addRow(const MDRow &row) override
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
MetaDataDb * SF
Pointer to input metadata.
void setValue(const MDObject &object) override
FileName fnOut
Flip the image? (bool)
Class to which the image belongs (int)
Number of images assigned to the same class as this image.
String formatString(const char *format,...)
Shift for the image in the Y axis (double)
std::vector< CL2DClass * > P
List of nodes.
MDRowSql getRowSql(size_t id)
Name of an image (std::string)

Member Data Documentation

◆ Nimgs

size_t CL2D::Nimgs =0

Number of images.

Definition at line 163 of file mpi_classify_CL2D.h.

◆ P

std::vector<CL2DClass *> CL2D::P

List of nodes.

Definition at line 169 of file mpi_classify_CL2D.h.

◆ SF

MetaDataDb* CL2D::SF =nullptr

Pointer to input metadata.

Definition at line 166 of file mpi_classify_CL2D.h.


The documentation for this class was generated from the following files: