<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def calc_rets(returns, weights):
 """ Calculate continuous return series for futures instruments. These consist of weighted underlying instrument returns, who's weights can vary over time. Parameters returns: pandas.Series or dict A Series of instrument returns with a MultiIndex where the top level is pandas.Timestamps and the second level is instrument names. Values correspond to one period instrument returns. returns should be available for all for all Timestamps and instruments provided in weights. If dict is given this should be a dict of pandas.Series in the above format, with keys which are a subset of the keys given in weights weights: pandas.DataFrame or dict A DataFrame of instrument weights with a MultiIndex where the top level contains pandas.Timestamps and the second level is instrument names. The columns consist of generic names. If dict is given this should be a dict of pandas.DataFrame in the above format, with keys for different root generics, e.g. 'CL' Returns ------- A pandas.DataFrame of continuous returns for generics. The index is pandas.Timestamps and the columns is generic names, corresponding to weights.columns Examples -------- """
  # NOQA

    if not isinstance(returns, dict):
        returns = {"": returns}
    if not isinstance(weights, dict):
        weights = {"": weights}

    generic_superset = []
    for root in weights:
        generic_superset.extend(weights[root].columns.tolist())
    if len(set(generic_superset)) != len(generic_superset):
        raise ValueError("Columns for weights must all be unique")

    _check_indices(returns, weights)

    grets = []
    cols = []
    for root in returns:
        root_wts = weights[root]
        root_rets = returns[root]
        for generic in root_wts.columns:
            gnrc_wts = root_wts.loc[:, generic]
            # drop generics where weight is 0, this avoids potential KeyError
            # in later indexing of rets even when ret has weight of 0
            gnrc_wts = gnrc_wts.loc[gnrc_wts != 0]
            rets = root_rets.loc[gnrc_wts.index]
            # groupby time
            group_rets = (rets * gnrc_wts).groupby(level=0)
            grets.append(group_rets.apply(pd.DataFrame.sum, skipna=False))
        cols.extend(root_wts.columns.tolist())

    rets = pd.concat(grets, axis=1, keys=cols).sort_index(axis=1)
    return rets