Reproduce data and/or candidates with given candloc or lm coordinate.

    d and segment can be given, if only reading data.
    candloc is length 5 or 6 with ([scan], segment, candint, dmind, dtind, beamnum).
    product can be 'data', 'dataph', 'imdata', 'datacorr'.
    lm is tuple of (l,m) coordinates in radians.

def pipeline_reproduce(d, candloc=[], segment=None, lm=None, product='data'):
    """ Reproduce data and/or candidates with given candloc or lm coordinate.

    d and segment can be given, if only reading data.
    candloc is length 5 or 6 with ([scan], segment, candint, dmind, dtind, beamnum).
    product can be 'data', 'dataph', 'imdata', 'datacorr'.
    lm is tuple of (l,m) coordinates in radians.
    """

    # set up shared arrays to fill
    data_reproduce_mem = mps.Array(mps.ctypes.c_float, datasize(d)*2)
    data_read_mem = mps.Array(mps.ctypes.c_float, datasize(d)*2)
    data_mem = mps.Array(mps.ctypes.c_float, datasize(d)*2)
    u_read_mem = mps.Array(mps.ctypes.c_float, d['nbl'])
    u_mem = mps.Array(mps.ctypes.c_float, d['nbl'])
    v_read_mem = mps.Array(mps.ctypes.c_float, d['nbl'])
    v_mem = mps.Array(mps.ctypes.c_float, d['nbl'])
    w_read_mem = mps.Array(mps.ctypes.c_float, d['nbl'])
    w_mem = mps.Array(mps.ctypes.c_float, d['nbl'])

    # get numpy views of memory spaces
    data = numpyview(data_mem, 'complex64', datashape(d)) # optional
    data_read = numpyview(data_read_mem, 'complex64', datashape(d)) # optional
    u = numpyview(u_mem, 'float32', d['nbl'], raw=False)
    v = numpyview(v_mem, 'float32', d['nbl'], raw=False)
    w = numpyview(w_mem, 'float32', d['nbl'], raw=False)

    # set up state dict for merge pkl
    if len(candloc) == 6:
        scan, segment, candint, dmind, dtind, beamnum = candloc
# this is now defined by call to rtpipe.set_pipeline in parsecands.plot_cand
#        d['scan'] = scan
#        d['starttime_mjd'] = d['starttime_mjddict'][scan]
#        d['nsegments'] = len(d['segmenttimesdict'][scan])
#        d['segmenttimes'] = d['segmenttimesdict'][scan]
    elif len(candloc) == 5:  # if not a merge pkl, then d['scan'] is correct
        segment, candint, dmind, dtind, beamnum = candloc        
    elif isinstance(segment, int):
        assert product == 'data', 'If only providing segment, then only data product can be produced.'
    else:
        logger.error('candloc must be length 5 or 6 or segment provided.')
        return

    with closing(mp.Pool(1, initializer=initread, initargs=(data_read_mem, u_read_mem, v_read_mem, w_read_mem, data_mem, u_mem, v_mem, w_mem))) as readpool:  
        readpool.apply(pipeline_dataprep, (d, segment))

    if product == 'data':
        logger.info('Returning prepared data...')
        return data

    elif product == 'dataph':
        logger.info('Reproducing data and phasing...')
        assert lm, 'lm must be tuple with (l, m) coords in radians.'
        data = runreproduce(d, data_mem, data_reproduce_mem, u, v, w, dmind, dtind, lm=lm)
        return data

    elif product == 'datacorr':
        logger.info('Reproducing data...')
        data = runreproduce(d, data_mem, data_reproduce_mem, u, v, w, dmind, dtind)
        return data

    elif product == 'imdata':
        logger.info('Reproducing candidate...')
        im, data = runreproduce(d, data_mem, data_reproduce_mem, u, v, w, dmind, dtind, candint=candint)
        return im, data

    else:
        logger.error('product must be data, dataph, or imdata.')