40 #define CREATE_LOG() _logCL2D = fopen(formatString("nodo%02d.log", node->rank).c_str(), "w+") 41 #define LOG(msg) do{fprintf(_logCL2D, "%s\t%s\n", getCurrentTimeString(), msg); fflush(_logCL2D); }while(0) 42 #define CLOSE_LOG() fclose(_logCL2D) 44 #define CREATE_LOG() ; 52 out <<
"(" << assigned.
objId <<
", " << assigned.
corr <<
")";
105 nextListImg.push_back(assignment);
128 nextListImg.push_back(assigned);
135 if (nextListImg.size() > 0)
138 double iNq = 1.0 / nextListImg.size();
141 Pupdate.statisticsAdjust(0., 1.);
146 Pupdate.initZeros(P);
157 XSIZE(P) / 2-2, plans, 1);
158 size_t finalSize = 2 * polarFourierP.getSampleNoOuterRing() - 1;
159 if (
XSIZE(rotationalCorr) != finalSize)
160 rotationalCorr.resize(finalSize);
161 rotAux.local_transformer.setReal(rotationalCorr);
164 currentListImg = nextListImg;
179 nextNonClassCorr.clear();
181 double minC=0., maxC=0.;
183 double minN=0., maxN=0.;
191 histClass /= histClass.sum();
192 histNonClass /= histNonClass.sum();
196 histClass.write(
"PPPclass.txt");
197 histNonClass.write(
"PPPnonClass.txt");
198 std::cout <<
"Histograms have been written. Press any key\n";
206 currentListImg.clear();
236 corrAux.transformer1.FourierTransform(P, corrAux.FFT1,
false);
240 save2.
write(
"PPPI1.xmp");
249 for (
int i = 0;
i < 3;
i++)
255 bestShift(P, corrAux.FFT1, IauxSR, shiftXSR, shiftYSR, corrAux);
264 save2.
write(
"PPPIauxSR_afterShift.xmp");
265 std::cout <<
"ASR\n" << ASR << std::endl;
274 bestRotSR =
best_rotation(polarFourierP, polarFourierI, rotAux);
283 save2.
write(
"PPPIauxSR_afterShiftAndRotation.xmp");
284 std::cout <<
"ASR\n" << ASR << std::endl;
293 bestRotRS =
best_rotation(polarFourierP, polarFourierI, rotAux);
302 save2.
write(
"PPPIauxRS_afterRotation.xmp");
303 std::cout <<
"ARS\n" << ARS << std::endl;
309 bestShift(P, corrAux.FFT1, IauxRS, shiftXRS, shiftYRS, corrAux);
318 save2.
write(
"PPPIauxRS_afterRotationAndShift.xmp");
319 std::cout <<
"ARS\n" << ARS << std::endl;
322 std::cout <<
"Press any key\n";
329 double corrRS=0.0, corrSR=0.0;
357 "this issue, please contact developers.");
370 std::cout <<
"corrRS=" << corrRS << std::endl;
371 std::cout <<
"corrSR=" << corrSR << std::endl;
390 candidateRS.
corr = 0;
392 candidateRS.
corr = corrRS;
395 candidateSR.
corr = 0;
397 candidateSR.
corr = corrSR;
399 if (candidateRS.
corr >= candidateSR.
corr)
404 else if (candidateSR.
corr > candidateRS.
corr)
417 save.
write(
"PPPI1.xmp");
419 save.
write(
"PPPI2.xmp");
421 save.
write(
"PPPdiff.xmp");
422 std::cout <<
"sigma=" << prm->
sigma <<
" corr=" << result.
corr 423 <<
". Press" << std::endl;
433 if (currentListImg.size() == 0)
439 fitBasic(Idirect, resultDirect);
447 fitBasic(Imirror, resultMirror,
true);
450 resultMirror.
corr=-1e38;
452 if (resultMirror.
corr > resultDirect.
corr)
468 histClass.val2index(result.
corr, idx);
471 double likelihoodClass = 0;
472 for (
int i = 0;
i <= idx;
i++)
474 histNonClass.val2index(result.
corr, idx);
477 double likelihoodNonClass = 0;
478 for (
int i = 0;
i <= idx;
i++)
480 result.
likelihood = likelihoodClass * likelihoodNonClass;
488 int Q = listP.size();
489 neighboursIdx.clear();
493 for (
int q = 0; q < Q; q++)
494 neighboursIdx.push_back(q);
502 for (
int q = 0; q < Q; q++)
504 if (listP[q] ==
this)
516 for (
int k = 0;
k <
K;
k++)
517 neighboursIdx.push_back(idx(Q -
k - 1) - 1);
522 save.
write(
"PPPthis.xmp");
523 for (
int k=0;
k<
K;
k++)
525 save()=listP[neighboursIdx[
k]]->P;
528 std::cout <<
"Neighbours saved. Press any key\n";
542 std::vector<int> nodeRef;
543 if (SF->containsLabel(
MDL_REF))
544 SF->getColumnValues(
MDL_REF, nodeRef);
546 nodeRef.resize(SF->size(), -1);
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 553 for (
size_t objId : SF->id())
558 LOG(
formatString(
"Image %s: class: %d",fnImg.c_str(),classRef).c_str());
566 std::vector<CL2DAssignment> auxList;
567 std::vector<double> auxList2;
569 for (
int q = 0; q < Q; q++)
576 std::vector<double> receivedNonClassCorr;
577 std::vector<CL2DAssignment> receivedNextListImage;
579 for (
size_t rank = 0; rank < prm->
node->
size; rank++)
583 listSize = P[q]->nextListImg.size();
584 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
585 MPI_Bcast(&(P[q]->nextListImg[0]),
587 MPI_CHAR, rank, MPI_COMM_WORLD);
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);
599 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
600 auxList.resize(listSize);
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]);
609 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
610 auxList2.resize(listSize);
611 MPI_Bcast(&(auxList2[0]), listSize, MPI_DOUBLE, rank,
613 receivedNonClassCorr.reserve(
614 receivedNonClassCorr.size() + listSize);
615 for (
int j = 0; j < listSize; j++)
616 receivedNonClassCorr.push_back(auxList2[j]);
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]);
644 MPI_Allreduce(MPI_IN_PLACE,
MATRIX1D_ARRAY(assignment), imax, MPI_INT,
645 MPI_MAX, MPI_COMM_WORLD);
648 std::vector<CL2DAssignment> auxList;
649 std::vector<double> auxList2;
651 for (
int q = 0; q < 2; q++)
662 std::vector<double> receivedNonClassCorr;
663 std::vector<CL2DAssignment> receivedNextListImage;
665 for (
size_t rank = 0; rank < prm->
node->
size; rank++)
671 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
674 MPI_CHAR, rank, MPI_COMM_WORLD);
677 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
685 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
686 auxList.resize(listSize);
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]);
694 MPI_Bcast(&listSize, 1, MPI_INT, rank, MPI_COMM_WORLD);
695 auxList2.resize(listSize);
696 MPI_Bcast(&(auxList2[0]), listSize, MPI_DOUBLE, rank,
698 receivedNonClassCorr.reserve(
699 receivedNonClassCorr.size() + listSize);
700 for (
int j = 0; j < listSize; j++)
701 receivedNonClassCorr.push_back(auxList2[j]);
708 listSize = receivedNextListImage.size();
710 for (
int j = 0;
j < listSize;
j++)
712 listSize = receivedNonClassCorr.size();
714 for (
int j = 0; j < listSize; j++)
726 for (
int q=0; q<qmax; q++)
741 I().setXmippOrigin();
743 I().statisticsAdjust(0., 1.);
752 std::cout <<
"Initializing ...\n";
760 bool initialCodesGiven = _codes0.size() > 0;
761 for (
int q = 0; q < prm->
Ncodes0; q++)
764 if (initialCodesGiven)
766 P[q]->Pupdate = _codes0[q];
767 P[q]->nextListImg.push_back(assignment);
768 P[q]->transferUpdate(
false);
783 SF->fillConstant(
MDL_REF,
"-1");
784 for (
size_t _ : prm->
SF.
ids())
789 if (!initialCodesGiven)
792 readImage(I, objId,
true);
796 I().computeAvgStdev_within_binary_mask(prm->
mask, avg, stddev);
797 prm->
sigma += stddev;
801 if (!initialCodesGiven)
803 bestAssignment.
corr = 1;
804 P[q]->updateProjection(I(), bestAssignment);
808 bestAssignment.
corr = 0;
810 for (
int qp = 0; qp < prm->
Ncodes0; qp++)
813 P[qp]->fit(Iaux, assignment);
814 if (assignment.
corr > bestAssignment.
corr)
816 bestAssignment = assignment;
822 P[q]->updateProjection(Ibest, bestAssignment);
824 SF->setValue(
MDL_REF, q + 1, objId);
825 if (idx % 100 == 0 && prm->
node->
rank == 1)
836 MPI_Allreduce(MPI_IN_PLACE, &(prm->
sigma), 1, MPI_DOUBLE, MPI_SUM,
841 shareAssignments(
true,
true,
false);
848 std::cout <<
"Computing histogram of correlation values\n";
854 for (
size_t _ : prm->
SF.
ids())
859 readImage(I, objId,
false);
862 SF->getValue(
MDL_REF, q, objId);
871 P[q]->fit(Iaux, inClass);
872 P[q]->updateProjection(Iaux, inClass);
874 for (
int qp = 0; qp < prm->
Ncodes0; qp++)
879 P[qp]->fit(Iaux, outClass);
880 P[qp]->updateNonProjection(outClass.
corr);
883 if (prm->
node->
rank == 1 && idx % 100 == 0)
892 shareAssignments(
false,
true,
true);
906 for (
int q = 0; q < Q; q++)
908 fnClass.compose(q + 1, fnOut);
922 for (
int q = 0; q < Q; q++)
925 std::vector<CL2DAssignment> ¤tListImg = P[q]->currentListImg;
926 int imax = currentListImg.
size();
927 for (
int i = 0;
i < imax;
i++)
948 std::cout <<
"Looking for node. Oldnode=" << oldnode << std::endl;
958 for (
int q = 0; q < Q; q++)
961 bool proceed =
false;
966 int imax = P[oldnode]->neighboursIdx.size();
967 for (
int i = 0;
i < imax;
i++)
969 if (P[oldnode]->neighboursIdx[
i] == q)
977 double threshold = 3.0 * P[oldnode]->currentListImg.size();
979 threshold = (double) (
XMIPP_MIN(threshold,Nimgs)) / Nimgs;
995 P[q]->fit(Iaux, assignment);
998 std::cout <<
" Proceeding with node " << q <<
" corr=" << assignment.
corr << std::endl;
1005 bestAssignment = assignment;
1017 std::cout <<
" New node=" << newnode << std::endl;
1021 P[newnode]->updateProjection(I, bestAssignment);
1023 for (
int q = 0; q < Q; q++)
1024 if (q != newnode && corrList(q) > 0)
1025 P[q]->updateNonProjection(corrList(q));
1033 for (
int q = 0; q < Q; q++)
1034 P[q]->transferUpdate();
1041 size_t Q = P.size();
1044 std::cout <<
"Quantizing with " << Q <<
" codes...\n";
1047 for (
int q=0; q<Q; q++)
1052 std::cout <<
"Classes written. Press any key" << std::endl;
1053 char c; std::cin >>
c;
1056 std::vector<int> oldAssignment, newAssignment;
1062 int progressStep =
XMIPP_MAX(1,Nimgs/60);
1070 std::cout <<
"Iteration " << iter <<
" ...\n";
1077 for (
size_t q = 0; q < Q; q++)
1078 P[q]->lookForNeighbours(P, K);
1082 SF->getColumnValues(
MDL_REF, oldAssignment);
1083 int *ptrOld = &(oldAssignment[0]);
1084 for (
size_t n = 0;
n < Nimgs; ++
n, ++ptrOld)
1086 SF->fillConstant(
MDL_REF,
"-1");
1088 for (
size_t _ : prm->
SF.
ids())
1093 readImage(I, objId,
false);
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)
1108 MPI_Allreduce(MPI_IN_PLACE, &corrSum, 1, MPI_DOUBLE, MPI_SUM,
1110 shareAssignments(
true,
true,
true);
1113 size_t idMdChanges=0;
1118 double avgSimilarity = corrSum / Nimgs;
1119 if (avgSimilarity==0)
1121 std::cerr <<
"The average correlation is 0.0, make sure that the maximum allowed shift is enough\n";
1126 std::cout <<
"\nAverage correlation with input vectors=" << avgSimilarity << std::endl;
1131 MPI_Bcast(&finish,1, MPI_INT, 1, MPI_COMM_WORLD);
1140 SF->getColumnValues(
MDL_REF, newAssignment);
1141 int *ptrNew = &(newAssignment[0]);
1142 for (
size_t n = 0;
n < Nimgs; ++
n, ++ptrNew)
1144 size_t Nchanges = 0;
1147 int *ptrNew = &(newAssignment[0]);
1148 ptrOld = &(oldAssignment[0]);
1149 for (
size_t n = 0;
n < Nimgs; ++
n, ++ptrNew, ++ptrOld)
1150 if (*ptrNew != *ptrOld)
1162 std::cout <<
"Number of assignment changes=" << Nchanges
1175 int largestNode = -1, sizeLargestNode = -1, smallNode = -1;
1176 size_t sizeSmallestNode = Nimgs + 1;
1177 for (
size_t q = 0; q < Q; q++)
1179 if (P[q]->currentListImg.size() < sizeSmallestNode)
1182 sizeSmallestNode = P[q]->currentListImg.size();
1184 if ((
int) (P[q]->currentListImg.size()) > sizeLargestNode)
1186 sizeLargestNode = P[q]->currentListImg.size();
1190 if (sizeLargestNode==0)
1192 if (largestNode == -1 || smallNode == -1)
1194 if (sizeSmallestNode < prm->PminSize * Nimgs / Q * 0.01 && sizeSmallestNode<0.25*sizeLargestNode)
1197 std::cout <<
"Splitting node " << largestNode <<
" (size=" << sizeLargestNode <<
") " 1198 <<
" by overwriting " << smallNode <<
" (size=" << sizeSmallestNode <<
")" << std::endl;
1202 std::vector<CL2DAssignment> ¤tListImgSmall =
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];
1210 std::vector<CL2DAssignment> ¤tListImgLargest =
1211 P[largestNode]->currentListImg;
1212 iimax = currentListImgLargest.size();
1213 for (
size_t ii = 0; ii < iimax; ii++)
1215 currentListImgLargest[ii].objId);
1220 std::vector<size_t> splitAssignment;
1221 splitNode(P[largestNode], node1, node2, splitAssignment);
1222 delete P[largestNode];
1225 P[largestNode] = node1;
1226 P[smallNode] = node2;
1227 iimax = splitAssignment.size();
1228 for (
size_t ii = 0; ii < iimax; ii += 2)
1230 if (splitAssignment[ii + 1] == 1)
1231 SF->setValue(
MDL_REF, largestNode + 1,
1232 splitAssignment[ii]);
1234 SF->setValue(
MDL_REF, smallNode + 1,
1235 splitAssignment[ii]);
1243 write(fnODir,fnOut,level);
1245 if ((iter > 1 && Nchanges < 0.005 * Nimgs && Q > 1) || iter >= prm->
Niter)
1258 std::vector<CL2DClass *>::iterator ptr = P.begin();
1259 while (ptr != P.end())
1260 if ((*ptr)->currentListImg.size() == 0)
1273 std::vector<size_t> &splitAssignment)
const 1276 std::vector<CL2DClass *> toDelete;
1277 Matrix1D<int> newAssignment, oldAssignment, firstSplitAssignment;
1284 size_t minAllowedSize = 0;
1289 bool success =
true;
1298 std::cout <<
"Splitting node " << node <<
"(" << node->
currentListImg.size() <<
") into " << node1 <<
" and " << node2 << std::endl;
1301 save.
write(
"PPPnodeToSplit.xmp");
1305 node2->
P = node1->
P = node->
P;
1308 if (imax < minAllowedSize)
1310 toDelete.push_back(node1);
1311 toDelete.push_back(node2);
1313 std::cout <<
"Pushing to delete " << node1 << std::endl;
1314 std::cout <<
"Pushing to delete " << node2 << std::endl;
1322 std::cerr <<
"Calculating corr distribution at split ..." 1325 for (
size_t i = 0;
i < imax;
i++)
1330 node->
fit(I(), assignment);
1338 MPI_Allreduce(MPI_IN_PLACE,
MULTIDIM_ARRAY(corrList), imax, MPI_DOUBLE,
1339 MPI_MAX, MPI_COMM_WORLD);
1344 double corrThreshold = corrList(idx(
XSIZE(idx)/2)-1);
1347 std::cout <<
" corrThreshold= " << corrThreshold << std::endl;
1349 if (corrThreshold == 0)
1351 if (firstSplitNode1 != NULL)
1353 toDelete.push_back(node1);
1354 toDelete.push_back(node2);
1356 std::cout <<
"Pushing to delete " << node1 << std::endl;
1357 std::cout <<
"Pushing to delete " << node2 << std::endl;
1365 for (
size_t i = 0;
i < imax;
i++)
1368 readImage(I, assignment.
objId,
false);
1369 node->
fit(I(), assignment);
1370 if ((
i + 1) % 2 == 0)
1388 save.
write(
"PPPnode1.xmp");
1390 save.
write(
"PPPnode2.xmp");
1391 std::cout <<
"Press any key" << std::endl;
1392 char c; std::cin >>
c;
1402 std::cerr <<
"Splitting by corr threshold ..." << std::endl;
1403 for (
size_t i = 0;
i < imax;
i++)
1408 readImage(I, assignment.
objId,
false);
1409 node->
fit(I(), assignment);
1410 if (assignment.
corr < corrThreshold)
1428 shareSplitAssignments(newAssignment, node1, node2);
1434 save.
write(
"PPPnode1.xmp");
1436 save.
write(
"PPPnode2.xmp");
1437 std::cout <<
"Press any key" << std::endl;
1438 char c; std::cin >>
c;
1442 if (firstSplitNode1 == NULL)
1445 std::cout <<
"Creating backup\n";
1447 firstSplitAssignment = newAssignment;
1448 firstSplitNode1 =
new CL2DClass(*node1);
1449 firstSplitNode2 =
new CL2DClass(*node2);
1453 for (
int it = 0; it < prm->
Niter; it++)
1460 oldAssignment = newAssignment;
1462 for (
size_t i = 0;
i < imax;
i++)
1469 readImage(I, assignment.
objId,
false);
1472 node1->
fit(Iaux1, assignment1);
1474 node2->
fit(Iaux2, assignment2);
1494 if (assignment1.
corr > assignment2.
corr)
1501 else if (assignment2.
corr > assignment1.
corr)
1515 shareSplitAssignments(newAssignment, node1, node2);
1518 std::cout <<
"After refinement iteration: " << it <<
" Node1: " << node1->
currentListImg.size() <<
" Node2 " << node2->
currentListImg.size() << std::endl;
1520 save.
write(
"PPPnode1.xmp");
1522 save.
write(
"PPPnode2.xmp");
1523 std::cout <<
"Press any key" << std::endl;
1529 if (newAssignment(
i) != oldAssignment(
i))
1532 std::cout <<
"Number of assignment split changes=" << Nchanges
1538 || Nchanges < 0.005 * imax)
1545 std::cout <<
"Removing both nodes, they are too small. Current size: " 1547 << minAllowedSize <<
"...\n";
1558 std::cout <<
"Removing node1, it's too small " 1560 << minAllowedSize <<
"...\n";
1564 toDelete.push_back(node2);
1566 std::cout <<
"Pushing to delete " << node2 << std::endl;
1575 std::cout <<
"Removing node2, it's too small " 1577 << minAllowedSize <<
"...\n";
1581 toDelete.push_back(node1);
1583 std::cout <<
"Pushing to delete " << node1 << std::endl;
1597 for (
size_t i = 0;
i < toDelete.size();
i++)
1598 if (toDelete[
i] != firstNode)
1601 std::cout <<
"deleting from list " << toDelete[
i] << std::endl;
1611 splitAssignment.push_back(1);
1616 splitAssignment.push_back(2);
1618 delete firstSplitNode1;
1619 delete firstSplitNode2;
1623 node1 = firstSplitNode1;
1624 node2 = firstSplitNode2;
1625 splitAssignment.reserve(
VEC_XSIZE(firstSplitAssignment));
1627 splitAssignment.push_back(
VEC_ELEM(firstSplitAssignment,
i));
1639 std::vector<size_t> splitAssignment;
1640 splitNode(P[0], P[Q], P[Q + 1], splitAssignment);
1663 fnSel = getParam(
"-i");
1664 fnOut = getParam(
"--oroot");
1665 fnODir = getParam(
"--odir");
1666 fnCodes0 = getParam(
"--ref0");
1667 Niter = getIntParam(
"--iter");
1668 Nneighbours = getIntParam(
"--neigh");
1669 Ncodes0 = getIntParam(
"--nref0");
1670 Ncodes = getIntParam(
"--nref");
1671 PminSize = getDoubleParam(
"--minsize");
1673 aux = getParam(
"--distance");
1674 useCorrelation = aux ==
"correlation";
1675 classicalMultiref = checkParam(
"--classicalMultiref");
1676 classicalSplit = checkParam(
"--classicalSplit");
1677 NSplitTrials = getIntParam(
"--maxSplitTrials");
1678 maxShift = getDoubleParam(
"--maxShift");
1679 classifyAllImages = checkParam(
"--classifyAllImages");
1680 normalizeImages = !checkParam(
"--dontNormalizeImages");
1681 mirrorImages = !checkParam(
"--dontMirrorImages");
1682 useThresholdMask = checkParam(
"--useThresholdMask");
1683 if (useThresholdMask)
1684 threshold=getDoubleParam(
"--useThresholdMask");
1693 std::cout <<
"Input images: " << fnSel << std::endl
1694 <<
"Output root: " <<
fnOut << std::endl
1695 <<
"Output dir: " << fnODir << std::endl
1696 <<
"Iterations: " << Niter << std::endl
1697 <<
"CodesSel0: " << fnCodes0 << std::endl
1698 <<
"Codes0: " << Ncodes0 << std::endl
1699 <<
"Codes: " << Ncodes << std::endl
1700 <<
"Neighbours: " << Nneighbours << std::endl
1701 <<
"Minimum node size: " << PminSize << std::endl
1702 <<
"Use Correlation: " << useCorrelation << std::endl
1703 <<
"Classical Multiref: " << classicalMultiref << std::endl
1704 <<
"Classical Split: " << classicalSplit << std::endl
1705 <<
"Max. Split trials: " << NSplitTrials << std::endl
1706 <<
"Maximum shift: " << maxShift << std::endl
1707 <<
"Classify all images: " << classifyAllImages << std::endl
1708 <<
"Normalize images: " << normalizeImages << std::endl
1709 <<
"Mirror images: " << mirrorImages << std::endl
1712 if (useThresholdMask)
1713 std::cout <<
"Threshold mask: " <<
threshold << std::endl;
1718 addUsageLine(
"Divide a selfile into the desired number of classes. ");
1719 addUsageLine(
"+Vector quantization with correntropy and a probabilistic criterion is used for creating the subdivisions.");
1720 addUsageLine(
"+Correlation and the standard maximum correlation criterion can also be used and normally produce good results.");
1721 addUsageLine(
"+Correntropy and the probabilistic clustering criterion are recommended for images with very low SNR or cases in which the correlation have clear difficulties to converge.");
1723 addUsageLine(
"+The algorithm is fully described in [[http://www.ncbi.nlm.nih.gov/pubmed/20362059][this article]].");
1725 addUsageLine(
"+An interesting convergence criterion is the number of images changing classes between iterations. If a low percentage of the image change class, then the clustering is rather stable and clear.");
1726 addUsageLine(
"+If many images change class, it is likely that there is not enough SNR to determine so many classes. It is recommended to reduce the number of classes");
1727 addSeeAlsoLine(
"mpi_image_sort");
1728 addParamsLine(
" -i <selfile> : Selfile with the input images");
1729 addParamsLine(
" [--odir <dir=\".\">] : Output directory");
1730 addParamsLine(
" [--oroot <root=class>] : Output rootname, by default, class");
1731 addParamsLine(
" [--iter <N=20>] : Number of iterations");
1732 addParamsLine(
" [--nref0 <N=2>] : Initial number of code vectors");
1733 addParamsLine(
"or --ref0 <selfile=\"\"> : Selfile with initial code vectors");
1734 addParamsLine(
" [--nref <N=16>] : Final number of code vectors");
1735 addParamsLine(
" [--neigh+ <N=4>] : Number of neighbour code vectors");
1736 addParamsLine(
" : Set -1 for all");
1737 addParamsLine(
" [--minsize+ <N=20>] : Percentage minimum node size");
1738 addParamsLine(
" : Let's say that we have 1000 images and we are currently estimating 2 classes.");
1739 addParamsLine(
" : On average each class should have about 500 images. ");
1740 addParamsLine(
" : If one of the classes drops below 20% (by default) of 500,");
1741 addParamsLine(
" : then that class is removed and the remaining class is splitted in two. ");
1742 addParamsLine(
" : The same reasoning is applied when the number of classes is 4, but 20% ");
1743 addParamsLine(
" : is calculated now on 250 (=1000/4).");
1744 addParamsLine(
" [--distance <type=correntropy>] : Distance type");
1745 addParamsLine(
" where <type>");
1746 addParamsLine(
" correntropy correlation: See CL2D paper for the definition of correntropy");
1747 addParamsLine(
" [--classicalMultiref] : Instead of enhanced clustering");
1748 addParamsLine(
" [--classicalSplit] : Instead of enhanced clustering at the split iterations");
1749 addParamsLine(
" [--maxSplitTrials <n=5>] : Maximum number of trials to split before giving up");
1750 addParamsLine(
" [--maxShift <d=10>] : Maximum allowed shift");
1751 addParamsLine(
" [--classifyAllImages] : By default, some images may not be classified. Use this option to classify them all.");
1752 addParamsLine(
" [--dontNormalizeImages] : By default, input images are normalized to have 0 mean and standard deviation 1");
1753 addParamsLine(
" [--dontMirrorImages] : By default, input images are studied unmirrored and mirrored");
1754 addParamsLine(
" [--useThresholdMask <t>] : Use a mask to compare images. Remove pixels whose value is smaller or equal t");
1755 addParamsLine(
" [--dontAlign] : Do not center the class representatives");
1756 addExampleLine(
"mpirun -np 3 `which xmipp_mpi_classify_CL2D` -i images.stk --nref 256 --oroot class --odir CL2Dresults --iter 10");
1761 if (!useCorrelation)
1762 normalizeImages=
false;
1764 maxShift2 = maxShift * maxShift;
1766 gaussianInterpolator.initialize(6, 60000,
false);
1770 SF.removeDisabled();
1776 SF.findObjects(
objId);
1781 mask.setXmippOrigin();
1785 std::vector<MultidimArray<double> > codes0;
1791 size_t Xdim0, Ydim0, Zdim0, Ndim0;
1793 if (Xdim0!=Xdim || Ydim0!=Ydim)
1799 I().setXmippOrigin();
1800 codes0.push_back(I());
1802 Ncodes0 = codes0.size();
1804 vq.initialize(SF, codes0);
1815 int Q = vq.P.size();
1816 bool originalClassicalMultiref=classicalMultiref;
1818 classicalMultiref=
true;
1819 vq.run(fnODir,
fnOut, level);
1824 std::cout <<
"Spliting nodes ...\n";
1826 int Nclean = vq.cleanEmptyNodes();
1827 int Nsplits =
XMIPP_MIN(Q,Ncodes-Q) + Nclean;
1829 for (
int i = 0;
i < Nsplits;
i++)
1831 vq.splitFirstNode();
1833 std::cout <<
"Currently there are " << vq.P.size() <<
" nodes" 1839 classicalMultiref=originalClassicalMultiref || Q==1;
1840 vq.run(fnODir,
fnOut, level);
1847 for (
int q = 0; q < Q; q++)
1849 SFq.
read(
formatString(
"class%06d_images@%s/level_%02d/%s_classes.xmd",q+1,fnODir.c_str(),level,
fnOut.c_str()));
1858 SFclassified.
clear();
1862 SFaux.
write(fnODir+
"/images.xmd");
Just to locate unclassified errors.
std::vector< CL2DAssignment > nextListImg
void init_progress_bar(long total)
MultidimArray< double > P
bool CL2DAssignmentComparator(const CL2DAssignment &d1, const CL2DAssignment &d2)
void min(Image< double > &op1, const Image< double > &op2)
int Nneighbours
Number of neighbours.
#define SPEED_UP_tempsDouble
void updateProjection(const MultidimArray< double > &I, const CL2DAssignment &assigned, bool force=false)
void write(std::ostream &os, const datablock &db)
double alignImages(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, bool wrap, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3)
constexpr float INITIAL_ROTATE_THRESHOLD
#define REPORT_ERROR(nerr, ErrormMsg)
int Niter
Number of iterations.
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
void resizeNoCopy(const MultidimArray< T1 > &v)
int NSplitTrials
MaxTrials to split.
void sqrt(Image< double > &op)
void BinaryCircularMask(MultidimArray< int > &mask, double radius, int mode, double x0, double y0, double z0)
int Ncodes0
Initial number of code vectors.
void write(const FileName &fnODir, const FileName &fnRoot, int level) const
Write the nodes.
double PminSize
Minimum size of a node.
#define DIRECT_A2D_ELEM(v, i, j)
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 MULTIDIM_ARRAY(v)
void inv(Matrix2D< T > &result) const
const FileName & name() const
double fastCorrentropy(const MultidimArray< double > &x, const MultidimArray< double > &y, double sigma, const GaussianInterpolator &G, const MultidimArray< int > &mask)
void splitNode(CL2DClass *node, CL2DClass *&node1, CL2DClass *&node2, std::vector< size_t > &finalAssignment) const
String integerToString(int I, int _width, char fill_with)
Incorrect MultidimArray size.
bool classicalMultiref
Classical Multiref.
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY1D(v)
void run(const FileName &fnODir, const FileName &fnOut, int level)
bool classifyAllImages
Clasify all images.
int readApplyGeo(const FileName &name, const MDRow &row, const ApplyGeoParams ¶ms=DefaultApplyGeoParams)
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void shareAssignments(bool shareAssignment, bool shareUpdates, bool shareNonCorr)
Share assignments.
bool normalizeImages
Normalize input images.
Matrix2D< double > centerImage(MultidimArray< double > &I, CorrelationAux &aux, RotationalCorrelationAux &aux2, int Niter, bool limitShift)
#define MAT_ELEM(m, i, j)
MultidimArray< double > Pupdate
void threshold(double *phi, unsigned long nvox, double limit)
std::vector< size_t > objId
void copyAlignment(const CL2DAssignment &alignment)
Copy alignment.
std::ostream & operator<<(std::ostream &out, const CL2DAssignment &assigned)
Show.
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
void fit(MultidimArray< double > &I, CL2DAssignment &result)
#define DIRECT_A1D_ELEM(v, i)
void fitBasic(MultidimArray< double > &I, CL2DAssignment &result, bool reverse=false)
double best_rotation(const Polar< std::complex< double > > &I1, const Polar< std::complex< double > > &I2, RotationalCorrelationAux &aux)
void compute_hist(const MultidimArrayGeneric &array, Histogram1D &hist, int no_steps)
std::vector< double > nextNonClassCorr
constexpr double INITIAL_SHIFT_THRESHOLD
void shareSplitAssignments(Matrix1D< int > &assignment, CL2DClass *node1, CL2DClass *node2) const
Share split assignment.
ProgClassifyCL2D(int argc, char **argv)
MPI constructor.
void setValue(const MDObject &object) override
#define M3x3_BY_M3x3(A, B, C)
void lookNode(MultidimArray< double > &I, int oldnode, int &newnode, CL2DAssignment &bestAssignment)
bool alignImages
Don't align images.
void lookForNeighbours(const std::vector< CL2DClass *> listP, int K)
Look for K-nearest neighbours.
void progress_bar(long rlen)
void updateNonProjection(double corr, bool force=false)
void computeDoubleMinMax(double &minval, double &maxval) const
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
int makePath(mode_t mode=0755) const
double sigma
Noise in the images.
#define DIRECT_MULTIDIM_ELEM(v, n)
bool useCorrelation
Use Correlation instead of Correntropy.
int verbose
Verbosity level.
void initialize(MetaDataDb &_SF, std::vector< MultidimArray< double > > &_codes0)
Initialize.
void transferUpdate(bool centerReference=true)
void printStats(std::ostream &out=std::cout) const
void sort(struct DCEL_T *dcel)
template void polarFourierTransform< true >(MultidimArray< double > const &, Polar< double > &, Polar< std::complex< double > > &, bool, int, int, Polar_fftw_plans *&, int)
void readImage(Image< double > &I, size_t objId, bool applyGeo) const
Read Image.
std::vector< CL2DAssignment > currentListImg
#define MATRIX1D_ARRAY(v)
String formatString(const char *format,...)
bool useThresholdMask
Use threshold mask.
bool classicalSplit
Use ClassicalCriterion at split.
void resizeNoCopy(int Xdim)
template float bestShift(MultidimArray< float > &, float &, float &, const MultidimArray< int > *, int)
void produceSideInfo()
Produce side info.
~ProgClassifyCL2D()
Destructor.
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
double threshold
Threshold to use.
void initZeros(const MultidimArray< T1 > &op)
std::vector< int > neighboursIdx
MultidimArray< int > mask
Mask for the background.
GaussianInterpolator gaussianInterpolator
CL2DClass & operator=(const CL2DClass &other)
constexpr float ROTATE_THRESHOLD
constexpr double SHIFT_THRESHOLD
void defineParams()
Usage.
void indexSort(MultidimArray< int > &indx) const
void readAlignment(const Matrix2D< double > &M)
Read alignment parameters.
CL2DAssignment()
Empty constructor.