def getDefocPairParticles(imgdata, selectionid, particlelabel=None):
    ### get defocal pair
    if imgdata['preset'] is not None:
        defimgdata = apDefocalPairs.getDefocusPair(imgdata)
    else:
        # For pairs from Leginon Manual Application
        defimgdata = apDefocalPairs.getManualDefocusPair(imgdata)
    if defimgdata is None:
        apDisplay.printWarning(
            "Could not find defocal pair for image %s (id %d)" %
            (apDisplay.short(imgdata['filename']), imgdata.dbid))
        return ([], {'shiftx': 0, 'shifty': 0, 'scale': 1})
    apDisplay.printMsg(
        "Found defocus pair %s (id %d) for image %s (id %d)" %
        (apDisplay.short(defimgdata['filename']), defimgdata.dbid,
         apDisplay.short(imgdata['filename']), imgdata.dbid))

    ### get particles
    partq = appiondata.ApParticleData()
    partq['image'] = defimgdata
    partq['selectionrun'] = appiondata.ApSelectionRunData.direct_query(
        selectionid)
    if particlelabel is not None:
        partq['label'] = particlelabel
    partdatas = partq.query()
    apDisplay.printMsg("Found %d particles for defocal pair %s (id %d)" % (
        len(partdatas),
        apDisplay.short(defimgdata['filename']),
        defimgdata.dbid,
    ))

    if len(partdatas) == 0:
        return ([], {'shiftx': 0, 'shifty': 0, 'scale': 1})

    ### get shift information
    has_tried = False
    while True:
        shiftq = appiondata.ApImageTransformationData()
        shiftq['image1'] = defimgdata
        shiftdatas = shiftq.query()
        if shiftdatas:
            shiftdata = shiftdatas[0]
            apDisplay.printMsg(
                "Shifting particles by %.1f,%.1f (%d X)" %
                (shiftdata['shiftx'], shiftdata['shifty'], shiftdata['scale']))
            break
        else:
            if has_tried == True:
                apDisplay.printError(
                    "No shift inserted to database after one try")
            apDisplay.printMsg("Calculating shift....")
            shiftpeak = apDefocalPairs.getShift(defimgdata, imgdata)
            apDefocalPairs.insertShift(defimgdata, imgdata, shiftpeak)
            has_tried = True
    return (partdatas, shiftdata)
def getTransformedDefocPair(imgdata, direction):
    simgq = appiondata.ApImageTransformationData()
    base = 'image'
    direction = str(direction)
    if direction == '2':
        sfrom = base + '2'
        sto = base + '1'
    if direction == '1':
        sfrom = base + '1'
        sto = base + '2'
    simgq[sfrom] = imgdata
    simgresults = simgq.query(readimages=False)
    if simgresults:
        sbimgref = simgresults[0].special_getitem(sto, dereference=False)
        sbimgdata = leginon.leginondata.AcquisitionImageData.direct_query(
            sbimgref.dbid, readimages=False)
    else:
        return None
    return sbimgdata
def insertShift(imgdata, siblingdata, peak):
    if not siblingdata or not peak:
        apDisplay.printWarning("No sibling or peak found. No database insert")
        return False
    shiftq = appiondata.ApImageTransformationData()
    shiftq['image1'] = imgdata
    shiftdata = shiftq.query()
    if shiftdata:
        apDisplay.printWarning("Shift values already in database")
        return False
    shiftq['image2'] = siblingdata
    shiftq['shiftx'] = peak['shift'][1]
    shiftq['shifty'] = peak['shift'][0]
    shiftq['scale'] = peak['scalefactor']
    if not peak['subfailed']:
        shiftq['correlation'] = peak['subpixel peak value']
    else:
        shiftq['correlation'] = 0.0
    apDisplay.printMsg("Inserting shift beteween "+apDisplay.short(imgdata['filename'])+\
            " and "+apDisplay.short(siblingdata['filename'])+" into database")
    shiftq.insert()
    return True