示例#1
0
文件: Graph.cpp 项目: rrnntt/plugins
void Graph::correctToSquare()
{
  auto xMap = canvasMap(QtAPI::Plot::xBottom);
  auto yMap = canvasMap(QtAPI::Plot::yLeft);

  double xRatio = xMap.sDist() / xMap.pDist();

  if (xRatio == 0)
  {
    m_needSquareCorrection = true;
    return;
  }

  double ySDist = xRatio * yMap.pDist();

  double y0 = (yMap.s1() + yMap.s2()) / 2;
  setYAxisScale(y0 - ySDist/2, y0 + ySDist/2,false);

  std::cerr << y0 - ySDist/2 << ' ' << y0 + ySDist/2 << std::endl;
}
示例#2
0
const std::list<sClLnk *> JLinkage::DoJLClusterization(void (*OnProgress)(float)){
	
	
	float tEps = (float)1.0f/(1.0f+(float)mModels.size()); // Just a distance to see if the jaccard distance is equal to one
	float tOneEpsDistance = 1.0f - tEps; // Just a distance to see if the jaccard distance is equal to one

	
	// Update neighboardhood information
	if(mUseKDTree){
		mKDTree.optimise();
		
		/* old FIND WITHING RANGE
		static std::vector<sPtLnkPointer> nearPtsIdx;
	
		static bool firsttime = true;
		if(firsttime){
			nearPtsIdx.reserve(500);
			firsttime = false;
		}
		*/
		for(std::list<sPtLnk *>::iterator tIterPt = mDataPoints.begin(); tIterPt != mDataPoints.end(); ++tIterPt){
			if(!(*tIterPt)->mToBeUpdateKDTree)
				continue;
			// Threadable build Distance list for kdtree 


			/* old FIND WITHING RANGE
			nearPtsIdx.clear();
			sPtLnkPointer nPtPointer; nPtPointer.mPtLnk = *tIterPt;
			mKDTree.find_within_range(nPtPointer, mNNeighboardsUpdateDistance, std::back_inserter(nearPtsIdx));
			*/
			sPtLnkPointer nPtPointer; nPtPointer.mPtLnk = *tIterPt; nPtPointer.mPtLnk->mAlreadyFound = false;
			std::list<sPtLnkPointer> kneigh = FindKNearest(nPtPointer,std::numeric_limits<float>::max(),mKNeighboards, (int)mDataPointsSize);

			// Find K-Nearest
			for(std::list<sPtLnkPointer>::iterator tIter = kneigh.begin(); tIter != kneigh.end(); ++tIter){
			
			//for(std::vector<sPtLnkPointer>::iterator tIter = nearPtsIdx.begin(); tIter != nearPtsIdx.end(); ++tIter){
				if((*tIter).mPtLnk->mBelongingCluster == (*tIterPt)->mBelongingCluster)
					continue;				
				
				bool alreadyPresent = false;
				for(std::list<sDist *>::iterator distIter = (*tIter).mPtLnk->mBelongingCluster->mPairwiseJaccardDistance.begin();
					distIter != (*tIter).mPtLnk->mBelongingCluster->mPairwiseJaccardDistance.end();
					distIter++){
					
					if((*distIter)->mCluster1 == (*tIterPt)->mBelongingCluster || (*distIter)->mCluster2 == (*tIterPt)->mBelongingCluster)
						alreadyPresent = true;
				}

				if(alreadyPresent)
					continue;

				sDist *tDist = new sDist;
				tDist->mCluster1 = (*tIterPt)->mBelongingCluster;
				tDist->mCluster2 = (*tIter).mPtLnk->mBelongingCluster;
				
				(*tIterPt)->mBelongingCluster->mPairwiseJaccardDistance.push_back(tDist);
				(*tIter).mPtLnk->mBelongingCluster->mPairwiseJaccardDistance.push_back(tDist);
				
				tDist->mToBeUpdated = true;
				mDistancesToBeUpdated.push_back(tDist);
				mDistancesToBeUpdatedSize++;
			}
			(*tIterPt)->mToBeUpdateKDTree = false;			
		}
		
	}
	
	if(OnProgress != NULL)
		OnProgress(0.01f);
	
	// First step: update all the pw distances that needs an update
	// Please Note: If a distance don't need to be updated it means that it would be certainly equal to 1 from the previous JLClusterization
	// --> Store also a list with ALL the pairwise unique jaccard distance
	std::vector<sDist *> mHeapDistanceList(mDistancesToBeUpdatedSize);	
	
	unsigned int counter = 0;
	while(mDistancesToBeUpdatedSize > 0){
		sDist *tDist = mDistancesToBeUpdated.back();
		mDistancesToBeUpdated.pop_back();
		mDistancesToBeUpdatedSize--;
		tDist->mPairwiseJaccardDistance = 
			PSJaccardDist(	tDist->mCluster1->mPreferenceSet,
							tDist->mCluster2->mPreferenceSet,
							&(tDist->mPairwiseUnion),
							&(tDist->mPairwiseIntersection) );
		tDist->mToBeUpdated = false;
		if(tDist->mPairwiseJaccardDistance < tOneEpsDistance){
			mHeapDistanceList[counter] = tDist;
			++counter;
		}
	}

	if(OnProgress != NULL)
		OnProgress(0.02f);

	mHeapDistanceList.resize(counter);

	// A distance that will invalidate the heap, needing a heap resort
	float mCurrentInvalidatingDistance = 1.0f;

	// Make the heap
	std::sort(mHeapDistanceList.begin(), mHeapDistanceList.end(), sDist());
	
	unsigned int currentSortIdx = 0;
	unsigned int initialDistance = (unsigned int)mHeapDistanceList.size();
		
	while(mHeapDistanceList.size() > 0){
		
		
		sDist *sCurrentMinDist = NULL;
		if(currentSortIdx < mHeapDistanceList.size())
			sCurrentMinDist = mHeapDistanceList[currentSortIdx];
		// TODO speed up previous line!
		
	    if(sCurrentMinDist == NULL || sCurrentMinDist->mPairwiseJaccardDistance > tOneEpsDistance && mCurrentInvalidatingDistance > tOneEpsDistance  ){ // All the distance will be equals to one - clusterization is finished
			// We've finished since all distances have been processed or are equal to 1.0f
			mHeapDistanceList.clear();
		}
		else if(sCurrentMinDist->mCluster1 == NULL || sCurrentMinDist->mCluster2 == NULL ){
			// Eliminate the non-valid distance(belong to an eliminated clusters
			for(std::vector<sDist *>::iterator tIterDist = mHeapDistanceList.begin() + currentSortIdx + 1 ; tIterDist != mHeapDistanceList.end(); tIterDist++){
				assert((*tIterDist) != sCurrentMinDist);
			}
			delete sCurrentMinDist;
			++currentSortIdx;
		}
		else if(sCurrentMinDist->mPairwiseJaccardDistance > (mCurrentInvalidatingDistance-tEps)){ // We need an heap resort
			
			mHeapDistanceList.erase(mHeapDistanceList.begin(), mHeapDistanceList.begin()+(currentSortIdx));
			
			if(mHeapDistanceList.size() > 1){

				// First eliminate all the distance equals to one from the heap
				// Push all these distances to the end of the vector...
				unsigned int idxElementProcessing = 0;
				unsigned int idxLastUsefullElement = (unsigned int)mHeapDistanceList.size() - 1;
				
				while(idxElementProcessing <= idxLastUsefullElement && idxLastUsefullElement > 0 ){
					
					if(mHeapDistanceList[idxElementProcessing]->mPairwiseJaccardDistance > tOneEpsDistance || mHeapDistanceList[idxElementProcessing]->mCluster1 == NULL || mHeapDistanceList[idxElementProcessing]->mCluster2 == NULL){
						// In this case we need to move the distance to the end

						// Swap elements
						sDist *temp = mHeapDistanceList[idxElementProcessing];
						mHeapDistanceList[idxElementProcessing] = mHeapDistanceList[idxLastUsefullElement];
						mHeapDistanceList[idxLastUsefullElement] = temp;

						// If the distance belongs to one eliminated cluster, delete it
						if(mHeapDistanceList[idxLastUsefullElement]->mCluster1 == NULL || mHeapDistanceList[idxLastUsefullElement]->mCluster2 == NULL)
							delete mHeapDistanceList[idxLastUsefullElement];

						idxLastUsefullElement--;
					}
					else{
						idxElementProcessing++;
					}
				}
				
				if(idxLastUsefullElement > 0){
					// ... and then erase them
					if(idxLastUsefullElement < mHeapDistanceList.size()-1)
						mHeapDistanceList.erase(mHeapDistanceList.begin()+idxLastUsefullElement+1, mHeapDistanceList.end());
					// Re-Set the heap
					std::sort(mHeapDistanceList.begin(), mHeapDistanceList.end(), sDist());
				}
				else{
					// Ok we finished
					mHeapDistanceList.clear();
				}
								
			}
			
			mCurrentInvalidatingDistance = 2.0f;
			currentSortIdx = 0;
		}
		else{
			// The distance is less than the invalidating distance, merge the two cluster and update the other distances accordingly
			
			// if kd-tree is used, merge the distances of the clusters for adding the new ones of the new created cluster
			std::list<sClLnk *> distancesToBeAdded;

			sCurrentMinDist->mCluster2->mPairwiseJaccardDistance.remove(sCurrentMinDist);
			sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.remove(sCurrentMinDist);

			if(mUseKDTree){
				for(std::list<sDist *>::iterator distIter1 = sCurrentMinDist->mCluster2->mPairwiseJaccardDistance.begin(); distIter1 != sCurrentMinDist->mCluster2->mPairwiseJaccardDistance.end(); ++distIter1){
					// Threadable Check distance to merge KD-Tree
					bool add = true;
					// Check if the distance already exists
					for(std::list<sDist *>::iterator distIter2 = sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.begin(); distIter2 != sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.end(); ++distIter2){
						if((*distIter1)->mCluster1 == (*distIter2)->mCluster1 || (*distIter1)->mCluster2 == (*distIter2)->mCluster2 
						   || (*distIter1)->mCluster2 == (*distIter2)->mCluster1 || (*distIter1)->mCluster1 == (*distIter2)->mCluster2){
							add = false; // Point already present
							break;
						}
					}
					if(add){
						if((*distIter1)->mCluster1 != sCurrentMinDist->mCluster2)
							distancesToBeAdded.push_back((*distIter1)->mCluster1);
						else if((*distIter1)->mCluster2 != sCurrentMinDist->mCluster2)
							distancesToBeAdded.push_back((*distIter1)->mCluster2);
					}
					
				}
			}
			
			
			// Update the cluster pointer of all the points of the deleted cluster
			for(std::list<sPtLnk *>::iterator ptIter = sCurrentMinDist->mCluster2->mBelongingPts.begin(); ptIter != sCurrentMinDist->mCluster2->mBelongingPts.end(); ptIter++)
				(*ptIter)->mBelongingCluster = sCurrentMinDist->mCluster1;

						
			// Merge the two clusters into cluster 1
			sCurrentMinDist->mCluster1->mPreferenceSet &= sCurrentMinDist->mCluster2->mPreferenceSet;
			sCurrentMinDist->mCluster1->mBelongingPts.merge(sCurrentMinDist->mCluster2->mBelongingPts);			

			
			// Delete cluster 2
			mDataClusters.remove(sCurrentMinDist->mCluster2);

			if(mUseKDTree){
				for(std::list<sClLnk *>::iterator clIter = distancesToBeAdded.begin(); clIter != distancesToBeAdded.end(); ++clIter){
					// Threadable Add kd-tree distances
					sDist *tDist = new sDist;
					tDist->mCluster1 = sCurrentMinDist->mCluster1;
					tDist->mCluster2 = *clIter;
					
					sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.push_back(tDist);
					(*clIter)->mPairwiseJaccardDistance.push_back(tDist);
					mHeapDistanceList.push_back(tDist);
				}
			}
			
				
			
			// Update all the distances of the old cluster -- delete
			for(std::list<sDist *>::iterator tIterDist = sCurrentMinDist->mCluster2->mPairwiseJaccardDistance.begin(); tIterDist != sCurrentMinDist->mCluster2->mPairwiseJaccardDistance.end(); tIterDist++){
				// Threadable: delete distance for the old cluster
				if(sCurrentMinDist != (*tIterDist)){
					if((*tIterDist)->mCluster1 != sCurrentMinDist->mCluster2)
						(*tIterDist)->mCluster1->mPairwiseJaccardDistance.remove( (*tIterDist));
					else if((*tIterDist)->mCluster2 != sCurrentMinDist->mCluster2)
						(*tIterDist)->mCluster2->mPairwiseJaccardDistance.remove( (*tIterDist));
					(*tIterDist)->mCluster1 = NULL;
					(*tIterDist)->mCluster2 = NULL;
				}
			}

			// Do additional user-defined update steps if specified
			if(mClusterMergeAdditionalOperation != NULL)
				mClusterMergeAdditionalOperation(sCurrentMinDist->mCluster1);

#ifndef JL_NO_THREADS
				boost::thread_group *tg = new boost::thread_group();
				// Update all the distances of the new cluster
				for(std::list<sDist *>::iterator tIterDist = sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.begin(); tIterDist != sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.end(); tIterDist++){
					// Update distances
					tg->create_thread(boost::bind(&(UpdateDistance),*tIterDist, &mCurrentInvalidatingDistance, mClusterClusterDiscardTest));
					if(tg->size() >= MAXTHREADS){
						tg->join_all();
						delete tg;
						tg = new boost::thread_group();
					}
				}
			tg->join_all();
			delete tg;
#else
				for(std::list<sDist *>::iterator tIterDist = sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.begin(); tIterDist != sCurrentMinDist->mCluster1->mPairwiseJaccardDistance.end(); tIterDist++){
					// Update distances
					JLinkage::UpdateDistance(*tIterDist, &mCurrentInvalidatingDistance, mClusterClusterDiscardTest);
				}

#endif

			if(OnProgress != NULL)
				OnProgress(1.0f - ((float) (mHeapDistanceList.size() - currentSortIdx) / (float)initialDistance));
			
			// Delete old cluster
			if(sCurrentMinDist->mCluster2 && mDestroyAdditionalData)
				mDestroyAdditionalData(sCurrentMinDist->mCluster2);
		
			delete sCurrentMinDist->mCluster2;
			delete sCurrentMinDist;

			++currentSortIdx;

		}



	}

	if(OnProgress != NULL)
		OnProgress(1.0f);
	
	// return the list of clusters
	return mDataClusters;
}