"""
    smd_combined, smd, smd_preclustered = frameconnect(smd::SMD, params::ParamStruct)

Connect repeated localizations of the same emitter in `smd`.

# Description
Repeated localizations of the same emitter present in `smd` are connected and
combined into higher precision localizations of that emitter.  This is done by
1) forming pre-clusters of localizations, 2) estimating rate parameters from
the pre-clusters, 3) solving a linear assignment problem for connecting 
localizations in each pre-cluster, and 4) combining the connected localizations
using their MLE position estimate assuming Gaussian noise.
"""
function frameconnect(smd::SMD, params::ParamStruct = ParamStruct())
    # Generate pre-clusters of localizations in `smd`.
    smd_preclustered = precluster(smd, params)
    clusterdata = organizeclusters(smd_preclustered)

    # Estimate rate parameters.
    params.k_on, params.k_off, params.k_bleach, params.p_miss = 
        estimateparams(smd_preclustered, clusterdata)

    # Estimate the underlying density of emitters.
    params.initialdensity = 
        estimatedensities(smd_preclustered, clusterdata, params)

    # Connect localizations in `smd` by solving the LAP.
    nframes = isempty(smd.nframes) ? maximum(smd.framenum) : smd.nframes
    smd.connectID = connectlocalizations(
        smd_preclustered.connectID, clusterdata, params, nframes)

    # Combine the connected localizations into higher precision localizations.
    smd_combined = combinelocalizations(smd)
    
    return smd_combined, smd, smd_preclustered, params
end