Пример #1
0
def obsUpdateRow(fldPar, donePar, startTime, mmt, prevPos=None):
    """Calculate observing weight for given observation.

    Input:
        fldpar : DataFrame for a single observation. Comes from
                 readAllFLDFiles (i.e. not a single dictionary)
        donepar : Dataframe with stats pertaining to a fields doneness
        starTime : datetime string for beginning time for observation

    """
    # The idea here is to loop through all of the fields and calculate
    # the weight for this startTime.
    weightList = []  # Will store array of dicts with weight info

    for objID in fldPar["objid"]:
        # Is this already observed?
        donefld = donePar[donePar['objid'] == objID]
        fld = fldPar[fldPar["objid"] == objID]

        if donefld['complete'].values[0] == 1:
            continue

        # Initialize the weight dictionary
        obsWeight = {}
        obsWeight['objid'] = objID

        objEphem = MMTEphem.ObjEphem(fld['ra'].values[0], fld['dec'].values[0],
                                     startTime, mmt)
        fitWeight, endTime, fitVisits = willItFitWeight(
            fld, startTime, mmt, objEphem, donefld)
        moonFlag = calcMoonFlag(fld, startTime, endTime, mmt)

        # Does this observation have one very close by
        dist_weight = 1
        if prevPos is not None:

            dist = angSep(
                hms2dec(fld['ra'].values[0]) * 15.0,
                hms2dec(fld['dec'].values[0]), prevPos[0], prevPos[1])
            if dist < 10. / 3600.:
                dist_weight = 1000

        obsWeight['fitWeight'] = fitWeight
        obsWeight['obsTime'] = (endTime - startTime).total_seconds()
        obsWeight['moonFlag'] = moonFlag
        obsWeight['nVisits'] = fitVisits
        obsWeight['ra'] = fld['ra'].values[0]
        obsWeight['dec'] = fld['dec'].values[0]

        # Priority Weight
        priorFlag = 1.0 / float(fld['priority'])**3

        # Now combine the weights
        weightTAC = 1.0 - 1.0 * donefld['doneTime'].values[0] \
            / donefld['totalTime'].values[0]
        if weightTAC < 0:
            weightTAC = 0.001
        totalWeight = fitWeight * moonFlag * \
            (weightTAC) *dist_weight*priorFlag
        # We need to account for a few extra things.
        # 1. I want fields that have had previously observed
        #    fields to be the top priority if they are observable.
        # This modification will weight fields with no observations
        # at one (1+0) and those partially observed at 10
        partCompWeight = int(donefld['doneVisit'].values[0] > 0)
        #totalWeight = totalWeight * (1+0.5*partCompWeight)

        # Now account for weighting from preivous iteration of the
        # code. This should smooth things out
        totalWeight = totalWeight / donefld['prevWeight'].values[0]
        obsWeight['totalWeight'] = totalWeight
        # Append to weight listing
        weightList.append(obsWeight)

    obsWeights = pd.DataFrame(weightList)

    # Doing the O(n) problem here
    hasMax = []

    # Check to see there are actually targets!
    if len(obsWeights) == 0:
        return None, None

    maxWeight = max(obsWeights['totalWeight'])
    for ii in range(len(obsWeights)):
        if obsWeights['totalWeight'].values[ii] == maxWeight:
            hasMax.append(ii)

    # Now, check there are some with non-zero weight and
    # Observe a random one
    if maxWeight == 0:
        # No targets were done.
        return None, None
    else:

        # This allows for random choice.
        randIndex = hasMax[randint(0, len(hasMax) - 1)]

        diffTime = obsWeights['obsTime'].values[randIndex]
        # Increment the schedule
        schedule = []
        schedule.append(startTime)
        schedule.append(diffTime)
        schedule.append(obsWeights['objid'].values[randIndex])
        schedule.append(obsWeights['nVisits'].values[randIndex])
        outPos = [
            hms2dec(obsWeights['ra'].values[randIndex]) * 15.0,
            hms2dec(obsWeights['dec'].values[randIndex])
        ]

        # Update the done masks
        index = [i for i, x in enumerate(donePar['objid'] == schedule[2]) if x]

        # Donetime tracks total time for this PI.  We weight by
        # this, so let's increment all entries in donefld

        PI = donePar.loc[index, 'PI'].values[0]
        for ii in range(len(fldPar)):
            if donePar["PI"].values[ii] == PI:
                donePar.loc[ii, 'doneTime'] += diffTime / 3600.
                donePar.loc[ii, 'currentWeight'] = \
                    donePar.loc[ii, 'doneTime'] / \
                    donePar.loc[ii, 'totalTime']

        donePar.loc[index, 'doneVisit'] += \
            obsWeights['nVisits'].values[randIndex]

        # Check to see if the target is now done
        requested = int(
            fldPar[fldPar['objid'] == schedule[2]]["repeats"].values[0])
        if int(donePar.loc[index, 'doneVisit']) >= requested:
            donePar.loc[index, 'complete'] = 1
        return schedule, outPos