def constructDT(gpsPoints, testPhones):
    
    reload(tripActivitySeparatorMongo)
    reload(modeChainSeparatorMongo)

    minDuration, maxRadius, minSamplingRate, gpsAccuracyThreshold = 360000, 50, 300000, 200
    minSeparationDistance, minSeparationTime = 100, 360000
    maxWalkSpeed, maxWalkAcceleration, minSegmentDuration, minSegmentLength = 5, 1620, 90000, 200
    hcrThreshold, srThreshold, vcrTheshold = 19, 7.6, 0.26
    
    modeData = []

    for testPhone in testPhones:
        
        print 'Processing data for ' + str(testPhone)
        try:
            query = {'phNum': testPhone}
            projection = {'_id': 0, 'gpsReading': 1, 'epochTime': 1, 'groundTruth': 1, 'movesTime': 1}
            gpsTraces = list(gpsPoints.find(query, projection).sort('epochTime'))
    
            trips, activities, holes = tripActivitySeparatorMongo.inferTripActivity(gpsTraces, minDuration, 
                    maxRadius, minSeparationDistance, minSeparationTime, minSamplingRate, gpsAccuracyThreshold)
            
            for trip in trips:
                modeChains = modeChainSeparatorMongo.inferModeChain(gpsTraces, trip, maxWalkSpeed, maxWalkAcceleration, 
                        minSegmentDuration, minSegmentLength, gpsAccuracyThreshold)
                determineModes(modeChains, modeData, gpsTraces, hcrThreshold, srThreshold, vcrTheshold, minSamplingRate)
        except:
            print "Unexpected error during inference:", sys.exc_info()[0]
            pass

    return modeData
def addActivities(gpsPoints, segments, testPhones):

    reload(tripActivitySeparatorMongo)
    minDuration, maxRadius, minSamplingRate, gpsAccuracyThreshold = 360000, 50, 300000, 200
    minSeparationDistance, minSeparationTime = 100, 360000
    
    for testPhone in testPhones:
        
        print 'Processing data for ' + str(testPhone)
        query = {'phNum': testPhone}
        projection = {'_id': 1, 'gpsReading': 1, 'epochTime': 1, 'groundTruth': 1, 'movesTime': 1}
        gpsTraces = list(gpsPoints.find(query, projection).sort('epochTime'))
        
        purposes = list(gpsPoints.distinct('groundTruth.purpose'))    
        trips, activities, holes = tripActivitySeparatorMongo.inferTripActivity(gpsTraces, minDuration, maxRadius, 
                minSeparationDistance, minSeparationTime, minSamplingRate, gpsAccuracyThreshold)
        
        for activity in activities:

            trackPoints, wiFiNetwork, location = [], [], []
            purposeCount = {}
            for purpose in purposes:
                purposeCount[purpose] = 0

            for i in range(activity[0], activity[1]):
                trackPoint = {'location': gpsTraces[i]['gpsReading']['location'],
                              'time': gpsTraces[i]['movesTime'],
                              'id': gpsTraces[i]['_id']}
                trackPoints.append(trackPoint)
                if 'wiFiNetwork' in gpsTraces[i]:
                    if gpsTraces[i]['wiFiNetwork'] not in wiFiNetwork:
                        wiFiNetwork.append(gpsTraces[i]['wiFiNetwork'])
                if 'purpose' in gpsTraces[i]['groundTruth']:
                    for gtPurpose in gpsTraces[i]['groundTruth']['purpose']:
                        purposeCount[gtPurpose] += 1
                if 'exactLocation' in gpsTraces[i]['groundTruth']:
                    if gpsTraces[i]['groundTruth']['exactLocation'] not in location:
                        location.append(gpsTraces[i]['groundTruth']['exactLocation'])
            
            centroid = calCentroid(trackPoints)
            centroid = {'coordinates': [centroid[0], centroid[1]],
                        'type': 'Point'}

            maxCount, gtPurpose = purposeCount[max(purposeCount, key = purposeCount.get)], []
            if maxCount > (0.5 * (activity[1] - activity[0])):
                for purpose in purposes:
                    if purposeCount[purpose] == maxCount:
                        gtPurpose.append(purpose)
                                   
            startTime = gpsTraces[activity[0]]['movesTime']
            endTime = gpsTraces[activity[1]]['movesTime']
            duration = (dateutil.parser.parse(endTime) - dateutil.parser.parse(startTime)).total_seconds()
                                    
            record = {'type': 'Activity',
                      'phNum': testPhone,
                      'startTime': startTime,
                      'endTime': endTime,
                      'duration': duration,
                      'purpose': gtPurpose,
                      'location': location,
                      'wiFiNetwork': wiFiNetwork,
                      'centroid': centroid,
                      'trackPoints': trackPoints}

            if 'Sleep' in gtPurpose:
                record['mainPurpose'] = 'Sleep'
            elif 'Waiting' in gtPurpose:
                record['mainPurpose'] = 'Waiting'
            elif ('Work' in gtPurpose) or ('School' in gtPurpose):
                record['mainPurpose'] = 'Mandatory'
            elif ('Household_chores' in gtPurpose) or ('Meals' in gtPurpose) or ('Medical' in 
                    gtPurpose) or ('Personal_services' in gtPurpose) or ('Shopping' in gtPurpose):
                record['mainPurpose'] = 'Maintenance'
            elif ('Recreation' in gtPurpose) or ('Relaxing' in gtPurpose) or ('Social' in gtPurpose):
                record['mainPurpose'] = 'Discretionary'            
            
            if segments.find({'startTime': startTime, 'endTime': endTime, 'phNum': testPhone}).count() == 0:
                segments.insert(record)
                print testPhone, startTime, endTime, maxCount, gtPurpose
def modeChainSeparator(gpsPoints, testPhones):

    print
    reload(tripActivitySeparatorMongo)

    minDuration, maxRadius, minSamplingRate, gpsAccuracyThreshold = 360000, 50, 300000, 200
    minSeparationDistance, minSeparationTime = 100, 360000
    maxWalkSpeed, maxWalkAcceleration, minSegmentDuration, minSegmentLength = 5, 1620, 90000, 200

    timeTotTrips, timeInfTrips, distTotTrips, distInfTrips = 0, 0, 0, 0
    segTotTrips, segInfTrips, segWalkInfNonWalkTrips, segNonWalkInfWalkTrips = 0, 0, 0, 0

    for testPhone in testPhones:

        print "Processing data for " + str(testPhone)
        try:
            query = {"phNum": testPhone}
            projection = {"_id": 0, "gpsReading": 1, "epochTime": 1, "groundTruth": 1, "movesTime": 1}
            gpsTraces = list(gpsPoints.find(query, projection).sort("epochTime"))

            trips, activities, holes = tripActivitySeparatorMongo.inferTripActivity(
                gpsTraces,
                minDuration,
                maxRadius,
                minSeparationDistance,
                minSeparationTime,
                minSamplingRate,
                gpsAccuracyThreshold,
            )

            for trip in trips:
                modeChains = inferModeChain(
                    gpsTraces,
                    trip,
                    maxWalkSpeed,
                    maxWalkAcceleration,
                    minSegmentDuration,
                    minSegmentLength,
                    gpsAccuracyThreshold,
                )

                (
                    timeTotal,
                    timeInferred,
                    distTotal,
                    distInferred,
                    segTotal,
                    segInferred,
                    segWalkInfNonWalk,
                    segNonWalkInfWalk,
                ) = calInfAccuray(modeChains, gpsTraces)
                timeTotTrips += timeTotal
                timeInfTrips += timeInferred
                distTotTrips += distTotal
                distInfTrips += distInferred
                segTotTrips += segTotal
                segInfTrips += segInferred
                segWalkInfNonWalkTrips += segWalkInfNonWalk
                segNonWalkInfWalkTrips += segNonWalkInfWalk

        except:
            print "Unexpected error during inference:", sys.exc_info()[0]
            pass

    print
    print "Accuracy in terms of time: %.0f%% of %.0f hours" % ((timeInfTrips * 100.0) / timeTotTrips, timeTotTrips)
    print "Accuracy in terms of distance: %.0f%% of %.0f miles" % ((distInfTrips * 100.0) / distTotTrips, distTotTrips)
    print "Accuracy in terms of number of segments: %.0f%% of %.0f segments" % (
        (segInfTrips * 100.0) / segTotTrips,
        segTotTrips,
    )
    print (
        "Percentage of total segments that are walk but inferred as non-walk: %.0f%% of %.0f segments"
        % ((segWalkInfNonWalkTrips * 100.0) / segTotTrips, segTotTrips)
    )
    print (
        "Percentage of total segments that are non-walk but inferred as walk: %.0f%% of %.0f segments"
        % ((segNonWalkInfWalkTrips * 100.0) / segTotTrips, segTotTrips)
    )