Search function.
    Queues all trials with multiprocessing.
    Assumes shared memory system with single uvw grid for all images.

def search(d, data_mem, u_mem, v_mem, w_mem):
    """ Search function.
    Queues all trials with multiprocessing.
    Assumes shared memory system with single uvw grid for all images.
    """

    data = numpyview(data_mem, 'complex64', datashape(d))
    u = numpyview(u_mem, 'float32', d['nbl'])
    v = numpyview(v_mem, 'float32', d['nbl'])
    w = numpyview(w_mem, 'float32', d['nbl'])
    data_resamp_mem = mps.Array(mps.ctypes.c_float, datasize(d)*2)
    data_resamp = numpyview(data_resamp_mem, 'complex64', datashape(d))

    logger.debug('Search of segment %d' % d['segment'])

    beamnum = 0   # not yet implemented
    cands = {}

    candsfile = getcandsfile(d)
    if d['savecands'] and os.path.exists(candsfile):
        logger.warn('candsfile %s already exists' % candsfile)
        return cands

    # make wterm kernels
    if d['searchtype'] == 'image2w':
        wres = 100
        npix = max(d['npixx_full'], d['npixy_full'])
        bls, uvkers = rtlib.genuvkernels(w, wres, npix, d['uvres'], thresh=0.05)

    # SUBMITTING THE LOOPS
    if n.any(data):
        logger.debug('Searching in %d chunks with %d threads' % (d['nchunk'], d['nthread']))
        logger.info('Dedispering to max (DM, dt) of (%d, %d) ...' % (d['dmarr'][-1], d['dtarr'][-1]) )

        # open pool
        with closing(mp.Pool(d['nthread'], initializer=initresamp, initargs=(data_mem, data_resamp_mem))) as resamppool:
            blranges = [(d['nbl'] * t/d['nthread'], d['nbl']*(t+1)/d['nthread']) for t in range(d['nthread'])]           
            for dmind in xrange(len(d['dmarr'])):
                dm = d['dmarr'][dmind]
                logger.debug('Dedispersing for %d' % dm,)
                dedisppart = partial(correct_dm, d, dm)   # moves in fresh data
                dedispresults = resamppool.map(dedisppart, blranges)

                dtlast = 1
                for dtind in xrange(len(d['dtarr'])):
                    dt = d['dtarr'][dtind]
                    
                    if dt > 1:
                        # dedispersion in shared memory, mapped over baselines
                        # set partial functions for pool.map

                        logger.debug('Resampling for %d' % dt,)
                        resample = dt/dtlast
                        resamppart = partial(correct_dt, d, resample)   # corrects in place
                        resampresults = resamppool.map(resamppart, blranges)
                        dtlast = dt

                    # set dm- and dt-dependent int ranges for segment
                    nskip_dm = ((d['datadelay'][-1] - d['datadelay'][dmind]) / dt) * (d['segment'] != 0)  # nskip=0 for first segment
                    searchints = (d['readints'] - d['datadelay'][dmind]) / dt - nskip_dm
                    logger.debug('Imaging %d ints from %d for (%d,%d)' % (searchints, nskip_dm, dm, dt),)

                    # imaging in shared memory, mapped over ints
                    image1part = partial(image1, d, u, v, w, dmind, dtind, beamnum)
                    nchunkdt = min(searchints, max(d['nthread'], d['nchunk']/dt))  # parallelize in range bounded by (searchints, nthread)
                    irange = [(nskip_dm + searchints*chunk/nchunkdt, nskip_dm + searchints*(chunk+1)/nchunkdt) for chunk in range(nchunkdt)]
                    imageresults = resamppool.map(image1part, irange)

                    # COLLECTING THE RESULTS per dm/dt. Clears the way for overwriting data_resamp
                    for imageresult in imageresults:
                        for kk in imageresult.keys():
                            cands[kk] = imageresult[kk]

        if 'sigma_plot' in d:
            from rtpipe.reproduce import make_cand_plot as makecp
            if 'snr2' in d['features']:
                snrcol = d['features'].index('snr2')
            elif 'snr1' in d['features']:
                snrcol = d['features'].index('snr1')

            snrs = n.array([value[snrcol] for value in cands.itervalues()])

            maxsnr = max([0] + [value[snrcol] for value in cands.itervalues()])  # be sure max includes at least one value
            if maxsnr > d['sigma_plot']:
                segment, candint, dmind, dtind, beamnum = [key for key, value in cands.iteritems() if value[snrcol] == maxsnr][0]
                logger.info('Making cand plot for scan %d, segment %d, candint %d, dmind %d, dtint %d with SNR %.1f.' % (d['scan'], segment, candint, dmind, dtind, maxsnr))
                im, data = runreproduce(d, data_mem, data_resamp_mem, u, v, w, dmind, dtind, candint)
                loclabel = [d['scan'], segment, candint, dmind, dtind, beamnum]
                makecp(d, im, data, loclabel, version=2, snrs=snrs)
            else:
                logger.info('No candidate in segment %d above sigma_plot %.1f' % (d['segment'], d['sigma_plot']))

    else:
        logger.warn('Data for processing is zeros. Moving on...')

    logger.info('Found %d cands in scan %d segment %d of %s. ' % (len(cands), d['scan'], d['segment'], d['filename']))
    return cands