<commit_before>void AliAnalysisTaskSECompareHFTest()
{
  //
  // Test macro for the AliAnalysisTaskSE for heavy-flavour candidates
  // association with MC truth (using MC info in AOD)
  // A.Dainese, andrea.dainese@lnl.infn.it
  //

  gSystem->Load("libTree.so");
  gSystem->Load("libGeom.so");
  gSystem->Load("libPhysics.so");
  gSystem->Load("libVMC.so");
  gSystem->Load("libSTEERBase.so");
  gSystem->Load("libESD.so");
  gSystem->Load("libAOD.so");
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  gSystem->Load("libPWG3base.so");
  gSystem->Load("libPWG3vertexingHF.so");

  // Local files
  TChain *chain = new TChain("aodTree");
  chain->Add("./AliAOD.root");

  // or:
  /*
  //Fetch files with AliEn :
  const char *collectionfile = "CollectionTags.xml";
  TGrid::Connect("alien://") ;
  //Create an AliRunTagCuts and an AliEventTagCuts Object and impose some selection criteria
  AliRunTagCuts      *runCuts   = new AliRunTagCuts();
  AliEventTagCuts    *eventCuts = new AliEventTagCuts();
  AliLHCTagCuts      *lhcCuts   = new AliLHCTagCuts();
  AliDetectorTagCuts *detCuts   = new AliDetectorTagCuts();
  eventCuts->SetMultiplicityRange(0,20000);
  //Create an AliTagAnalysis Object and chain the tags
  AliTagAnalysis   *tagAna = new AliTagAnalysis();
  tagAna->SetType("AOD");
  TAlienCollection *coll   = TAlienCollection::Open(collectionfile);
  TGridResult      *tagResult = coll->GetGridResult("",0,0);
  tagResult->Print();
  tagAna->ChainGridTags(tagResult);
  //Create a new aod chain and assign the chain that is returned by querying the tags
  TChain* chain = tagAna->QueryTags(runCuts,lhcCuts,detCuts,eventCuts);
  */

  // Create the analysis manager
  AliAnalysisManager *mgr  = new AliAnalysisManager("My Manager","My Manager");
  mgr->SetDebugLevel(10);

  // Input
  AliAODInputHandler *inputHandler = new AliAODInputHandler();
  inputHandler->AddFriend("AliAOD.VertexingHF.root");
  mgr->SetInputEventHandler(inputHandler);

  // Aanalysis task
  AliAnalysisTaskSECompareHF *hfTask = new AliAnalysisTaskSECompareHF("CompareHFAnalysis");
  hfTask->SetDebugLevel(2);
  Double_t cutsD0[9]=
    // cutsD0[0] = inv. mass half width [GeV]
    // cutsD0[1] = dca [cm]
    // cutsD0[2] = cosThetaStar
    // cutsD0[3] = pTK [GeV/c]
    // cutsD0[4] = pTPi [GeV/c]
    // cutsD0[5] = d0K [cm]   upper limit!
    // cutsD0[6] = d0Pi [cm]  upper limit!
    // cutsD0[7] = d0d0 [cm^2]
    // cutsD0[8] = cosThetaPoint
                     {1,
		      100000.,
		      1.1,
		      0.,
		      0.,
		      100000.,
		      100000.,
		      100000000.,
		      -0.9};
  hfTask->SetD0toKpiCuts(cutsD0);

  mgr->AddTask(hfTask);

  //
  // Create containers for input/output
  AliAnalysisDataContainer *cinput = mgr->CreateContainer("cinput",TChain::Class(),
							  AliAnalysisManager::kInputContainer);
  AliAnalysisDataContainer *coutput = mgr->CreateContainer("coutput",TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   "CmpHF.root");
  mgr->ConnectInput(hfTask,0,cinput);
  mgr->ConnectOutput(hfTask,1,coutput);

  //
  // Run the analysis
  //
  printf("CHAIN HAS %d ENTRIES\n",(Int_t)chain->GetEntries());
  if(mgr->InitAnalysis()) {
    mgr->PrintStatus();
    mgr->StartAnalysis("local",chain);
    //mgr->StartAnalysis("grid",chain);
  }

  return;
}
<commit_msg>Added flag for "local" or "grid" mode<commit_after>void AliAnalysisTaskSECompareHFTest()
{
  //
  // Test macro for the AliAnalysisTaskSE for heavy-flavour candidates
  // association with MC truth (using MC info in AOD)
  // A.Dainese, andrea.dainese@lnl.infn.it
  //
  TString mode="local"; // otherwise, "grid"

  gSystem->Load("libTree.so");
  gSystem->Load("libGeom.so");
  gSystem->Load("libPhysics.so");
  gSystem->Load("libVMC.so");
  gSystem->Load("libSTEERBase.so");
  gSystem->Load("libESD.so");
  gSystem->Load("libAOD.so");
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  gSystem->Load("libPWG3base.so");
  gSystem->Load("libPWG3vertexingHF.so");

  TChain *chainAOD = 0;
  TChain *chainAODfriend = 0;

  chainAOD = new TChain("aodTree");
  chainAODfriend = new TChain("aodTree");

  if(mode=="local") {
    // Local files
    chainAOD->Add("./AliAOD.root");
    chainAODfriend->Add("./AliAOD.VertexingHF.root");
    // ... add more if needed
  } else { // grid (NOT TESTED YET)
    //Fetch files with AliEn
    // xml: need to check the 1-to-1 correspondence
    const char *collectionfileAOD = "CollectionAOD.xml";
    const char *collectionfileAODfriend = "CollectionAODfriend.xml";
    TGrid::Connect("alien://");
    //Create an AliTagAnalysis Object and chain the tags
    AliTagAnalysis   *tagAna = new AliTagAnalysis();
    chainAOD = tagAna->GetChainFromCollection(collectionfileAOD,"aodTree");
    chainAODfriend = tagAna->GetChainFromCollection(collectionfileAODfriend,"aodTree");
  }

  // attach the friend chain
  chainAOD->AddFriend(chainAODfriend);

  // Create the analysis manager
  AliAnalysisManager *mgr  = new AliAnalysisManager("My Manager","My Manager");
  mgr->SetDebugLevel(10);

  // Input
  AliAODInputHandler *inputHandler = new AliAODInputHandler();
  //inputHandler->AddFriend("AliAOD.VertexingHF.root");//should not be needed
  mgr->SetInputEventHandler(inputHandler);

  // Aanalysis task
  AliAnalysisTaskSECompareHF *hfTask = new AliAnalysisTaskSECompareHF("CompareHFAnalysis");
  hfTask->SetDebugLevel(2);
  Double_t cutsD0[9]=
    // cutsD0[0] = inv. mass half width [GeV]
    // cutsD0[1] = dca [cm]
    // cutsD0[2] = cosThetaStar
    // cutsD0[3] = pTK [GeV/c]
    // cutsD0[4] = pTPi [GeV/c]
    // cutsD0[5] = d0K [cm]   upper limit!
    // cutsD0[6] = d0Pi [cm]  upper limit!
    // cutsD0[7] = d0d0 [cm^2]
    // cutsD0[8] = cosThetaPoint
                     {1,
		      100000.,
		      1.1,
		      0.,
		      0.,
		      100000.,
		      100000.,
		      100000000.,
		      -0.9};
  hfTask->SetD0toKpiCuts(cutsD0);

  mgr->AddTask(hfTask);

  //
  // Create containers for input/output
  AliAnalysisDataContainer *cinput = mgr->CreateContainer("cinput",TChain::Class(),
							  AliAnalysisManager::kInputContainer);
  AliAnalysisDataContainer *coutput = mgr->CreateContainer("coutput",TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   "CmpHF.root");
  mgr->ConnectInput(hfTask,0,cinput);
  mgr->ConnectOutput(hfTask,1,coutput);

  //
  // Run the analysis
  //
  printf("CHAIN HAS %d ENTRIES\n",(Int_t)chainAOD->GetEntries());
  if(mgr->InitAnalysis()) {
    mgr->PrintStatus();
    mgr->StartAnalysis(mode.Data(),chainAOD);
  }

  return;
}
<|endoftext|>


<commit_before><commit_msg>interpolateZ added and working<commit_after><|endoftext|>


<commit_before>//
//  calcPWP.cpp
//
//
//  Created by Evan McCartney-Melstad on 1/10/15.
//
//
#include "calcPWPchunks.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <thread>
#include <string>

int calcPWPfromBinaryFile (std::string binaryFile, unsigned long long int numLoci, const int numIndividuals, std::string outFile, int lociChunkSize, std::string sampleNamesFile, int numThreads) {
    // Get the list of sample names from the sampleNames file
    std::ifstream sampleFile(sampleNamesFile);
    std::string sampleLine;
    std::vector<std::string> sampleLines;
    while (std::getline(sampleFile, sampleLine)) {
        sampleLines.push_back(sampleLine);
    }

    std::cout << "Number of threads: " << numThreads << std::endl;

    std::ifstream file (binaryFile, std::ios::in|std::ios::binary);
    if (file.is_open()) {
        std::cout << "Calculating divergence based on " << numLoci << " total loci." << std::endl;

        // How many bytes to read in at one time. The number of loci read in at a time will actually be numLoci*numThreads
        unsigned long long int lociChunkByteSize = (unsigned long long int)lociChunkSize * numIndividuals * 2 * numThreads;
        int numFullChunks = (numLoci*numIndividuals*2)/lociChunkByteSize; // Truncates answer to an integer
        unsigned long long int remainingBytesAfterFullChunks = (numLoci*numIndividuals*2) % lociChunkByteSize;

        if (remainingBytesAfterFullChunks != 0) {
            std::cout << "Total number of chunks to run: " << numFullChunks + 1 << std::endl;
        } else {
            std::cout << "Total number of chunks to run: " << numFullChunks << std::endl;
        }

        /* We are going to split the loci in the chunk between numThreads threads. Each thread will modify two multidimensional
         vectors of the forms std::vector< std::vector<long double> > pwp(numIndividuals, std::vector<long double>(numIndividuals,0))
         and std::vector< std::vector<unsigned long long int> > weightings(numIndividuals, std::vector<unsigned long long int>(numIndividuals,0))
         First, we'll generate all of these vectors, which apparently in C++ needs to be constructed of a
         vector of two-dimensional vectors...
         */
        std::vector<std::vector<std::vector<long double>>> pwpThreads(numThreads, std::vector<std::vector<long double>> (numIndividuals, std::vector<long double> (numIndividuals,0) ) ); //pwpThreads[0] is the first 2D array for the first thread, etc...
        std::vector<std::vector<std::vector<unsigned long long int>>> weightingsThreads(numThreads, std::vector<std::vector<unsigned long long int> > (numIndividuals, std::vector<unsigned long long int> (numIndividuals,0) ) );
        std::cout << "Initialized the 3d weighting and pwp vectors" << std::endl;

        // Read in the data in chunks, and process each chunk using numThreads threads
        int chunkCounter = 0;
        while (chunkCounter < numFullChunks) {
            unsigned long long bytesPerThread = lociChunkByteSize / numThreads;
            unsigned long long int lociPerThread = bytesPerThread / (numIndividuals*2);

            std::cout << "Running chunk #" << chunkCounter << std::endl;
            // Load the read counts into the vector readCounts, starting at byte 0
            std::vector<unsigned char> readCounts(lociChunkByteSize);
            file.read((char*) &readCounts[0], lociChunkByteSize);

            std::vector<std::thread> threadsVec;
            for (int threadRunning = 0; threadRunning < numThreads; threadRunning++) {
                unsigned long long int firstLocus = (unsigned long long int) threadRunning * lociPerThread;
                unsigned long long int finishingLocus = ((unsigned long long int) threadRunning * lociPerThread) + lociPerThread - (unsigned long long int)1.0;

                threadsVec.push_back(std::thread(calcPWPforRange, firstLocus, finishingLocus, numIndividuals, std::ref(readCounts), std::ref(pwpThreads[threadRunning]), std::ref(weightingsThreads[threadRunning])));
            }

            // Wait on threads to finish
            for (int i = 0; i < numThreads; ++i) {
                threadsVec[i].join();
            }
            if (remainingBytesAfterFullChunks != 0) {
                std::cout << "All threads completed running for chunk " << chunkCounter + 1 << " of " << numFullChunks + 1 << std::endl;
            } else {
                std::cout << "All threads completed running for chunk " << chunkCounter + 1 << " of " << numFullChunks << std::endl;
            }
            chunkCounter++;
            std::cout << "Finished processing " << chunkCounter * lociPerThread * numThreads << " loci out of " << numLoci << std::endl;
        }

        //////// LAST CHUNK ////////
        // For the last chunk, we'll just run it in a single thread. Just add everything to the vectors for the first thread.
        // We can skip this if there aren't any bytes remaining (i.e. if total loci are perfectly divisibile by chunk size * number of threads).
        if (remainingBytesAfterFullChunks != 0) {
            std::vector<unsigned char> readCountsRemaining(remainingBytesAfterFullChunks);
            file.read((char*) &readCountsRemaining[0], remainingBytesAfterFullChunks);
            unsigned long long int finishingLocus = (readCountsRemaining.size()/(numIndividuals*2)) - 1;
            calcPWPforRange(0, finishingLocus, numIndividuals, std::ref(readCountsRemaining), std::ref(pwpThreads[0]), std::ref(weightingsThreads[0]));
        }

        //////// Aggregate the results of the threads and print final results ////////
        std::vector<std::vector<long double>> weightingsSum(numIndividuals, std::vector<long double>(numIndividuals,0));
        std::vector<std::vector<long double>> pwpSum(numIndividuals, std::vector<long double>(numIndividuals,0));

        for (int tortoise = 0; tortoise < numIndividuals; tortoise++) {
            for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                for (int threadVector = 0; threadVector < numThreads; threadVector++) {
                    weightingsSum[tortoise][comparisonTortoise] += weightingsThreads[threadVector][tortoise][comparisonTortoise];
                    pwpSum[tortoise][comparisonTortoise] += pwpThreads[threadVector][tortoise][comparisonTortoise];
                }
            }
        }
        std::cout << "Finished summing the threads vectors" << std::endl;\
        file.close(); // This is the binary file that holds all the read count data

        //////// Print out the final output to the pairwise pi file ////////
        std::ofstream pwpOUT (outFile);
        pwpOUT << "Sample1\tSample2\tPWP" << std::endl;
        int rowCounter = 0;
        if (!pwpOUT) {
            std::cerr << "Crap, " << outFile << "didn't open!" << std::endl;
        } else {
            for (int tortoise=0; tortoise < numIndividuals; tortoise++) {
                for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                    rowCounter++;

                    //std::cout << "Tortoise numbers: " << tortoise << " and " << comparisonTortoise << std::endl;
                    if (weightingsSum[tortoise][comparisonTortoise] > 0) {
                        /*
                        std::cout << weightings[tortoise][comparisonTortoise] << std::endl;
                        std::cout << pwp[tortoise][comparisonTortoise] / weightings[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::fixed;
                        std::cout << "Weightings for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << weightingsSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << "PWP for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << pwpSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::scientific;
                        */
                        pwpOUT << sampleLines[tortoise] << "\t" << sampleLines[comparisonTortoise] << "\t" << pwpSum[tortoise][comparisonTortoise] / weightingsSum[tortoise][comparisonTortoise] << std::endl;
                    } else {
                        pwpOUT << "NA" << std::endl;
                    }
                }
            }
        }
    } else {
        std::cout << "Unable to open file";
    }
    return 0;
}

int calcPWPforRange (unsigned long long startingLocus, unsigned long long endingLocus, int numIndividuals, std::vector<unsigned char>& mainReadCountVector, std::vector<std::vector<long double>>& threadPWP, std::vector<std::vector<unsigned long long int>>& threadWeightings) {
    //std::cout << "Calculating PWP for the following locus range: " << startingLocus + ((chunkCounter + 1) * numLoci * numThreads) << " to " << endingLocus + ((chunkCounter + 1) * numLoci * numThreads) << std::endl;
    for( unsigned long long locus = startingLocus; locus < endingLocus; locus++) {
        //std::cout << "Processing locus # " << locus << std::endl;
        //if (locus % 100000 == 0) {
        //    std::cout << locus << " loci processed through calcPWPfromBinaryFile" << std::endl;
        //}

        unsigned long long coverages[numIndividuals];
        long double *majorAlleleFreqs = new long double[numIndividuals]; // This will hold the major allele frequencies for that locus for each tortoise

        for( int tortoise = 0; tortoise < numIndividuals; tortoise++ ) {
            unsigned long long majorIndex = locus * (numIndividuals*2) + 2 * tortoise;
            unsigned long long minorIndex = locus * (numIndividuals*2) + 2 * tortoise + 1;

            coverages[tortoise] = int(mainReadCountVector[majorIndex]) + int(mainReadCountVector[minorIndex]); // Hold the coverages for each locus
            if ( coverages[tortoise] > 0 ) {
                majorAlleleFreqs[tortoise] = (long double)mainReadCountVector[majorIndex] / (long double)coverages[tortoise]; // Not necessarily an int, but could be 0 or 1

                if (coverages[tortoise] > 1) {
                    unsigned long long locusWeighting = (unsigned long long) (coverages[tortoise]*(coverages[tortoise]-1));
                    threadWeightings[tortoise][tortoise] += (unsigned long long)locusWeighting; // This is an integer--discrete number of reads

                    threadPWP[tortoise][tortoise] += (long double)(locusWeighting) * ((long double)2.0 * majorAlleleFreqs[tortoise] * ((long double)(coverages[tortoise]) - (long double)(mainReadCountVector[majorIndex])) / (long double)((coverages[tortoise])-(long double)1.0));
                }

                for( int comparisonTortoise = 0; comparisonTortoise < tortoise; comparisonTortoise++) {
                    if (coverages[comparisonTortoise] > 0) {
                        unsigned long long locusWeighting = (unsigned long long)coverages[tortoise] * (unsigned long long)(coverages[comparisonTortoise]);
                        threadWeightings[tortoise][comparisonTortoise] += locusWeighting;

                        threadPWP[tortoise][comparisonTortoise] += (long double)locusWeighting * (majorAlleleFreqs[tortoise] * ((long double)1.0-majorAlleleFreqs[comparisonTortoise]) + majorAlleleFreqs[comparisonTortoise] * ((long double)1.0-majorAlleleFreqs[tortoise]));
                    }
                }
            }
        }
        delete[] majorAlleleFreqs; // Needed to avoid memory leaks
    }
    //std::cout << "Finished thread ending on locus " << endingLocus + ((chunkCounter + 1) * numLoci * numThreads) << std::endl;
    return 0;
}

<commit_msg>Update calcPWPchunks.cpp<commit_after>//
//  calcPWP.cpp
//
//
//  Created by Evan McCartney-Melstad on 1/10/15.
//
//
#include "calcPWPchunks.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <thread>
#include <string>

int calcPWPfromBinaryFile (std::string binaryFile, unsigned long long int numLoci, const int numIndividuals, std::string outFile, int lociChunkSize, std::string sampleNamesFile, int numThreads) {
    // Get the list of sample names from the sampleNames file. We'll store these in a vector so that we can make the output readable at the end
    std::ifstream sampleFile(sampleNamesFile);
    std::string sampleLine;
    std::vector<std::string> sampleLines;
    while (std::getline(sampleFile, sampleLine)) {
        sampleLines.push_back(sampleLine);
    }

    std::cout << "Number of threads: " << numThreads << std::endl;

    std::ifstream file (binaryFile, std::ios::in|std::ios::binary);
    if (file.is_open()) {
        std::cout << "Calculating divergence based on " << numLoci << " total loci." << std::endl;

        // How many bytes to read in at one time. The number of loci read in at a time will actually be numLoci*numThreads
        unsigned long long int lociChunkByteSize = (unsigned long long int)lociChunkSize * numIndividuals * 2 * numThreads;
        int numFullChunks = (numLoci*numIndividuals*2)/lociChunkByteSize; // Truncates answer to an integer
        unsigned long long int remainingBytesAfterFullChunks = (numLoci*numIndividuals*2) % lociChunkByteSize;

        if (remainingBytesAfterFullChunks != 0) {
            std::cout << "Total number of chunks to run: " << numFullChunks + 1 << std::endl;
        } else {
            std::cout << "Total number of chunks to run: " << numFullChunks << std::endl;
        }

        /* We are going to split the loci in the chunk between numThreads threads. Each thread will modify two multidimensional
         vectors of the forms std::vector< std::vector<long double> > pwp(numIndividuals, std::vector<long double>(numIndividuals,0))
         and std::vector< std::vector<unsigned long long int> > weightings(numIndividuals, std::vector<unsigned long long int>(numIndividuals,0))
         First, we'll generate all of these vectors of two-dimensional vectors:
         */
        std::vector<std::vector<std::vector<long double>>> pwpThreads(numThreads, std::vector<std::vector<long double>> (numIndividuals, std::vector<long double> (numIndividuals,0) ) ); //pwpThreads[0] is the first 2D array for the first thread, etc...
        std::vector<std::vector<std::vector<unsigned long long int>>> weightingsThreads(numThreads, std::vector<std::vector<unsigned long long int> > (numIndividuals, std::vector<unsigned long long int> (numIndividuals,0) ) );
        std::cout << "Initialized the 3d weighting and pwp vectors" << std::endl;

        // Read in the data in chunks, and process each chunk using numThreads threads
        int chunkCounter = 0;
        while (chunkCounter < numFullChunks) {
            unsigned long long bytesPerThread = lociChunkByteSize / numThreads;
            unsigned long long int lociPerThread = bytesPerThread / (numIndividuals*2);

            std::cout << "Running chunk #" << chunkCounter << std::endl;
            // Load the read counts into the vector readCounts, starting at byte 0
            std::vector<unsigned char> readCounts(lociChunkByteSize);
            file.read((char*) &readCounts[0], lociChunkByteSize);

            std::vector<std::thread> threadsVec;
            for (int threadRunning = 0; threadRunning < numThreads; threadRunning++) {
                unsigned long long int firstLocus = (unsigned long long int) threadRunning * lociPerThread;
                unsigned long long int finishingLocus = ((unsigned long long int) threadRunning * lociPerThread) + lociPerThread - (unsigned long long int)1.0;

                threadsVec.push_back(std::thread(calcPWPforRange, firstLocus, finishingLocus, numIndividuals, std::ref(readCounts), std::ref(pwpThreads[threadRunning]), std::ref(weightingsThreads[threadRunning])));
            }

            // Wait on all threads to finish
            for (int i = 0; i < numThreads; ++i) {
                threadsVec[i].join();
            }
            if (remainingBytesAfterFullChunks != 0) {
                std::cout << "All threads completed running for chunk " << chunkCounter + 1 << " of " << numFullChunks + 1 << std::endl;
            } else {
                std::cout << "All threads completed running for chunk " << chunkCounter + 1 << " of " << numFullChunks << std::endl;
            }
            chunkCounter++;
            std::cout << "Finished processing " << chunkCounter * lociPerThread * numThreads << " loci out of " << numLoci << std::endl;
        }

        //////// LAST CHUNK ////////
        // For the last chunk, we'll just run it in a single thread. Just add everything to the vectors for the first thread.
        // We can skip this if there aren't any bytes remaining (i.e. if total loci are perfectly divisibile by chunk size * number of threads).
        if (remainingBytesAfterFullChunks != 0) {
            std::vector<unsigned char> readCountsRemaining(remainingBytesAfterFullChunks);
            file.read((char*) &readCountsRemaining[0], remainingBytesAfterFullChunks);
            unsigned long long int finishingLocus = (readCountsRemaining.size()/(numIndividuals*2)) - 1;
            calcPWPforRange(0, finishingLocus, numIndividuals, std::ref(readCountsRemaining), std::ref(pwpThreads[0]), std::ref(weightingsThreads[0]));
        }

        //////// Aggregate the results of the threads and print final results into the output file ////////
        std::vector<std::vector<long double>> weightingsSum(numIndividuals, std::vector<long double>(numIndividuals,0));
        std::vector<std::vector<long double>> pwpSum(numIndividuals, std::vector<long double>(numIndividuals,0));

        for (int tortoise = 0; tortoise < numIndividuals; tortoise++) {
            for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                for (int threadVector = 0; threadVector < numThreads; threadVector++) {
                    weightingsSum[tortoise][comparisonTortoise] += weightingsThreads[threadVector][tortoise][comparisonTortoise];
                    pwpSum[tortoise][comparisonTortoise] += pwpThreads[threadVector][tortoise][comparisonTortoise];
                }
            }
        }
        std::cout << "Finished summing the threads vectors" << std::endl;\
        file.close(); // This is the binary file that holds all the read count data

        //////// Print out the final output to the pairwise pi file ////////
        std::ofstream pwpOUT (outFile);
        pwpOUT << "Sample1\tSample2\tPWP" << std::endl;
        int rowCounter = 0;
        if (!pwpOUT) {
            std::cerr << "Crap, " << outFile << "didn't open!" << std::endl;
        } else {
            for (int tortoise=0; tortoise < numIndividuals; tortoise++) {
                for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                    rowCounter++;

                    //std::cout << "Tortoise numbers: " << tortoise << " and " << comparisonTortoise << std::endl;
                    if (weightingsSum[tortoise][comparisonTortoise] > 0) {
                        /*
                        std::cout << weightings[tortoise][comparisonTortoise] << std::endl;
                        std::cout << pwp[tortoise][comparisonTortoise] / weightings[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::fixed;
                        std::cout << "Weightings for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << weightingsSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << "PWP for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << pwpSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::scientific;
                        */
                        pwpOUT << sampleLines[tortoise] << "\t" << sampleLines[comparisonTortoise] << "\t" << pwpSum[tortoise][comparisonTortoise] / weightingsSum[tortoise][comparisonTortoise] << std::endl;
                    } else {
                        pwpOUT << "NA" << std::endl;
                    }
                }
            }
        }
    } else {
        std::cout << "Unable to open file";
    }
    return 0;
}

int calcPWPforRange (unsigned long long startingLocus, unsigned long long endingLocus, int numIndividuals, std::vector<unsigned char>& mainReadCountVector, std::vector<std::vector<long double>>& threadPWP, std::vector<std::vector<unsigned long long int>>& threadWeightings) {
    //std::cout << "Calculating PWP for the following locus range: " << startingLocus + ((chunkCounter + 1) * numLoci * numThreads) << " to " << endingLocus + ((chunkCounter + 1) * numLoci * numThreads) << std::endl;
    for( unsigned long long locus = startingLocus; locus < endingLocus; locus++) {
        //std::cout << "Processing locus # " << locus << std::endl;
        //if (locus % 100000 == 0) {
        //    std::cout << locus << " loci processed through calcPWPfromBinaryFile" << std::endl;
        //}

        unsigned long long coverages[numIndividuals];
        long double *majorAlleleFreqs = new long double[numIndividuals]; // This will hold the major allele frequencies for that locus for each tortoise

        for( int tortoise = 0; tortoise < numIndividuals; tortoise++ ) {
            unsigned long long majorIndex = locus * (numIndividuals*2) + 2 * tortoise;
            unsigned long long minorIndex = locus * (numIndividuals*2) + 2 * tortoise + 1;

            coverages[tortoise] = int(mainReadCountVector[majorIndex]) + int(mainReadCountVector[minorIndex]); // Hold the coverages for each locus
            if ( coverages[tortoise] > 0 ) {
                majorAlleleFreqs[tortoise] = (long double)mainReadCountVector[majorIndex] / (long double)coverages[tortoise]; // Not necessarily an int, but could be 0 or 1

                if (coverages[tortoise] > 1) {
                    unsigned long long locusWeighting = (unsigned long long) (coverages[tortoise]*(coverages[tortoise]-1));
                    threadWeightings[tortoise][tortoise] += (unsigned long long)locusWeighting; // This is an integer--discrete number of reads

                    threadPWP[tortoise][tortoise] += (long double)(locusWeighting) * ((long double)2.0 * majorAlleleFreqs[tortoise] * ((long double)(coverages[tortoise]) - (long double)(mainReadCountVector[majorIndex])) / (long double)((coverages[tortoise])-(long double)1.0));
                }

                for( int comparisonTortoise = 0; comparisonTortoise < tortoise; comparisonTortoise++) {
                    if (coverages[comparisonTortoise] > 0) {
                        unsigned long long locusWeighting = (unsigned long long)coverages[tortoise] * (unsigned long long)(coverages[comparisonTortoise]);
                        threadWeightings[tortoise][comparisonTortoise] += locusWeighting;

                        threadPWP[tortoise][comparisonTortoise] += (long double)locusWeighting * (majorAlleleFreqs[tortoise] * ((long double)1.0-majorAlleleFreqs[comparisonTortoise]) + majorAlleleFreqs[comparisonTortoise] * ((long double)1.0-majorAlleleFreqs[tortoise]));
                    }
                }
            }
        }
        delete[] majorAlleleFreqs; // Needed to avoid memory leaks
    }
    //std::cout << "Finished thread ending on locus " << endingLocus + ((chunkCounter + 1) * numLoci * numThreads) << std::endl;
    return 0;
}

<|endoftext|>


<commit_before>//
//  calcPWP.cpp
//
//
//  Created by Evan McCartney-Melstad on 1/10/15.
//
//

#include "calcPWPchunks.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <thread>
#include <string>

int calcPWPfromBinaryFile (std::string binaryFile, unsigned long long int numLoci, const int numIndividuals, std::string outFile, int lociChunkSize, int numThreads) {

    std::cout << "Number of threads: " << numThreads << std::endl;
    std::streampos size;
    std::ifstream file (binaryFile, std::ios::in|std::ios::binary|std::ios::ate);

    if (file.is_open()) {
        size = file.tellg(); // Just a variable that shows position of stream--at end since ios::ate, so it's the file size. PROBABLY WON'T WORK FOR FILES LARGER THAN ~ 2GB!
        file.seekg (0, std::ios::beg); // Go back to the beginning of the file
        std::cout << "The total size of the file is " << size << "bytes. This corresponds to " << size/(numIndividuals*2) << " loci" << std::endl;

        unsigned long long int maxLocus;
        if (numLoci == 0) {
            maxLocus = (unsigned long long)(size/(numIndividuals*2));
        } else {
            maxLocus = numLoci;
        }

        std::cout << "Calculating divergence based on " << maxLocus << " total loci." << std::endl;

        // How many bytes to read in at one time (this number of loci will be split amongs numThreads threads, so it should be divisible exactly by numThreads. So the number of loci read in at a time will actually be numLoci*numThreads
        unsigned long long int lociChunkByteSize = (unsigned long long)lociChunkSize * numIndividuals * 2 * numThreads; // *
        int numFullChunks = (maxLocus*numIndividuals*2)/lociChunkByteSize; // Truncates answer to an integer
        unsigned long long remainingBytesAfterFullChunks = (maxLocus*numIndividuals*2) % lociChunkByteSize;

        std::cout << "Total number of chunks to run: " << numFullChunks + 1 << std::endl;

        /* We are going to split the loci between numThreads threads. Each thread will modify two multidimensional
         vectors of the forms std::vector< std::vector<long double> > pwp(numIndividuals, std::vector<long double>(numIndividuals,0))    and   std::vector< std::vector<unsigned long long int> > weightings(numIndividuals, std::vector<unsigned long long int>(numIndividuals,0))
         First, we'll generate all of these vectors, which apparently in C++ needs to be constructed of a
         vector of two-dimensional vectors...
         */
        std::vector<std::vector<std::vector<long double>>> pwpThreads(numThreads, std::vector<std::vector<long double>> (numIndividuals, std::vector<long double> (numIndividuals,0) ) ); //pwpThreads[0] is the first 2D array for the first thread, etc...
        std::vector<std::vector<std::vector<unsigned long long int>>> weightingsThreads(numThreads, std::vector<std::vector<unsigned long long int> > (numIndividuals, std::vector<unsigned long long int> (numIndividuals,0) ) );
        std::cout << "Initialized the 3d weighting and pwp vectors" << std::endl;

        //file.read((char*) &readCounts[0], size);

        // Read in the data in chunks, and process each chunk using numThreads threads

        int chunkCounter = 0;
        while (chunkCounter < numFullChunks) {
            std::cout << "Running chunk #" << chunkCounter << std::endl;
            std::vector<unsigned char> readCounts(lociChunkByteSize);
            file.read((char*) &readCounts[0], lociChunkByteSize);

            std::cout << "Number of bytes in the chunk vector: " << readCounts.size() << std::endl;

            std::vector<std::thread> threadsVec;
            for (int threadRunning = 0; threadRunning < numThreads; threadRunning++) {
                unsigned long long bytesPerThread = lociChunkByteSize / numThreads;
                std::vector<unsigned char> readCounts(bytesPerThread);
                file.read((char*) &readCounts[0], bytesPerThread);
                unsigned long long int lociPerThread = bytesPerThread / (numIndividuals*2);

                std::cout << "Got to the function call in main loop. Running thread # " << threadRunning << std::endl;

                threadsVec.push_back(std::thread(calcPWPforRange, numIndividuals, lociPerThread, std::ref(readCounts), std::ref(pwpThreads[threadRunning]), std::ref(weightingsThreads[threadRunning])));
            }

            // Wait on threads to finish
            for (int i = 0; i < numThreads; ++i) {
                threadsVec[i].join();
                std::cout << "Joined thread " << i << std::endl;
            }
            std::cout << "All threads completed running for chunk " << chunkCounter << " of " << numFullChunks + 1 << std::endl;
            chunkCounter++;
        }

        // That takes care of all the full-sized loci chunks, now deal with the remainder of loci
        std::vector<unsigned char> readCountsRemaining(remainingBytesAfterFullChunks);
        file.read((char*) &readCountsRemaining[0], remainingBytesAfterFullChunks);
        unsigned long long remainingLociAfterFullChunks = (remainingBytesAfterFullChunks/(numIndividuals*2));

        std::vector<std::thread> threadsVecRemaining;
        for (int threadRunning = 0; threadRunning < numThreads; threadRunning++) {
            std::cout << "Got to the function call in the remaining loci. Running thread # " << threadRunning << std::endl;

            threadsVecRemaining.push_back(std::thread(calcPWPforRange, numIndividuals, remainingLociAfterFullChunks, std::ref(readCountsRemaining), std::ref(pwpThreads[threadRunning]), std::ref(weightingsThreads[threadRunning])));
        }

        // Wait on threads to finish
        for (int i = 0; i < numThreads; ++i) {
            threadsVecRemaining[i].join();
            std::cout << "Joined thread " << i << std::endl;
        }
        std::cout << "All threads completed running for last chunk." << std::endl;

        // Now aggregate the results of the threads and print final results
        std::vector<std::vector<long double>> weightingsSum(numIndividuals, std::vector<long double>(numIndividuals,0));
        std::vector<std::vector<long double>> pwpSum(numIndividuals, std::vector<long double>(numIndividuals,0));

        for (int tortoise = 0; tortoise < numIndividuals; tortoise++) {
            for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                for (int threadVector = 0; threadVector < numThreads; threadVector++) {
                    weightingsSum[tortoise][comparisonTortoise] += weightingsThreads[threadVector][tortoise][comparisonTortoise];
                    pwpSum[tortoise][comparisonTortoise] += pwpThreads[threadVector][tortoise][comparisonTortoise];
                }
            }
        }
        std::cout << "Finished summing the threads vectors" << std::endl;\
        file.close(); // This is the binary file that holds all the read count data

        // Now print out the final output to the pairwise pi file:
        std::ofstream pwpOUT (outFile);
        int rowCounter = 0;
        if (!pwpOUT) {
            std::cerr << "Crap, " << outFile << "didn't open!" << std::endl;
        } else {
            for (int tortoise=0; tortoise < numIndividuals; tortoise++) {
                for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                    rowCounter++;

                    //std::cout << "Made it past the beginning of the last end for loop" << std::endl;
                    //std::cout << "Tortoise numbers: " << tortoise << " and " << comparisonTortoise << std::endl;
                    if (weightingsSum[tortoise][comparisonTortoise] > 0) {
                        //std::cout << weightings[tortoise][comparisonTortoise] << std::endl;
                        //std::cout << pwp[tortoise][comparisonTortoise] / weightings[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::fixed;
                        std::cout << "Weightings for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << weightingsSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << "PWP for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << pwpSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::scientific;
                        pwpOUT << pwpSum[tortoise][comparisonTortoise] / weightingsSum[tortoise][comparisonTortoise] << std::endl;
                    } else {
                        pwpOUT << "NA" << std::endl;
                    }
                }
            }
        }
    } else std::cout << "Unable to open file";

    return 0;
}

int calcPWPforRange (int numberIndividuals, unsigned long long int lociToCalc, std::vector<unsigned char>& mainReadCountVector, std::vector<std::vector<long double>>& threadPWP, std::vector<std::vector<unsigned long long int>>& threadWeightings) {

    std::cout << "Processing " << lociToCalc << " total loci" << std::endl;

    for( unsigned long long locus = 0; locus < lociToCalc; locus++) {
        //std::cout << "Processing locus # " << locus << std::endl;
        if (locus % 100000 == 0) {
            std::cout << locus << " loci processed through calcPWPfromBinaryFile" << std::endl;
        }

        unsigned long long coverages[numberIndividuals];
        long double *majorAlleleFreqs = new long double[numberIndividuals]; // This will hold the major allele frequencies for that locus for each tortoise

        for( int tortoise = 0; tortoise < numberIndividuals; tortoise++ ) {
            unsigned long long majorIndex = locus * (numberIndividuals*2) + 2 * tortoise;
            unsigned long long minorIndex = locus * (numberIndividuals*2) + 2 * tortoise + 1;

            coverages[tortoise] = int(mainReadCountVector[majorIndex]) + int(mainReadCountVector[minorIndex]); // Hold the coverages for each locus
            if ( coverages[tortoise] > 0 ) {
                majorAlleleFreqs[tortoise] = (long double)mainReadCountVector[majorIndex] / (long double)coverages[tortoise]; // Not necessarily an int, but could be 0 or 1

                if (coverages[tortoise] > 1) {
                    unsigned long long locusWeighting = (unsigned long long) (coverages[tortoise]*(coverages[tortoise]-1));
                    //unsigned long long locusWeighting = (unsigned long long) (coverages[tortoise]*(coverages[tortoise])); // Shift weightings to match the weightings of the inter-comparisons by removing the -1
                    threadWeightings[tortoise][tortoise] += (unsigned long long)locusWeighting; // This is an integer--discrete number of reads

                    threadPWP[tortoise][tortoise] += (long double)(locusWeighting) * ((long double)2.0 * majorAlleleFreqs[tortoise] * ((long double)(coverages[tortoise]) - (long double)(mainReadCountVector[majorIndex])) / (long double)((coverages[tortoise])-(long double)1.0));
                }

                for( int comparisonTortoise = 0; comparisonTortoise < tortoise; comparisonTortoise++) {
                    if (coverages[comparisonTortoise] > 0) {
                        unsigned long long locusWeighting = (unsigned long long)coverages[tortoise] * (unsigned long long)(coverages[comparisonTortoise]);
                        threadWeightings[tortoise][comparisonTortoise] += locusWeighting;

                        threadPWP[tortoise][comparisonTortoise] += (long double)locusWeighting * (majorAlleleFreqs[tortoise] * ((long double)1.0-majorAlleleFreqs[comparisonTortoise]) + majorAlleleFreqs[comparisonTortoise] * ((long double)1.0-majorAlleleFreqs[tortoise]));
                    }
                }
            }
        }
        delete[] majorAlleleFreqs; // Needed to avoid memory leaks
    }
    return 0;
}

<commit_msg>Minor changes<commit_after>//
//  calcPWP.cpp
//
//
//  Created by Evan McCartney-Melstad on 1/10/15.
//
//

#include "calcPWPchunks.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <thread>
#include <string>

int calcPWPfromBinaryFile (std::string binaryFile, unsigned long long int numLoci, const int numIndividuals, std::string outFile, int lociChunkSize, int numThreads) {

    std::cout << "Number of threads: " << numThreads << std::endl;
    std::streampos size;
    std::ifstream file (binaryFile, std::ios::in|std::ios::binary|std::ios::ate);

    if (file.is_open()) {
        size = file.tellg(); // Just a variable that shows position of stream--at end since ios::ate, so it's the file size. PROBABLY WON'T WORK FOR FILES LARGER THAN ~ 2GB!
        file.seekg (0, std::ios::beg); // Go back to the beginning of the file
        std::cout << "The total size of the file is " << size << "bytes. This corresponds to " << size/(numIndividuals*2) << " loci" << std::endl;

        unsigned long long int maxLocus;
        if (numLoci == 0) {
            maxLocus = (unsigned long long)(size/(numIndividuals*2));
        } else {
            maxLocus = numLoci;
        }

        std::cout << "Calculating divergence based on " << maxLocus << " total loci." << std::endl;

        // How many bytes to read in at one time (this number of loci will be split amongs numThreads threads, so it should be divisible exactly by numThreads. So the number of loci read in at a time will actually be numLoci*numThreads
        unsigned long long int lociChunkByteSize = (unsigned long long)lociChunkSize * numIndividuals * 2 * numThreads; // *
        int numFullChunks = (maxLocus*numIndividuals*2)/lociChunkByteSize; // Truncates answer to an integer
        unsigned long long remainingBytesAfterFullChunks = (maxLocus*numIndividuals*2) % lociChunkByteSize;

        std::cout << "Total number of chunks to run: " << numFullChunks + 1 << std::endl;

        /* We are going to split the loci between numThreads threads. Each thread will modify two multidimensional
         vectors of the forms std::vector< std::vector<long double> > pwp(numIndividuals, std::vector<long double>(numIndividuals,0))    and   std::vector< std::vector<unsigned long long int> > weightings(numIndividuals, std::vector<unsigned long long int>(numIndividuals,0))
         First, we'll generate all of these vectors, which apparently in C++ needs to be constructed of a
         vector of two-dimensional vectors...
         */
        std::vector<std::vector<std::vector<long double>>> pwpThreads(numThreads, std::vector<std::vector<long double>> (numIndividuals, std::vector<long double> (numIndividuals,0) ) ); //pwpThreads[0] is the first 2D array for the first thread, etc...
        std::vector<std::vector<std::vector<unsigned long long int>>> weightingsThreads(numThreads, std::vector<std::vector<unsigned long long int> > (numIndividuals, std::vector<unsigned long long int> (numIndividuals,0) ) );
        std::cout << "Initialized the 3d weighting and pwp vectors" << std::endl;

        //file.read((char*) &readCounts[0], size);

        // Read in the data in chunks, and process each chunk using numThreads threads

        int chunkCounter = 0;
        while (chunkCounter < numFullChunks) {
            std::cout << "Running chunk #" << chunkCounter << std::endl;
            std::vector<unsigned char> readCounts(lociChunkByteSize);
            file.read((char*) &readCounts[0], lociChunkByteSize);

            std::cout << "Number of bytes in the chunk vector: " << readCounts.size() << std::endl;

            std::vector<std::thread> threadsVec;
            for (int threadRunning = 0; threadRunning < numThreads; threadRunning++) {
                unsigned long long bytesPerThread = lociChunkByteSize / numThreads;
                std::vector<unsigned char> readCounts(bytesPerThread);
                file.read((char*) &readCounts[0], bytesPerThread);
                unsigned long long int lociPerThread = bytesPerThread / (numIndividuals*2);

                std::cout << "Got to the function call in main loop. Running thread # " << threadRunning << std::endl;

                threadsVec.push_back(std::thread(calcPWPforRange, numIndividuals, lociPerThread, std::ref(readCounts), std::ref(pwpThreads[threadRunning]), std::ref(weightingsThreads[threadRunning])));
            }

            // Wait on threads to finish
            for (int i = 0; i < numThreads; ++i) {
                threadsVec[i].join();
                std::cout << "Joined thread " << i << std::endl;
            }
            std::cout << "All threads completed running for chunk " << chunkCounter << " of " << numFullChunks + 1 << std::endl;
            chunkCounter++;
        }

        // That takes care of all the full-sized loci chunks, now deal with the remainder of loci
        std::vector<unsigned char> readCountsRemaining(remainingBytesAfterFullChunks);
        file.read((char*) &readCountsRemaining[0], remainingBytesAfterFullChunks);
        unsigned long long remainingLociAfterFullChunks = (remainingBytesAfterFullChunks/(numIndividuals*2));

        std::vector<std::thread> threadsVecRemaining;
        for (int threadRunning = 0; threadRunning < numThreads; threadRunning++) {
            std::cout << "Got to the function call in the remaining loci. Running thread # " << threadRunning << std::endl;

            threadsVecRemaining.push_back(std::thread(calcPWPforRange, numIndividuals, remainingLociAfterFullChunks, std::ref(readCountsRemaining), std::ref(pwpThreads[threadRunning]), std::ref(weightingsThreads[threadRunning])));
        }

        // Wait on threads to finish
        for (int i = 0; i < numThreads; ++i) {
            threadsVecRemaining[i].join();
            std::cout << "Joined thread " << i << std::endl;
        }
        std::cout << "All threads completed running for last chunk." << std::endl;

        // Now aggregate the results of the threads and print final results
        std::vector<std::vector<long double>> weightingsSum(numIndividuals, std::vector<long double>(numIndividuals,0));
        std::vector<std::vector<long double>> pwpSum(numIndividuals, std::vector<long double>(numIndividuals,0));

        for (int tortoise = 0; tortoise < numIndividuals; tortoise++) {
            for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                for (int threadVector = 0; threadVector < numThreads; threadVector++) {
                    weightingsSum[tortoise][comparisonTortoise] += weightingsThreads[threadVector][tortoise][comparisonTortoise];
                    pwpSum[tortoise][comparisonTortoise] += pwpThreads[threadVector][tortoise][comparisonTortoise];
                }
            }
        }
        std::cout << "Finished summing the threads vectors" << std::endl;\
        file.close(); // This is the binary file that holds all the read count data

        // Now print out the final output to the pairwise pi file:
        std::ofstream pwpOUT (outFile);
        int rowCounter = 0;
        if (!pwpOUT) {
            std::cerr << "Crap, " << outFile << "didn't open!" << std::endl;
        } else {
            for (int tortoise=0; tortoise < numIndividuals; tortoise++) {
                for (int comparisonTortoise = 0; comparisonTortoise <= tortoise; comparisonTortoise++) {
                    rowCounter++;

                    //std::cout << "Made it past the beginning of the last end for loop" << std::endl;
                    //std::cout << "Tortoise numbers: " << tortoise << " and " << comparisonTortoise << std::endl;
                    if (weightingsSum[tortoise][comparisonTortoise] > 0) {
                        //std::cout << weightings[tortoise][comparisonTortoise] << std::endl;
                        //std::cout << pwp[tortoise][comparisonTortoise] / weightings[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::fixed;
                        std::cout << "Weightings for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << weightingsSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << "PWP for tortoise " << tortoise << " and comparisonTortoise " << comparisonTortoise << " : " << pwpSum[tortoise][comparisonTortoise] << std::endl;
                        std::cout << std::scientific;
                        pwpOUT << pwpSum[tortoise][comparisonTortoise] / weightingsSum[tortoise][comparisonTortoise] << std::endl;
                    } else {
                        pwpOUT << "NA" << std::endl;
                    }
                }
            }
        }
    } else std::cout << "Unable to open file";

    return 0;
}

int calcPWPforRange (int numberIndividuals, unsigned long long int lociToCalc, std::vector<unsigned char>& mainReadCountVector, std::vector<std::vector<long double>>& threadPWP, std::vector<std::vector<unsigned long long int>>& threadWeightings) {

    std::cout << "Processing " << lociToCalc << " total loci" << std::endl;

    for( unsigned long long locus = 0; locus < lociToCalc; locus++) {
        std::cout << "Working on locus " << locus << std::endl;
        //std::cout << "Processing locus # " << locus << std::endl;
        if (locus % 100000 == 0) {
            std::cout << locus << " loci processed through calcPWPfromBinaryFile" << std::endl;
        }

        std::cout << "Made it to line 169" << std::endl;

        unsigned long long coverages[numberIndividuals];
        long double *majorAlleleFreqs = new long double[numberIndividuals]; // This will hold the major allele frequencies for that locus for each tortoise
        std::cout << "Made it to line 173" << std::endl;

        for( int tortoise = 0; tortoise < numberIndividuals; tortoise++ ) {
            unsigned long long majorIndex = locus * (numberIndividuals*2) + 2 * tortoise;
            unsigned long long minorIndex = locus * (numberIndividuals*2) + 2 * tortoise + 1;
            std::cout << "Made it to line 178 for tortoise " << tortoise <<

            coverages[tortoise] = int(mainReadCountVector[majorIndex]) + int(mainReadCountVector[minorIndex]); // Hold the coverages for each locus
            std::cout << "Made it to line 182 for tortoise" << tortoise << " and locus " << locus << std::endl;
            if ( coverages[tortoise] > 0 ) {
                majorAlleleFreqs[tortoise] = (long double)mainReadCountVector[majorIndex] / (long double)coverages[tortoise]; // Not necessarily an int, but could be 0 or 1
                std::cout << "Made it to line 185 for tortoise" << tortoise << " and locus " << locus << std::endl;
                if (coverages[tortoise] > 1) {
                    unsigned long long locusWeighting = (unsigned long long) (coverages[tortoise]*(coverages[tortoise]-1));
                    //unsigned long long locusWeighting = (unsigned long long) (coverages[tortoise]*(coverages[tortoise])); // Shift weightings to match the weightings of the inter-comparisons by removing the -1
                    threadWeightings[tortoise][tortoise] += (unsigned long long)locusWeighting; // This is an integer--discrete number of reads
                    std::cout << "Made it to line 190 for tortoise" << tortoise << " and locus " << locus << std::endl;
                    threadPWP[tortoise][tortoise] += (long double)(locusWeighting) * ((long double)2.0 * majorAlleleFreqs[tortoise] * ((long double)(coverages[tortoise]) - (long double)(mainReadCountVector[majorIndex])) / (long double)((coverages[tortoise])-(long double)1.0));
                }
                std::cout << "Made it to line 193 for tortoise" << tortoise << " and locus " << locus << std::endl;
                for( int comparisonTortoise = 0; comparisonTortoise < tortoise; comparisonTortoise++) {
                    if (coverages[comparisonTortoise] > 0) {
                        unsigned long long locusWeighting = (unsigned long long)coverages[tortoise] * (unsigned long long)(coverages[comparisonTortoise]);
                        threadWeightings[tortoise][comparisonTortoise] += locusWeighting;

                        threadPWP[tortoise][comparisonTortoise] += (long double)locusWeighting * (majorAlleleFreqs[tortoise] * ((long double)1.0-majorAlleleFreqs[comparisonTortoise]) + majorAlleleFreqs[comparisonTortoise] * ((long double)1.0-majorAlleleFreqs[tortoise]));
                    }
                }
            }
        }
        delete[] majorAlleleFreqs; // Needed to avoid memory leaks
    }
    return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2020.  All rights reserved
 */
#include "../../../StroikaPreComp.h"

#include "Jenkins.h"

using std::byte;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Cryptography;
using namespace Stroika::Foundation::Cryptography::Digest;

namespace {
    /*
     *  Implementation based on text from http://en.wikipedia.org/wiki/Jenkins_hash_function on 2013-05-30
     */
    inline void DoMore_ (uint32_t* hash2Update, const byte* from, const byte* to)
    {
        RequireNotNull (hash2Update);
        uint32_t hash = (*hash2Update);
        for (const byte* bi = from; bi != to; ++bi) {
            hash += to_integer<uint8_t> (*bi);
            hash += (hash << 10);
            hash ^= (hash >> 6);
        }
        (*hash2Update) = hash;
    }
    inline void DoEnd_ (uint32_t* hash2Update)
    {
        RequireNotNull (hash2Update);
        uint32_t hash = (*hash2Update);
        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);
        (*hash2Update) = hash;
    }
}

Digester<Algorithm::Jenkins, uint32_t>::ReturnType Digester<Algorithm::Jenkins, uint32_t>::ComputeDigest (const Memory::BLOB& from)
{
    return Digester<Algorithm::Jenkins, uint32_t>{}.operator() (from.begin (), from.end ());
}

Digester<Algorithm::Jenkins, uint32_t>::ReturnType Digester<Algorithm::Jenkins, uint32_t>::operator() (const Streams::InputStream<std::byte>::Ptr& from) const
{
    uint32_t hash = 0;
    while (true) {
        byte   buf[32 * 1024];
        size_t n = from.Read (std::begin (buf), std::end (buf));
        Assert (n <= sizeof (buf));
        if (n == 0) {
            break;
        }
        DoMore_ (&hash, std::begin (buf), std::begin (buf) + n);
    }
    DoEnd_ (&hash);
    return hash;
}

Digester<Algorithm::Jenkins, uint32_t>::ReturnType Digester<Algorithm::Jenkins, uint32_t>::operator() (const std::byte* from, const std::byte* to) const
{
    Require (from == to or from != nullptr);
    Require (from == to or to != nullptr);
    uint32_t hash = 0;
    DoMore_ (&hash, from, to);
    DoEnd_ (&hash);
    return hash;
}
<commit_msg>fixed typo<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2020.  All rights reserved
 */
#include "../../../StroikaPreComp.h"

#include "Jenkins.h"

using std::byte;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Cryptography;
using namespace Stroika::Foundation::Cryptography::Digest;

namespace {
    /*
     *  Implementation based on text from http://en.wikipedia.org/wiki/Jenkins_hash_function on 2013-05-30
     */
    inline void DoMore_ (uint32_t* hash2Update, const byte* from, const byte* to)
    {
        RequireNotNull (hash2Update);
        uint32_t hash = (*hash2Update);
        for (const byte* bi = from; bi != to; ++bi) {
            hash += to_integer<uint8_t> (*bi);
            hash += (hash << 10);
            hash ^= (hash >> 6);
        }
        (*hash2Update) = hash;
    }
    inline void DoEnd_ (uint32_t* hash2Update)
    {
        RequireNotNull (hash2Update);
        uint32_t hash = (*hash2Update);
        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);
        (*hash2Update) = hash;
    }
}

Digester<Algorithm::Jenkins, uint32_t>::ReturnType Digester<Algorithm::Jenkins, uint32_t>::operator() (const Streams::InputStream<std::byte>::Ptr& from) const
{
    uint32_t hash = 0;
    while (true) {
        byte   buf[32 * 1024];
        size_t n = from.Read (std::begin (buf), std::end (buf));
        Assert (n <= sizeof (buf));
        if (n == 0) {
            break;
        }
        DoMore_ (&hash, std::begin (buf), std::begin (buf) + n);
    }
    DoEnd_ (&hash);
    return hash;
}

Digester<Algorithm::Jenkins, uint32_t>::ReturnType Digester<Algorithm::Jenkins, uint32_t>::operator() (const std::byte* from, const std::byte* to) const
{
    Require (from == to or from != nullptr);
    Require (from == to or to != nullptr);
    uint32_t hash = 0;
    DoMore_ (&hash, from, to);
    DoEnd_ (&hash);
    return hash;
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmljscheck.h"
#include "qmljsbind.h"
#include "qmljsinterpreter.h"
#include "qmljsevaluate.h"
#include "parser/qmljsast_p.h"

#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtGui/QColor>
#include <QtGui/QApplication>

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::Interpreter;

namespace {

class AssignmentCheck : public ValueVisitor
{
public:
    DiagnosticMessage operator()(
            const SourceLocation &location,
            const Interpreter::Value *lhsValue,
            const Interpreter::Value *rhsValue,
            ExpressionNode *ast)
    {
        _message = DiagnosticMessage(DiagnosticMessage::Error, location, QString());
        _rhsValue = rhsValue;
        _ast = ast;

        if (lhsValue)
            lhsValue->accept(this);

        return _message;
    }

    virtual void visit(const NumberValue *)
    {
        // ### Consider enums: elide: "ElideLeft" is valid, but currently elide is a NumberValue.
        if (/*cast<StringLiteral *>(_ast)
                ||*/ _ast->kind == Node::Kind_TrueLiteral
                || _ast->kind == Node::Kind_FalseLiteral) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "numerical value expected");
        }
    }

    virtual void visit(const BooleanValue *)
    {
        UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);

        if (cast<StringLiteral *>(_ast)
                || cast<NumericLiteral *>(_ast)
                || (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression))) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "boolean value expected");
        }
    }

    virtual void visit(const StringValue *)
    {
        UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);

        if (cast<NumericLiteral *>(_ast)
                || (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression))
                || _ast->kind == Node::Kind_TrueLiteral
                || _ast->kind == Node::Kind_FalseLiteral) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "string value expected");
        }
    }

    virtual void visit(const EasingCurveNameValue *)
    {
        if (StringLiteral *stringLiteral = cast<StringLiteral *>(_ast)) {
            const QString curveName = stringLiteral->value->asString();

            if (!EasingCurveNameValue::curveNames().contains(curveName)) {
                _message.message = QCoreApplication::translate("QmlJS::Check", "unknown easing-curve name");
            }
        } else if (_rhsValue->asUndefinedValue()) {
            _message.kind = DiagnosticMessage::Warning;
            _message.message = QCoreApplication::translate("QmlJS::Check", "value might be 'undefined'");
        } else if (! _rhsValue->asStringValue()) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "easing-curve name is not a string");
        }
    }

    virtual void visit(const ColorValue *)
    {
        if (StringLiteral *stringLiteral = cast<StringLiteral *>(_ast)) {
            const QString colorString = stringLiteral->value->asString();

            bool ok = true;
            if (colorString.size() == 9 && colorString.at(0) == QLatin1Char('#')) {
                // #rgba
                for (int i = 1; i < 9; ++i) {
                    const QChar c = colorString.at(i);
                    if ((c >= QLatin1Char('0') && c <= QLatin1Char('9'))
                        || (c >= QLatin1Char('a') && c <= QLatin1Char('f'))
                        || (c >= QLatin1Char('A') && c <= QLatin1Char('F')))
                        continue;
                    ok = false;
                    break;
                }
            } else {
                ok = QColor::isValidColor(colorString);
            }
            if (!ok)
                _message.message = QCoreApplication::translate("QmlJS::Check", "not a valid color");
        } else {
            visit((StringValue *)0);
        }
    }

    virtual void visit(const AnchorLineValue *)
    {
        if (! (_rhsValue->asAnchorLineValue() || _rhsValue->asUndefinedValue()))
            _message.message = QCoreApplication::translate("QmlJS::Check", "expected anchor line");
    }

    DiagnosticMessage _message;
    const Value *_rhsValue;
    ExpressionNode *_ast;
};

} // end of anonymous namespace

Check::Check(Document::Ptr doc, const Snapshot &snapshot, const QStringList &importPaths)
    : _doc(doc)
    , _snapshot(snapshot)
    , _context(&_engine)
    , _link(&_context, doc, snapshot, importPaths)
    , _scopeBuilder(doc, &_context)
    , _ignoreTypeErrors(_context.documentImportsPlugins(_doc.data()))
{
}

Check::~Check()
{
}

QList<DiagnosticMessage> Check::operator()()
{
    _messages.clear();
    Node::accept(_doc->ast(), this);
    _messages.append(_link.diagnosticMessages());
    return _messages;
}

bool Check::visit(UiProgram *)
{
    return true;
}

bool Check::visit(UiObjectDefinition *ast)
{
    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

bool Check::visit(UiObjectBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
                           UiObjectInitializer *initializer)
{
    // If the 'typeId' starts with a lower-case letter, it doesn't define
    // a new object instance. For instance: anchors { ... }
    if (typeId->name->asString().at(0).isLower() && ! typeId->next) {
        checkScopeObjectMember(typeId);
        // ### don't give up!
        return;
    }

    _scopeBuilder.push(ast);

    if (! _context.lookupType(_doc.data(), typeId)) {
        if (! _ignoreTypeErrors)
            error(typeId->identifierToken,
                  QCoreApplication::translate("QmlJS::Check", "unknown type"));
        // suppress subsequent errors about scope object lookup by clearing
        // the scope object list
        // ### todo: better way?
        _context.scopeChain().qmlScopeObjects.clear();
        _context.scopeChain().update();
    }

    Node::accept(initializer, this);

    _scopeBuilder.pop();
}

bool Check::visit(UiScriptBinding *ast)
{
    // special case for id property
    if (ast->qualifiedId->name->asString() == QLatin1String("id") && ! ast->qualifiedId->next) {
        if (! ast->statement)
            return false;

        const SourceLocation loc = locationFromRange(ast->statement->firstSourceLocation(),
                                                     ast->statement->lastSourceLocation());

        ExpressionStatement *expStmt = cast<ExpressionStatement *>(ast->statement);
        if (!expStmt) {
            error(loc, QCoreApplication::translate("QmlJS::Check", "expected id"));
            return false;
        }

        QString id;
        if (IdentifierExpression *idExp = cast<IdentifierExpression *>(expStmt->expression)) {
            id = idExp->name->asString();
        } else if (StringLiteral *strExp = cast<StringLiteral *>(expStmt->expression)) {
            id = strExp->value->asString();
            warning(loc, QCoreApplication::translate("QmlJS::Check", "using string literals for ids is discouraged"));
        } else {
            error(loc, QCoreApplication::translate("QmlJS::Check", "expected id"));
            return false;
        }

        if (id.isEmpty() || ! id[0].isLower()) {
            error(loc, QCoreApplication::translate("QmlJS::Check", "ids must be lower case"));
            return false;
        }
    }

    const Value *lhsValue = checkScopeObjectMember(ast->qualifiedId);
    if (lhsValue) {
        // ### Fix the evaluator to accept statements!
        if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(ast->statement)) {
            ExpressionNode *expr = expStmt->expression;

            Evaluate evaluator(&_context);
            const Value *rhsValue = evaluator(expr);

            const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(),
                                                         expStmt->lastSourceLocation());
            AssignmentCheck assignmentCheck;
            DiagnosticMessage message = assignmentCheck(loc, lhsValue, rhsValue, expr);
            if (! message.message.isEmpty())
                _messages += message;
        }

    }

    return true;
}

bool Check::visit(UiArrayBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    return true;
}

/// When something is changed here, also change ReadingContext::lookupProperty in
/// texttomodelmerger.cpp
/// ### Maybe put this into the context as a helper method.
const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
{
    QList<const ObjectValue *> scopeObjects = _context.scopeChain().qmlScopeObjects;
    if (scopeObjects.isEmpty())
        return 0;

    if (! id)
        return 0; // ### error?

    if (! id->name) // possible after error recovery
        return 0;

    QString propertyName = id->name->asString();

    if (propertyName == QLatin1String("id") && ! id->next)
        return 0; // ### should probably be a special value

    // attached properties
    bool isAttachedProperty = false;
    if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
        isAttachedProperty = true;
        scopeObjects += _context.scopeChain().qmlTypes;
    }

    if (scopeObjects.isEmpty())
        return 0;

    // global lookup for first part of id
    const Value *value = 0;
    for (int i = scopeObjects.size() - 1; i >= 0; --i) {
        value = scopeObjects[i]->lookupMember(propertyName, &_context);
        if (value)
            break;
    }
    if (!value) {
        error(id->identifierToken,
              QCoreApplication::translate("QmlJS::Check", "'%1' is not a valid property name").arg(propertyName));
    }

    // can't look up members for attached properties
    if (isAttachedProperty)
        return 0;

    // member lookup
    const UiQualifiedId *idPart = id;
    while (idPart->next) {
        const ObjectValue *objectValue = value_cast<const ObjectValue *>(value);
        if (! objectValue) {
            error(idPart->identifierToken,
                  QCoreApplication::translate("QmlJS::Check", "'%1' does not have members").arg(propertyName));
            return 0;
        }

        if (! idPart->next->name) {
            // somebody typed "id." and error recovery still gave us a valid tree,
            // so just bail out here.
            return 0;
        }

        idPart = idPart->next;
        propertyName = idPart->name->asString();

        value = objectValue->lookupMember(propertyName, &_context);
        if (! value) {
            error(idPart->identifierToken,
                  QCoreApplication::translate("QmlJS::Check", "'%1' is not a member of '%2'").arg(
                          propertyName, objectValue->className()));
            return 0;
        }
    }

    return value;
}

void Check::error(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
}

void Check::warning(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
}

SourceLocation Check::locationFromRange(const SourceLocation &start,
                                        const SourceLocation &end)
{
    return SourceLocation(start.offset,
                          end.end() - start.begin(),
                          start.startLine,
                          start.startColumn);
}
<commit_msg>QmlJS: Allow numbers to be assigned to easing.type.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmljscheck.h"
#include "qmljsbind.h"
#include "qmljsinterpreter.h"
#include "qmljsevaluate.h"
#include "parser/qmljsast_p.h"

#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtGui/QColor>
#include <QtGui/QApplication>

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::Interpreter;

namespace {

class AssignmentCheck : public ValueVisitor
{
public:
    DiagnosticMessage operator()(
            const SourceLocation &location,
            const Interpreter::Value *lhsValue,
            const Interpreter::Value *rhsValue,
            ExpressionNode *ast)
    {
        _message = DiagnosticMessage(DiagnosticMessage::Error, location, QString());
        _rhsValue = rhsValue;
        _ast = ast;

        if (lhsValue)
            lhsValue->accept(this);

        return _message;
    }

    virtual void visit(const NumberValue *)
    {
        // ### Consider enums: elide: "ElideLeft" is valid, but currently elide is a NumberValue.
        if (/*cast<StringLiteral *>(_ast)
                ||*/ _ast->kind == Node::Kind_TrueLiteral
                || _ast->kind == Node::Kind_FalseLiteral) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "numerical value expected");
        }
    }

    virtual void visit(const BooleanValue *)
    {
        UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);

        if (cast<StringLiteral *>(_ast)
                || cast<NumericLiteral *>(_ast)
                || (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression))) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "boolean value expected");
        }
    }

    virtual void visit(const StringValue *)
    {
        UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);

        if (cast<NumericLiteral *>(_ast)
                || (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression))
                || _ast->kind == Node::Kind_TrueLiteral
                || _ast->kind == Node::Kind_FalseLiteral) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "string value expected");
        }
    }

    virtual void visit(const EasingCurveNameValue *)
    {
        if (StringLiteral *stringLiteral = cast<StringLiteral *>(_ast)) {
            const QString curveName = stringLiteral->value->asString();

            if (!EasingCurveNameValue::curveNames().contains(curveName)) {
                _message.message = QCoreApplication::translate("QmlJS::Check", "unknown easing-curve name");
            }
        } else if (_rhsValue->asUndefinedValue()) {
            _message.kind = DiagnosticMessage::Warning;
            _message.message = QCoreApplication::translate("QmlJS::Check", "value might be 'undefined'");
        } else if (! _rhsValue->asStringValue() && ! _rhsValue->asNumberValue()) {
            _message.message = QCoreApplication::translate("QmlJS::Check", "easing-curve name is not a string or number");
        }
    }

    virtual void visit(const ColorValue *)
    {
        if (StringLiteral *stringLiteral = cast<StringLiteral *>(_ast)) {
            const QString colorString = stringLiteral->value->asString();

            bool ok = true;
            if (colorString.size() == 9 && colorString.at(0) == QLatin1Char('#')) {
                // #rgba
                for (int i = 1; i < 9; ++i) {
                    const QChar c = colorString.at(i);
                    if ((c >= QLatin1Char('0') && c <= QLatin1Char('9'))
                        || (c >= QLatin1Char('a') && c <= QLatin1Char('f'))
                        || (c >= QLatin1Char('A') && c <= QLatin1Char('F')))
                        continue;
                    ok = false;
                    break;
                }
            } else {
                ok = QColor::isValidColor(colorString);
            }
            if (!ok)
                _message.message = QCoreApplication::translate("QmlJS::Check", "not a valid color");
        } else {
            visit((StringValue *)0);
        }
    }

    virtual void visit(const AnchorLineValue *)
    {
        if (! (_rhsValue->asAnchorLineValue() || _rhsValue->asUndefinedValue()))
            _message.message = QCoreApplication::translate("QmlJS::Check", "expected anchor line");
    }

    DiagnosticMessage _message;
    const Value *_rhsValue;
    ExpressionNode *_ast;
};

} // end of anonymous namespace

Check::Check(Document::Ptr doc, const Snapshot &snapshot, const QStringList &importPaths)
    : _doc(doc)
    , _snapshot(snapshot)
    , _context(&_engine)
    , _link(&_context, doc, snapshot, importPaths)
    , _scopeBuilder(doc, &_context)
    , _ignoreTypeErrors(_context.documentImportsPlugins(_doc.data()))
{
}

Check::~Check()
{
}

QList<DiagnosticMessage> Check::operator()()
{
    _messages.clear();
    Node::accept(_doc->ast(), this);
    _messages.append(_link.diagnosticMessages());
    return _messages;
}

bool Check::visit(UiProgram *)
{
    return true;
}

bool Check::visit(UiObjectDefinition *ast)
{
    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

bool Check::visit(UiObjectBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
                           UiObjectInitializer *initializer)
{
    // If the 'typeId' starts with a lower-case letter, it doesn't define
    // a new object instance. For instance: anchors { ... }
    if (typeId->name->asString().at(0).isLower() && ! typeId->next) {
        checkScopeObjectMember(typeId);
        // ### don't give up!
        return;
    }

    _scopeBuilder.push(ast);

    if (! _context.lookupType(_doc.data(), typeId)) {
        if (! _ignoreTypeErrors)
            error(typeId->identifierToken,
                  QCoreApplication::translate("QmlJS::Check", "unknown type"));
        // suppress subsequent errors about scope object lookup by clearing
        // the scope object list
        // ### todo: better way?
        _context.scopeChain().qmlScopeObjects.clear();
        _context.scopeChain().update();
    }

    Node::accept(initializer, this);

    _scopeBuilder.pop();
}

bool Check::visit(UiScriptBinding *ast)
{
    // special case for id property
    if (ast->qualifiedId->name->asString() == QLatin1String("id") && ! ast->qualifiedId->next) {
        if (! ast->statement)
            return false;

        const SourceLocation loc = locationFromRange(ast->statement->firstSourceLocation(),
                                                     ast->statement->lastSourceLocation());

        ExpressionStatement *expStmt = cast<ExpressionStatement *>(ast->statement);
        if (!expStmt) {
            error(loc, QCoreApplication::translate("QmlJS::Check", "expected id"));
            return false;
        }

        QString id;
        if (IdentifierExpression *idExp = cast<IdentifierExpression *>(expStmt->expression)) {
            id = idExp->name->asString();
        } else if (StringLiteral *strExp = cast<StringLiteral *>(expStmt->expression)) {
            id = strExp->value->asString();
            warning(loc, QCoreApplication::translate("QmlJS::Check", "using string literals for ids is discouraged"));
        } else {
            error(loc, QCoreApplication::translate("QmlJS::Check", "expected id"));
            return false;
        }

        if (id.isEmpty() || ! id[0].isLower()) {
            error(loc, QCoreApplication::translate("QmlJS::Check", "ids must be lower case"));
            return false;
        }
    }

    const Value *lhsValue = checkScopeObjectMember(ast->qualifiedId);
    if (lhsValue) {
        // ### Fix the evaluator to accept statements!
        if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(ast->statement)) {
            ExpressionNode *expr = expStmt->expression;

            Evaluate evaluator(&_context);
            const Value *rhsValue = evaluator(expr);

            const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(),
                                                         expStmt->lastSourceLocation());
            AssignmentCheck assignmentCheck;
            DiagnosticMessage message = assignmentCheck(loc, lhsValue, rhsValue, expr);
            if (! message.message.isEmpty())
                _messages += message;
        }

    }

    return true;
}

bool Check::visit(UiArrayBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    return true;
}

/// When something is changed here, also change ReadingContext::lookupProperty in
/// texttomodelmerger.cpp
/// ### Maybe put this into the context as a helper method.
const Value *Check::checkScopeObjectMember(const UiQualifiedId *id)
{
    QList<const ObjectValue *> scopeObjects = _context.scopeChain().qmlScopeObjects;
    if (scopeObjects.isEmpty())
        return 0;

    if (! id)
        return 0; // ### error?

    if (! id->name) // possible after error recovery
        return 0;

    QString propertyName = id->name->asString();

    if (propertyName == QLatin1String("id") && ! id->next)
        return 0; // ### should probably be a special value

    // attached properties
    bool isAttachedProperty = false;
    if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
        isAttachedProperty = true;
        scopeObjects += _context.scopeChain().qmlTypes;
    }

    if (scopeObjects.isEmpty())
        return 0;

    // global lookup for first part of id
    const Value *value = 0;
    for (int i = scopeObjects.size() - 1; i >= 0; --i) {
        value = scopeObjects[i]->lookupMember(propertyName, &_context);
        if (value)
            break;
    }
    if (!value) {
        error(id->identifierToken,
              QCoreApplication::translate("QmlJS::Check", "'%1' is not a valid property name").arg(propertyName));
    }

    // can't look up members for attached properties
    if (isAttachedProperty)
        return 0;

    // member lookup
    const UiQualifiedId *idPart = id;
    while (idPart->next) {
        const ObjectValue *objectValue = value_cast<const ObjectValue *>(value);
        if (! objectValue) {
            error(idPart->identifierToken,
                  QCoreApplication::translate("QmlJS::Check", "'%1' does not have members").arg(propertyName));
            return 0;
        }

        if (! idPart->next->name) {
            // somebody typed "id." and error recovery still gave us a valid tree,
            // so just bail out here.
            return 0;
        }

        idPart = idPart->next;
        propertyName = idPart->name->asString();

        value = objectValue->lookupMember(propertyName, &_context);
        if (! value) {
            error(idPart->identifierToken,
                  QCoreApplication::translate("QmlJS::Check", "'%1' is not a member of '%2'").arg(
                          propertyName, objectValue->className()));
            return 0;
        }
    }

    return value;
}

void Check::error(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
}

void Check::warning(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
}

SourceLocation Check::locationFromRange(const SourceLocation &start,
                                        const SourceLocation &end)
{
    return SourceLocation(start.offset,
                          end.end() - start.begin(),
                          start.startLine,
                          start.startColumn);
}
<|endoftext|>