def gradient_pred(model, ref, ref_rc, alt, alt_rc, mutation_positions, out_annotation_all_outputs,
                  output_filter_mask=None, out_annotation=None):
    """Gradient-based (saliency) variant effect prediction

    Based on the idea of [saliency maps](https://arxiv.org/pdf/1312.6034.pdf) the gradient-based prediction of
    variant effects uses the `gradient` function of the Keras backend to estimate the importance of a variant
    for a given output. This value is then multiplied by the input, as recommended by
    [Shrikumar et al., 2017](https://arxiv.org/pdf/1605.01713.pdf).

    # Arguments
        model: Keras model
        ref: Input sequence with the reference genotype in the mutation position
        ref_rc: Reverse complement of the 'ref' argument
        alt: Input sequence with the alternative genotype in the mutation position
        alt_rc: Reverse complement of the 'alt' argument
        mutation_positions: Position on which the mutation was placed in the forward sequences
        out_annotation_all_outputs: Output labels of the model.
        output_filter_mask: Mask of boolean values indicating which model outputs should be used.
            Use this or 'out_annotation'
        out_annotation: List of outputs labels for which of the outputs (in case of a multi-task model) the
            predictions should be calculated.

    # Returns

    Dictionary with three different entries:

    - ref: Gradient * input at the mutation position using the reference sequence.
        Forward or reverse-complement sequence is chose based on sequence direction caused
        the bigger absolute difference ('diff')
    - alt: Gradient * input at the mutation position using the alternative sequence. Forward or
        reverse-complement sequence is chose based on sequence direction caused the bigger
        absolute difference ('diff')
    - diff: 'alt' - 'ref'. Forward or reverse-complement sequence is chose based on sequence
        direction caused the bigger absolute difference.
    """
    seqs = {"ref": ref, "ref_rc": ref_rc, "alt": alt, "alt_rc": alt_rc}

    for k in seqs:
        if not isinstance(seqs[k], (list, tuple, np.ndarray)):
            raise Exception("At the moment only models with list, tuple or np.ndarray inputs are supported.")

    assert np.all([np.array(get_seq_len(ref)) == np.array(get_seq_len(seqs[k])) for k in seqs.keys() if k != "ref"])
    assert get_seq_len(ref)[0] == mutation_positions.shape[0]
    assert len(mutation_positions.shape) == 1

    # determine which outputs should be selected
    if output_filter_mask is None:
        if out_annotation is None:
            output_filter_mask = np.arange(out_annotation_all_outputs.shape[0])
        else:
            output_filter_mask = np.where(np.in1d(out_annotation_all_outputs, out_annotation))[0]

    # make sure the labels are assigned correctly
    out_annotation = out_annotation_all_outputs[output_filter_mask]

    # Generate the necessary gradient functions
    sal_funcs = __generate_direct_saliency_functions__(model, out_annotation_all_outputs, out_annotation)

    # ANALOGOUS TO ISM:
    # predict
    preds = {}

    for k in seqs:
        preds[k] = {}
        if "_rc" in k:
            mutated_positions_here = get_seq_len(ref)[1] - 1 - mutation_positions
        else:
            mutated_positions_here = mutation_positions
        for l in out_annotation:
            preds[k][l] = predict_vals(input_data=seqs[k], apply_function=__get_direct_saliencies__,
                                       score_func=sal_funcs[l], mutated_positions=mutated_positions_here, model = model)

    diff_ret_dGrad = {}
    pred_out = {"ref": {}, "alt": {}}
    for k in preds["ref"]:
        # TODO make list (and dict)-ready
        diff_fwd = general_diff(preds["alt"][k]["dGrad"],  preds["ref"][k]["dGrad"])
        diff_rc = general_diff(preds["alt_rc"][k]["dGrad"],  preds["ref_rc"][k]["dGrad"])
        sel = general_sel(diff_fwd, diff_rc)
        replace_by_sel(diff_fwd, diff_rc, sel)
        diff_ret_dGrad[k] = diff_fwd
        # Overwrite the fwd values with rc values if rc was selected
        replace_by_sel(preds["ref"][k]["dGrad"], preds["ref_rc"][k]["dGrad"], sel)
        replace_by_sel(preds["alt"][k]["dGrad"], preds["alt_rc"][k]["dGrad"], sel)
        pred_out["ref"][k] = preds["ref"][k]["dGrad"]
        pred_out["alt"][k] = preds["alt"][k]["dGrad"]

    return {"diff": pd.DataFrame(diff_ret_dGrad),
            "ref": pd.DataFrame(pred_out["ref"]),
            "alt": pd.DataFrame(pred_out["alt"])}
def gradient_pred ( model , ref , ref_rc , alt , alt_rc , mutation_positions , out_annotation_all_outputs , output_filter_mask = None , out_annotation = None ) : seqs = { "ref" : ref , "ref_rc" : ref_rc , "alt" : alt , "alt_rc" : alt_rc } for k in seqs : if not isinstance ( seqs [ k ] , ( list , tuple , np . ndarray ) ) : raise Exception ( "At the moment only models with list, tuple or np.ndarray inputs are supported." ) assert np . all ( [ np . array ( get_seq_len ( ref ) ) == np . array ( get_seq_len ( seqs [ k ] ) ) for k in seqs . keys ( ) if k != "ref" ] ) assert get_seq_len ( ref ) [ 0 ] == mutation_positions . shape [ 0 ] assert len ( mutation_positions . shape ) == 1 if output_filter_mask is None : if out_annotation is None : output_filter_mask = np . arange ( out_annotation_all_outputs . shape [ 0 ] ) else : output_filter_mask = np . where ( np . in1d ( out_annotation_all_outputs , out_annotation ) ) [ 0 ] out_annotation = out_annotation_all_outputs [ output_filter_mask ] sal_funcs = __generate_direct_saliency_functions__ ( model , out_annotation_all_outputs , out_annotation ) preds = { } for k in seqs : preds [ k ] = { } if "_rc" in k : mutated_positions_here = get_seq_len ( ref ) [ 1 ] - 1 - mutation_positions else : mutated_positions_here = mutation_positions for l in out_annotation : preds [ k ] [ l ] = predict_vals ( input_data = seqs [ k ] , apply_function = __get_direct_saliencies__ , score_func = sal_funcs [ l ] , mutated_positions = mutated_positions_here , model = model ) diff_ret_dGrad = { } pred_out = { "ref" : { } , "alt" : { } } for k in preds [ "ref" ] : diff_fwd = general_diff ( preds [ "alt" ] [ k ] [ "dGrad" ] , preds [ "ref" ] [ k ] [ "dGrad" ] ) diff_rc = general_diff ( preds [ "alt_rc" ] [ k ] [ "dGrad" ] , preds [ "ref_rc" ] [ k ] [ "dGrad" ] ) sel = general_sel ( diff_fwd , diff_rc ) replace_by_sel ( diff_fwd , diff_rc , sel ) diff_ret_dGrad [ k ] = diff_fwd replace_by_sel ( preds [ "ref" ] [ k ] [ "dGrad" ] , preds [ "ref_rc" ] [ k ] [ "dGrad" ] , sel ) replace_by_sel ( preds [ "alt" ] [ k ] [ "dGrad" ] , preds [ "alt_rc" ] [ k ] [ "dGrad" ] , sel ) pred_out [ "ref" ] [ k ] = preds [ "ref" ] [ k ] [ "dGrad" ] pred_out [ "alt" ] [ k ] = preds [ "alt" ] [ k ] [ "dGrad" ] return { "diff" : pd . DataFrame ( diff_ret_dGrad ) , "ref" : pd . DataFrame ( pred_out [ "ref" ] ) , "alt" : pd . DataFrame ( pred_out [ "alt" ] ) }
Gradient-based (saliency) variant effect prediction

    Based on the idea of [saliency maps](https://arxiv.org/pdf/1312.6034.pdf) the gradient-based prediction of
    variant effects uses the `gradient` function of the Keras backend to estimate the importance of a variant
    for a given output. This value is then multiplied by the input, as recommended by
    [Shrikumar et al., 2017](https://arxiv.org/pdf/1605.01713.pdf).

    # Arguments
        model: Keras model
        ref: Input sequence with the reference genotype in the mutation position
        ref_rc: Reverse complement of the 'ref' argument
        alt: Input sequence with the alternative genotype in the mutation position
        alt_rc: Reverse complement of the 'alt' argument
        mutation_positions: Position on which the mutation was placed in the forward sequences
        out_annotation_all_outputs: Output labels of the model.
        output_filter_mask: Mask of boolean values indicating which model outputs should be used.
            Use this or 'out_annotation'
        out_annotation: List of outputs labels for which of the outputs (in case of a multi-task model) the
            predictions should be calculated.

    # Returns

    Dictionary with three different entries:

    - ref: Gradient * input at the mutation position using the reference sequence.
        Forward or reverse-complement sequence is chose based on sequence direction caused
        the bigger absolute difference ('diff')
    - alt: Gradient * input at the mutation position using the alternative sequence. Forward or
        reverse-complement sequence is chose based on sequence direction caused the bigger
        absolute difference ('diff')
    - diff: 'alt' - 'ref'. Forward or reverse-complement sequence is chose based on sequence
        direction caused the bigger absolute difference.