def predict_proba(self, x, y=None, **kwargs):
        """ Predict the causal score using a trained RCC model

        Args:
            x (numpy.array or pandas.DataFrame or pandas.Series): First variable or dataset.
            args (numpy.array): second variable (optional depending on the 1st argument).

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        if self.clf is None:
            raise ValueError("Model has to be trained before making predictions.")
        if x is pandas.Series:
            input_ = self.featurize_row(x.iloc[0], x.iloc[1]).reshape((1, -1))
        elif x is pandas.DataFrame:
            input_ = np.array([self.featurize_row(x.iloc[0], x.iloc[1]) for row in x])
        elif y is not None:
            input_ = self.featurize_row(x, y).reshape((1, -1))
        else:
            raise TypeError("DataType not understood.")
        return self.clf.predict(input_)


def predict_features(self, df_features, df_target, nh=20, idx=0, dropout=0.,
                         activation_function=th.nn.ReLU, lr=0.01, l1=0.1,  batch_size=-1,
                         train_epochs=1000, test_epochs=1000, device=None,
                         verbose=None, nb_runs=3):
        """For one variable, predict its neighbours.

        Args:
            df_features (pandas.DataFrame):
            df_target (pandas.Series):
            nh (int): number of hidden units
            idx (int): (optional) for printing purposes
            dropout (float): probability of dropout (between 0 and 1)
            activation_function (torch.nn.Module): activation function of the NN
            lr (float): learning rate of Adam
            l1 (float): L1 penalization coefficient
            batch_size (int): batch size, defaults to full-batch
            train_epochs (int): number of train epochs
            test_epochs (int): number of test epochs
            device (str): cuda or cpu device (defaults to ``cdt.SETTINGS.default_device``)
            verbose (bool): verbosity (defaults to ``cdt.SETTINGS.verbose``)
            nb_runs (int): number of bootstrap runs

        Returns:
            list: scores of each feature relatively to the target

        """
        device, verbose = SETTINGS.get_default(('device', device), ('verbose', verbose))
        x = th.FloatTensor(scale(df_features.values)).to(device)
        y = th.FloatTensor(scale(df_target.values)).to(device)
        out = []
        for i in range(nb_runs):
            model = FSGNN_model([x.size()[1] + 1, nh, 1],
                                dropout=dropout,
                                activation_function=activation_function).to(device)

            out.append(model.train(x, y, lr=0.01, l1=0.1, batch_size=-1,
                                   train_epochs=train_epochs, test_epochs=test_epochs,
                                   device=device, verbose=verbose))
        return list(np.mean(np.array(out), axis=0))

def predict_features ( self , df_features , df_target , nh = 20 , idx = 0 , dropout = 0. , activation_function = th . nn . ReLU , lr = 0.01 , l1 = 0.1 , batch_size = - 1 , train_epochs = 1000 , test_epochs = 1000 , device = None , verbose = None , nb_runs = 3 ) : device , verbose = SETTINGS . get_default ( ( 'device' , device ) , ( 'verbose' , verbose ) ) x = th . FloatTensor ( scale ( df_features . values ) ) . to ( device ) y = th . FloatTensor ( scale ( df_target . values ) ) . to ( device ) out = [ ] for i in range ( nb_runs ) : model = FSGNN_model ( [ x . size ( ) [ 1 ] + 1 , nh , 1 ] , dropout = dropout , activation_function = activation_function ) . to ( device ) out . append ( model . train ( x , y , lr = 0.01 , l1 = 0.1 , batch_size = - 1 , train_epochs = train_epochs , test_epochs = test_epochs , device = device , verbose = verbose ) ) return list ( np . mean ( np . array ( out ) , axis = 0 ) )

For one variable predict its neighbours .


def predict_undirected_graph(self, data):
        """Build a skeleton using a pairwise independence criterion.

        Args:
            data (pandas.DataFrame): Raw data table

        Returns:
            networkx.Graph: Undirected graph representing the skeleton.
        """
        graph = Graph()

        for idx_i, i in enumerate(data.columns):
            for idx_j, j in enumerate(data.columns[idx_i+1:]):
                score = self.predict(data[i].values, data[j].values)
                if abs(score) > 0.001:
                    graph.add_edge(i, j, weight=score)

        return graph

def predict_undirected_graph ( self , data ) : graph = Graph ( ) for idx_i , i in enumerate ( data . columns ) : for idx_j , j in enumerate ( data . columns [ idx_i + 1 : ] ) : score = self . predict ( data [ i ] . values , data [ j ] . values ) if abs ( score ) > 0.001 : graph . add_edge ( i , j , weight = score ) return graph

Build a skeleton using a pairwise independence criterion .


def predict(self, df_data, threshold=0.05, **kwargs):
        """Predict the skeleton of the graph from raw data.

        Returns iteratively the feature selection algorithm on each node.

        Args:
            df_data (pandas.DataFrame): data to construct a graph from
            threshold (float): cutoff value for feature selection scores
            kwargs (dict): additional arguments for algorithms

        Returns:
            networkx.Graph: predicted skeleton of the graph.
        """
        nb_jobs = kwargs.get("nb_jobs", SETTINGS.NB_JOBS)
        list_nodes = list(df_data.columns.values)
        if nb_jobs != 1:
            result_feature_selection = Parallel(n_jobs=nb_jobs)(delayed(self.run_feature_selection)
                                                                (df_data, node, idx, **kwargs)
                                                                for idx, node in enumerate(list_nodes))
        else:
            result_feature_selection = [self.run_feature_selection(df_data, node, idx, **kwargs) for idx, node in enumerate(list_nodes)]
        for idx, i in enumerate(result_feature_selection):
            try:
                i.insert(idx, 0)
            except AttributeError:  # if results are numpy arrays
                result_feature_selection[idx] = np.insert(i, idx, 0)
        matrix_results = np.array(result_feature_selection)
        matrix_results *= matrix_results.transpose()
        np.fill_diagonal(matrix_results, 0)
        matrix_results /= 2

        graph = nx.Graph()

        for (i, j), x in np.ndenumerate(matrix_results):
            if matrix_results[i, j] > threshold:
                graph.add_edge(list_nodes[i], list_nodes[j],
                               weight=matrix_results[i, j])
        for node in list_nodes:
            if node not in graph.nodes():
                graph.add_node(node)
        return graph

def predict ( self , df_data , threshold = 0.05 , ** kwargs ) : nb_jobs = kwargs . get ( "nb_jobs" , SETTINGS . NB_JOBS ) list_nodes = list ( df_data . columns . values ) if nb_jobs != 1 : result_feature_selection = Parallel ( n_jobs = nb_jobs ) ( delayed ( self . run_feature_selection ) ( df_data , node , idx , ** kwargs ) for idx , node in enumerate ( list_nodes ) ) else : result_feature_selection = [ self . run_feature_selection ( df_data , node , idx , ** kwargs ) for idx , node in enumerate ( list_nodes ) ] for idx , i in enumerate ( result_feature_selection ) : try : i . insert ( idx , 0 ) except AttributeError : result_feature_selection [ idx ] = np . insert ( i , idx , 0 ) matrix_results = np . array ( result_feature_selection ) matrix_results *= matrix_results . transpose ( ) np . fill_diagonal ( matrix_results , 0 ) matrix_results /= 2 graph = nx . Graph ( ) for ( i , j ) , x in np . ndenumerate ( matrix_results ) : if matrix_results [ i , j ] > threshold : graph . add_edge ( list_nodes [ i ] , list_nodes [ j ] , weight = matrix_results [ i , j ] ) for node in list_nodes : if node not in graph . nodes ( ) : graph . add_node ( node ) return graph

Predict the skeleton of the graph from raw data .


def orient_undirected_graph(self, data, graph):
        """Run GIES on an undirected graph.

        Args:
            data (pandas.DataFrame): DataFrame containing the data
            graph (networkx.Graph): Skeleton of the graph to orient

        Returns:
            networkx.DiGraph: Solution given by the GIES algorithm.

        """
        # Building setup w/ arguments.
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        self.arguments['{SCORE}'] = self.scores[self.score]

        fe = DataFrame(nx.adj_matrix(graph, weight=None).todense())
        fg = DataFrame(1 - fe.values)

        results = self._run_gies(data, fixedGaps=fg, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

def orient_undirected_graph ( self , data , graph ) : self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) self . arguments [ '{SCORE}' ] = self . scores [ self . score ] fe = DataFrame ( nx . adj_matrix ( graph , weight = None ) . todense ( ) ) fg = DataFrame ( 1 - fe . values ) results = self . _run_gies ( data , fixedGaps = fg , verbose = self . verbose ) return nx . relabel_nodes ( nx . DiGraph ( results ) , { idx : i for idx , i in enumerate ( data . columns ) } )


def create_graph_from_data(self, data):
        """Run the GIES algorithm.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by the GIES algorithm.
        """
        # Building setup w/ arguments.
        self.arguments['{SCORE}'] = self.scores[self.score]
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()

        results = self._run_gies(data, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

def create_graph_from_data ( self , data ) : self . arguments [ '{SCORE}' ] = self . scores [ self . score ] self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) results = self . _run_gies ( data , verbose = self . verbose ) return nx . relabel_nodes ( nx . DiGraph ( results ) , { idx : i for idx , i in enumerate ( data . columns ) } )


def _run_gies(self, data, fixedGaps=None, verbose=True):
        """Setting up and running GIES with all arguments."""
        # Run gies
        id = str(uuid.uuid4())
        os.makedirs('/tmp/cdt_gies' + id + '/')
        self.arguments['{FOLDER}'] = '/tmp/cdt_gies' + id + '/'

        def retrieve_result():
            return read_csv('/tmp/cdt_gies' + id + '/result.csv', delimiter=',').values

        try:
            data.to_csv('/tmp/cdt_gies' + id + '/data.csv', header=False, index=False)
            if fixedGaps is not None:
                fixedGaps.to_csv('/tmp/cdt_gies' + id + '/fixedgaps.csv', index=False, header=False)
                self.arguments['{SKELETON}'] = 'TRUE'
            else:
                self.arguments['{SKELETON}'] = 'FALSE'

            gies_result = launch_R_script("{}/R_templates/gies.R".format(os.path.dirname(os.path.realpath(__file__))),
                                          self.arguments, output_function=retrieve_result, verbose=verbose)
        # Cleanup
        except Exception as e:
            rmtree('/tmp/cdt_gies' + id + '')
            raise e
        except KeyboardInterrupt:
            rmtree('/tmp/cdt_gies' + id + '/')
            raise KeyboardInterrupt
        rmtree('/tmp/cdt_gies' + id + '')
        return gies_result

def _run_gies ( self , data , fixedGaps = None , verbose = True ) : id = str ( uuid . uuid4 ( ) ) os . makedirs ( '/tmp/cdt_gies' + id + '/' ) self . arguments [ '{FOLDER}' ] = '/tmp/cdt_gies' + id + '/' def retrieve_result ( ) : return read_csv ( '/tmp/cdt_gies' + id + '/result.csv' , delimiter = ',' ) . values try : data . to_csv ( '/tmp/cdt_gies' + id + '/data.csv' , header = False , index = False ) if fixedGaps is not None : fixedGaps . to_csv ( '/tmp/cdt_gies' + id + '/fixedgaps.csv' , index = False , header = False ) self . arguments [ '{SKELETON}' ] = 'TRUE' else : self . arguments [ '{SKELETON}' ] = 'FALSE' gies_result = launch_R_script ( "{}/R_templates/gies.R" . format ( os . path . dirname ( os . path . realpath ( __file__ ) ) ) , self . arguments , output_function = retrieve_result , verbose = verbose ) except Exception as e : rmtree ( '/tmp/cdt_gies' + id + '' ) raise e except KeyboardInterrupt : rmtree ( '/tmp/cdt_gies' + id + '/' ) raise KeyboardInterrupt rmtree ( '/tmp/cdt_gies' + id + '' ) return gies_result

Setting up and running GIES with all arguments .


def plot_curves(i_batch, adv_loss, gen_loss, l1_reg, cols):
    """Plot SAM's various losses."""
    from matplotlib import pyplot as plt
    if i_batch == 0:
        try:
            ax.clear()
            ax.plot(range(len(adv_plt)), adv_plt, "r-",
                    linewidth=1.5, markersize=4,
                    label="Discriminator")
            ax.plot(range(len(adv_plt)), gen_plt, "g-", linewidth=1.5,
                    markersize=4, label="Generators")
            ax.plot(range(len(adv_plt)), l1_plt, "b-",
                    linewidth=1.5, markersize=4,
                    label="L1-Regularization")
            plt.legend()

            adv_plt.append(adv_loss.cpu().data[0])
            gen_plt.append(gen_loss.cpu().data[0] / cols)
            l1_plt.append(l1_reg.cpu().data[0])

            plt.pause(0.0001)

        except NameError:
            plt.ion()
            fig, ax = plt.figure()
            plt.xlabel("Epoch")
            plt.ylabel("Losses")

            plt.pause(0.0001)

            adv_plt = [adv_loss.cpu().data[0]]
            gen_plt = [gen_loss.cpu().data[0] / cols]
            l1_plt = [l1_reg.cpu().data[0]]

    else:
        adv_plt.append(adv_loss.cpu().data[0])
        gen_plt.append(gen_loss.cpu().data[0] / cols)
        l1_plt.append(l1_reg.cpu().data[0])

def plot_curves ( i_batch , adv_loss , gen_loss , l1_reg , cols ) : from matplotlib import pyplot as plt if i_batch == 0 : try : ax . clear ( ) ax . plot ( range ( len ( adv_plt ) ) , adv_plt , "r-" , linewidth = 1.5 , markersize = 4 , label = "Discriminator" ) ax . plot ( range ( len ( adv_plt ) ) , gen_plt , "g-" , linewidth = 1.5 , markersize = 4 , label = "Generators" ) ax . plot ( range ( len ( adv_plt ) ) , l1_plt , "b-" , linewidth = 1.5 , markersize = 4 , label = "L1-Regularization" ) plt . legend ( ) adv_plt . append ( adv_loss . cpu ( ) . data [ 0 ] ) gen_plt . append ( gen_loss . cpu ( ) . data [ 0 ] / cols ) l1_plt . append ( l1_reg . cpu ( ) . data [ 0 ] ) plt . pause ( 0.0001 ) except NameError : plt . ion ( ) fig , ax = plt . figure ( ) plt . xlabel ( "Epoch" ) plt . ylabel ( "Losses" ) plt . pause ( 0.0001 ) adv_plt = [ adv_loss . cpu ( ) . data [ 0 ] ] gen_plt = [ gen_loss . cpu ( ) . data [ 0 ] / cols ] l1_plt = [ l1_reg . cpu ( ) . data [ 0 ] ] else : adv_plt . append ( adv_loss . cpu ( ) . data [ 0 ] ) gen_plt . append ( gen_loss . cpu ( ) . data [ 0 ] / cols ) l1_plt . append ( l1_reg . cpu ( ) . data [ 0 ] )


def plot_gen(epoch, batch, generated_variables, pairs_to_plot=[[0, 1]]):
    """Plot generated pairs of variables."""
    from matplotlib import pyplot as plt
    if epoch == 0:
        plt.ion()
    plt.clf()
    for (i, j) in pairs_to_plot:

        plt.scatter(generated_variables[i].data.cpu().numpy(
        ), batch.data.cpu().numpy()[:, j], label="Y -> X")
        plt.scatter(batch.data.cpu().numpy()[
            :, i], generated_variables[j].data.cpu().numpy(), label="X -> Y")

        plt.scatter(batch.data.cpu().numpy()[:, i], batch.data.cpu().numpy()[
            :, j], label="original data")
        plt.legend()

    plt.pause(0.01)

def
plot_gen
(
epoch
,
batch
,
generated_variables
,
pairs_to_plot
=
[
[
0
,
1
]
]
)
:
from
matplotlib
import
pyplot
as
plt
if
epoch
==
0
:
plt
.
ion
(
)
plt
.
clf
(
)
for
(
i
,
j
)
in
pairs_to_plot
:
plt
.
scatter
(
generated_variables
[
i
]
.
data
.
cpu
(
)
.
numpy
(
)
,
batch
.
data
.
cpu
(
)
.
numpy
(
)
[
:
,
j
]
,
label
=
"Y -> X"
)
plt
.
scatter
(
batch
.
data
.
cpu
(
)
.
numpy
(
)
[
:
,
i
]
,
generated_variables
[
j
]
.
data
.
cpu
(
)
.
numpy
(
)
,
label
=
"X -> Y"
)
plt
.
scatter
(
batch
.
data
.
cpu
(
)
.
numpy
(
)
[
:
,
i
]
,
batch
.
data
.
cpu
(
)
.
numpy
(
)
[
:
,
j
]
,
label
=
"original data"
)
plt
.
legend
(
)
plt
.
pause
(
0.01
)


def reset_parameters(self):
        """Reset the parameters."""
        stdv = 1. / math.sqrt(self.weight.size(1))
        self.weight.data.uniform_(-stdv, stdv)
        if self.bias is not None:
            self.bias.data.uniform_(-stdv, stdv)

def reset_parameters ( self ) : stdv = 1. / math . sqrt ( self . weight . size ( 1 ) ) self . weight . data . uniform_ ( - stdv , stdv ) if self . bias is not None : self . bias . data . uniform_ ( - stdv , stdv )


def forward(self, input):
        """Feed-forward through the network."""
        return th.nn.functional.linear(input, self.weight.div(self.weight.pow(2).sum(0).sqrt()))

def forward ( self , input ) : return th . nn . functional . linear ( input , self . weight . div ( self . weight . pow ( 2 ) . sum ( 0 ) . sqrt ( ) ) )


def predict(self, data, graph=None, nruns=6, njobs=None, gpus=0, verbose=None,
                plot=False, plot_generated_pair=False, return_list_results=False):
        """Execute SAM on a dataset given a skeleton or not.

        Args:
            data (pandas.DataFrame): Observational data for estimation of causal relationships by SAM
            skeleton (numpy.ndarray): A priori knowledge about the causal relationships as an adjacency matrix.
                      Can be fed either directed or undirected links.
            nruns (int): Number of runs to be made for causal estimation.
                   Recommended: >=12 for optimal performance.
            njobs (int): Numbers of jobs to be run in Parallel.
                   Recommended: 1 if no GPU available, 2*number of GPUs else.
            gpus (int): Number of available GPUs for the algorithm.
            verbose (bool): verbose mode
            plot (bool): Plot losses interactively. Not recommended if nruns>1
            plot_generated_pair (bool): plots a generated pair interactively.  Not recommended if nruns>1
        Returns:
            networkx.DiGraph: Graph estimated by SAM, where A[i,j] is the term
            of the ith variable for the jth generator.
        """
        verbose, njobs = SETTINGS.get_default(('verbose', verbose), ('nb_jobs', njobs))
        if njobs != 1:
            list_out = Parallel(n_jobs=njobs)(delayed(run_SAM)(data,
                                                               skeleton=graph,
                                                               lr_gen=self.lr, lr_disc=self.dlr,
                                                               regul_param=self.l1, nh=self.nh, dnh=self.dnh,
                                                               gpu=bool(gpus), train_epochs=self.train,
                                                               test_epochs=self.test, batch_size=self.batchsize,
                                                               plot=plot, verbose=verbose, gpu_no=idx % max(gpus, 1))
                                              for idx in range(nruns))
        else:
            list_out = [run_SAM(data, skeleton=graph,
                                lr_gen=self.lr, lr_disc=self.dlr,
                                regul_param=self.l1, nh=self.nh, dnh=self.dnh,
                                gpu=bool(gpus), train_epochs=self.train,
                                test_epochs=self.test, batch_size=self.batchsize,
                                plot=plot, verbose=verbose, gpu_no=0)
                        for idx in range(nruns)]
        if return_list_results:
            return list_out
        else:
            W = list_out[0]
            for w in list_out[1:]:
                W += w
            W /= nruns
        return nx.relabel_nodes(nx.DiGraph(W), {idx: i for idx, i in enumerate(data.columns)})

def predict ( self , data , graph = None , nruns = 6 , njobs = None , gpus = 0 , verbose = None , plot = False , plot_generated_pair = False , return_list_results = False ) : verbose , njobs = SETTINGS . get_default ( ( 'verbose' , verbose ) , ( 'nb_jobs' , njobs ) ) if njobs != 1 : list_out = Parallel ( n_jobs = njobs ) ( delayed ( run_SAM ) ( data , skeleton = graph , lr_gen = self . lr , lr_disc = self . dlr , regul_param = self . l1 , nh = self . nh , dnh = self . dnh , gpu = bool ( gpus ) , train_epochs = self . train , test_epochs = self . test , batch_size = self . batchsize , plot = plot , verbose = verbose , gpu_no = idx % max ( gpus , 1 ) ) for idx in range ( nruns ) ) else : list_out = [ run_SAM ( data , skeleton = graph , lr_gen = self . lr , lr_disc = self . dlr , regul_param = self . l1 , nh = self . nh , dnh = self . dnh , gpu = bool ( gpus ) , train_epochs = self . train , test_epochs = self . test , batch_size = self . batchsize , plot = plot , verbose = verbose , gpu_no = 0 ) for idx in range ( nruns ) ] if return_list_results : return list_out else : W = list_out [ 0 ] for w in list_out [ 1 : ] : W += w W /= nruns return nx . relabel_nodes ( nx . DiGraph ( W ) , { idx : i for idx , i in enumerate ( data . columns ) } )

Execute SAM on a dataset given a skeleton or not .


def predict_proba(self, a, b, **kwargs):
        """ Infer causal relationships between 2 variables using the RECI statistic

        :param a: Input variable 1
        :param b: Input variable 2
        :return: Causation coefficient (Value : 1 if a->b and -1 if b->a)
        :rtype: float
        """
        return self.b_fit_score(b, a) - self.b_fit_score(a, b)

def predict_proba ( self , a , b , ** kwargs ) : return self . b_fit_score ( b , a ) - self . b_fit_score ( a , b )


def b_fit_score(self, x, y):
        """ Compute the RECI fit score

        Args:
            x (numpy.ndarray): Variable 1
            y (numpy.ndarray): Variable 2

        Returns:
            float: RECI fit score

        """
        x = np.reshape(minmax_scale(x), (-1, 1))
        y = np.reshape(minmax_scale(y), (-1, 1))
        poly = PolynomialFeatures(degree=self.degree)
        poly_x = poly.fit_transform(x)

        poly_x[:,1] = 0
        poly_x[:,2] = 0

        regressor = LinearRegression()
        regressor.fit(poly_x, y)

        y_predict = regressor.predict(poly_x)
        error = mean_squared_error(y_predict, y)

        return error

def b_fit_score ( self , x , y ) : x = np . reshape ( minmax_scale ( x ) , ( - 1 , 1 ) ) y = np . reshape ( minmax_scale ( y ) , ( - 1 , 1 ) ) poly = PolynomialFeatures ( degree = self . degree ) poly_x = poly . fit_transform ( x ) poly_x [ : , 1 ] = 0 poly_x [ : , 2 ] = 0 regressor = LinearRegression ( ) regressor . fit ( poly_x , y ) y_predict = regressor . predict ( poly_x ) error = mean_squared_error ( y_predict , y ) return error


def predict_proba(self, a, b, **kwargs):
        """ Infer causal relationships between 2 variables using the CDS statistic

        Args:
            a (numpy.ndarray): Variable 1
            b (numpy.ndarray): Variable 2

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        return self.cds_score(b, a) - self.cds_score(a, b)

def predict_proba ( self , a , b , ** kwargs ) : return self . cds_score ( b , a ) - self . cds_score ( a , b )


def predict_proba(self, a, b, **kwargs):
        """Prediction method for pairwise causal inference using the ANM model.

        Args:
            a (numpy.ndarray): Variable 1
            b (numpy.ndarray): Variable 2

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        a = scale(a).reshape((-1, 1))
        b = scale(b).reshape((-1, 1))

        return self.anm_score(b, a) - self.anm_score(a, b)

def predict_proba ( self , a , b , ** kwargs ) : a = scale ( a ) . reshape ( ( - 1 , 1 ) ) b = scale ( b ) . reshape ( ( - 1 , 1 ) ) return self . anm_score ( b , a ) - self . anm_score ( a , b )

Prediction method for pairwise causal inference using the ANM model .


def anm_score(self, x, y):
        """Compute the fitness score of the ANM model in the x->y direction.

        Args:
            a (numpy.ndarray): Variable seen as cause
            b (numpy.ndarray): Variable seen as effect

        Returns:
            float: ANM fit score
        """
        gp = GaussianProcessRegressor().fit(x, y)
        y_predict = gp.predict(x)
        indepscore = normalized_hsic(y_predict - y, x)

        return indepscore

def anm_score ( self , x , y ) : gp = GaussianProcessRegressor ( ) . fit ( x , y ) y_predict = gp . predict ( x ) indepscore = normalized_hsic ( y_predict - y , x ) return indepscore

Compute the fitness score of the ANM model in the x - > y direction .


def orient_undirected_graph(self, data, graph, **kwargs):
        """Run PC on an undirected graph.

        Args:
            data (pandas.DataFrame): DataFrame containing the data
            graph (networkx.Graph): Skeleton of the graph to orient

        Returns:
            networkx.DiGraph: Solution given by PC on the given skeleton.
        """
        # Building setup w/ arguments.
        self.arguments['{CITEST}'] = self.dir_CI_test[self.CI_test]
        self.arguments['{METHOD_INDEP}'] = self.dir_method_indep[self.method_indep]
        self.arguments['{DIRECTED}'] = 'TRUE'
        self.arguments['{ALPHA}'] = str(self.alpha)
        self.arguments['{NJOBS}'] = str(self.nb_jobs)
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()

        fe = DataFrame(nx.adj_matrix(graph, weight=None).todense())
        fg = DataFrame(1 - fe.values)

        results = self._run_pc(data, fixedEdges=fe, fixedGaps=fg, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

def orient_undirected_graph ( self , data , graph , ** kwargs ) : self . arguments [ '{CITEST}' ] = self . dir_CI_test [ self . CI_test ] self . arguments [ '{METHOD_INDEP}' ] = self . dir_method_indep [ self . method_indep ] self . arguments [ '{DIRECTED}' ] = 'TRUE' self . arguments [ '{ALPHA}' ] = str ( self . alpha ) self . arguments [ '{NJOBS}' ] = str ( self . nb_jobs ) self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) fe = DataFrame ( nx . adj_matrix ( graph , weight = None ) . todense ( ) ) fg = DataFrame ( 1 - fe . values ) results = self . _run_pc ( data , fixedEdges = fe , fixedGaps = fg , verbose = self . verbose ) return nx . relabel_nodes ( nx . DiGraph ( results ) , { idx : i for idx , i in enumerate ( data . columns ) } )


def create_graph_from_data(self, data, **kwargs):
        """Run the PC algorithm.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by PC on the given data.
       """
        # Building setup w/ arguments.
        self.arguments['{CITEST}'] = self.dir_CI_test[self.CI_test]
        self.arguments['{METHOD_INDEP}'] = self.dir_method_indep[self.method_indep]
        self.arguments['{DIRECTED}'] = 'TRUE'
        self.arguments['{ALPHA}'] = str(self.alpha)
        self.arguments['{NJOBS}'] = str(self.nb_jobs)
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()

        results = self._run_pc(data, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

def create_graph_from_data ( self , data , ** kwargs ) : self . arguments [ '{CITEST}' ] = self . dir_CI_test [ self . CI_test ] self . arguments [ '{METHOD_INDEP}' ] = self . dir_method_indep [ self . method_indep ] self . arguments [ '{DIRECTED}' ] = 'TRUE' self . arguments [ '{ALPHA}' ] = str ( self . alpha ) self . arguments [ '{NJOBS}' ] = str ( self . nb_jobs ) self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) results = self . _run_pc ( data , verbose = self . verbose ) return nx . relabel_nodes ( nx . DiGraph ( results ) , { idx : i for idx , i in enumerate ( data . columns ) } )


def _run_pc(self, data, fixedEdges=None, fixedGaps=None, verbose=True):
        """Setting up and running pc with all arguments."""
        # Checking coherence of arguments
        # print(self.arguments)
        if (self.arguments['{CITEST}'] == self.dir_CI_test['hsic']
           and self.arguments['{METHOD_INDEP}'] == self.dir_method_indep['corr']):
            warnings.warn('Selected method for indep is unfit for the hsic test,'
                          ' setting the hsic.gamma method.')
            self.arguments['{METHOD_INDEP}'] = self.dir_method_indep['hsic_gamma']

        elif (self.arguments['{CITEST}'] == self.dir_CI_test['gaussian']
              and self.arguments['{METHOD_INDEP}'] != self.dir_method_indep['corr']):
            warnings.warn('Selected method for indep is unfit for the selected test,'
                          ' setting the classic correlation-based method.')
            self.arguments['{METHOD_INDEP}'] = self.dir_method_indep['corr']

        # Run PC
        id = str(uuid.uuid4())
        os.makedirs('/tmp/cdt_pc' + id + '/')
        self.arguments['{FOLDER}'] = '/tmp/cdt_pc' + id + '/'

        def retrieve_result():
            return read_csv('/tmp/cdt_pc' + id + '/result.csv', delimiter=',').values

        try:
            data.to_csv('/tmp/cdt_pc' + id + '/data.csv', header=False, index=False)
            if fixedGaps is not None and fixedEdges is not None:
                fixedGaps.to_csv('/tmp/cdt_pc' + id + '/fixedgaps.csv', index=False, header=False)
                fixedEdges.to_csv('/tmp/cdt_pc' + id + '/fixededges.csv', index=False, header=False)
                self.arguments['{SKELETON}'] = 'TRUE'
            else:
                self.arguments['{SKELETON}'] = 'FALSE'

            pc_result = launch_R_script("{}/R_templates/pc.R".format(os.path.dirname(os.path.realpath(__file__))),
                                        self.arguments, output_function=retrieve_result, verbose=verbose)
        # Cleanup
        except Exception as e:
            rmtree('/tmp/cdt_pc' + id + '')
            raise e
        except KeyboardInterrupt:
            rmtree('/tmp/cdt_pc' + id + '/')
            raise KeyboardInterrupt
        rmtree('/tmp/cdt_pc' + id + '')
        return pc_result

Setting up and running pc with all arguments .


def predict(self, data, alpha=0.01, max_iter=2000, **kwargs):
        """ Predict the graph skeleton.

        Args:
            data (pandas.DataFrame): observational data
            alpha (float): regularization parameter
            max_iter (int): maximum number of iterations

        Returns:
            networkx.Graph: Graph skeleton
        """
        edge_model = GraphLasso(alpha=alpha, max_iter=max_iter)
        edge_model.fit(data.values)

        return nx.relabel_nodes(nx.DiGraph(edge_model.get_precision()),
                                {idx: i for idx, i in enumerate(data.columns)})

def predict ( self , data , alpha = 0.01 , max_iter = 2000 , ** kwargs ) : edge_model = GraphLasso ( alpha = alpha , max_iter = max_iter ) edge_model . fit ( data . values ) return nx . relabel_nodes ( nx . DiGraph ( edge_model . get_precision ( ) ) , { idx : i for idx , i in enumerate ( data . columns ) } )


def autoset_settings(set_var):
    """Autoset GPU parameters using CUDA_VISIBLE_DEVICES variables.

    Return default config if variable not set.
    :param set_var: Variable to set. Must be of type ConfigSettings
    """
    try:
        devices = ast.literal_eval(os.environ["CUDA_VISIBLE_DEVICES"])
        if type(devices) != list and type(devices) != tuple:
            devices = [devices]
        if len(devices) != 0:
            set_var.GPU = len(devices)
            set_var.NB_JOBS = len(devices)
            warnings.warn("Detecting CUDA devices : {}".format(devices))

    except KeyError:
        set_var.GPU = check_cuda_devices()
        set_var.NB_JOBS = set_var.GPU
        warnings.warn("Detecting {} CUDA devices.".format(set_var.GPU))
        if not set_var.GPU:
            warnings.warn("No GPU automatically detected. Setting SETTINGS.GPU to 0, " +
                          "and SETTINGS.NB_JOBS to cpu_count.")
            set_var.GPU = 0
            set_var.NB_JOBS = multiprocessing.cpu_count()

    return set_var

Autoset GPU parameters using CUDA_VISIBLE_DEVICES variables .


def check_cuda_devices():
    """Output some information on CUDA-enabled devices on your computer,
    including current memory usage. Modified to only get number of devices.

    It's a port of https://gist.github.com/f0k/0d6431e3faa60bffc788f8b4daa029b1
    from C to Python with ctypes, so it can run without compiling
    anything. Note that this is a direct translation with no attempt to
    make the code Pythonic. It's meant as a general demonstration on how
    to obtain CUDA device information from Python without resorting to
    nvidia-smi or a compiled Python extension.

    .. note:: Author: Jan Schlüter, https://gist.github.com/63a664160d016a491b2cbea15913d549.git
    """
    import ctypes

    # Some constants taken from cuda.h
    CUDA_SUCCESS = 0

    libnames = ('libcuda.so', 'libcuda.dylib', 'cuda.dll')
    for libname in libnames:
        try:
            cuda = ctypes.CDLL(libname)
        except OSError:
            continue
        else:
            break
    else:
        # raise OSError("could not load any of: " + ' '.join(libnames))
        return 0

    nGpus = ctypes.c_int()
    error_str = ctypes.c_char_p()

    result = cuda.cuInit(0)
    if result != CUDA_SUCCESS:
        cuda.cuGetErrorString(result, ctypes.byref(error_str))
        # print("cuInit failed with error code %d: %s" % (result, error_str.value.decode()))
        return 0
    result = cuda.cuDeviceGetCount(ctypes.byref(nGpus))
    if result != CUDA_SUCCESS:
        cuda.cuGetErrorString(result, ctypes.byref(error_str))
        # print("cuDeviceGetCount failed with error code %d: %s" % (result, error_str.value.decode()))
        return 0
    # print("Found %d device(s)." % nGpus.value)
    return nGpus.value

def check_cuda_devices ( ) : import ctypes CUDA_SUCCESS = 0 libnames = ( 'libcuda.so' , 'libcuda.dylib' , 'cuda.dll' ) for libname in libnames : try : cuda = ctypes . CDLL ( libname ) except OSError : continue else : break else : return 0 nGpus = ctypes . c_int ( ) error_str = ctypes . c_char_p ( ) result = cuda . cuInit ( 0 ) if result != CUDA_SUCCESS : cuda . cuGetErrorString ( result , ctypes . byref ( error_str ) ) return 0 result = cuda . cuDeviceGetCount ( ctypes . byref ( nGpus ) ) if result != CUDA_SUCCESS : cuda . cuGetErrorString ( result , ctypes . byref ( error_str ) ) return 0 return nGpus . value

Output some information on CUDA - enabled devices on your computer including current memory usage . Modified to only get number of devices .


def get_default(self, *args, **kwargs):
        """Get the default parameters as defined in the Settings instance.

        This function proceeds to seamlessly retrieve the argument to pass
        through, depending on either it was overidden or not: If no argument
        was overridden in a function of the toolbox, the default argument will
        be set to ``None``, and this function will retrieve the default
        parameters as defined by the ``cdt.SETTINGS`` 's attributes.

        It has two modes of processing:

        1. **kwargs for retrieving a single argument: ``get_default(argument_name=value)``.
        2. *args through a list of tuples of the shape ``('argument_name', value)`` to retrieve multiple values at once.
        """
        def retrieve_param(i):
            try:
                return self.__getattribute__(i)
            except AttributeError:
                if i == "device":
                    return self.default_device
                else:
                    return self.__getattribute__(i.upper())
        if len(args) == 0:
            if len(kwargs) == 1 and kwargs[list(kwargs.keys())[0]] is not None:
                return kwargs[list(kwargs.keys())[0]]
            elif len(kwargs) == 1:
                return retrieve_param(list(kwargs.keys())[0])
            else:
                raise TypeError("As dict is unordered, it is impossible to give"
                                "the parameters in the correct order.")
        else:
            out = []
            for i in args:
                if i[1] is None:
                    out.append(retrieve_param(i[0]))
                else:
                    out.append(i[1])
            return out

Get the default parameters as defined in the Settings instance .


def read_causal_pairs(filename, scale=True, **kwargs):
    """Convert a ChaLearn Cause effect pairs challenge format into numpy.ndarray.

    :param filename: path of the file to read or DataFrame containing the data
    :type filename: str or pandas.DataFrame
    :param scale: Scale the data
    :type scale: bool
    :param kwargs: parameters to be passed to pandas.read_csv
    :return: Dataframe composed of (SampleID, a (numpy.ndarray) , b (numpy.ndarray))
    :rtype: pandas.DataFrame
    """
    def convert_row(row, scale):
        """Convert a CCEPC row into numpy.ndarrays.

        :param row:
        :type row: pandas.Series
        :return: tuple of sample ID and the converted data into numpy.ndarrays
        :rtype: tuple
        """
        a = row["A"].split(" ")
        b = row["B"].split(" ")

        if a[0] == "":
            a.pop(0)
            b.pop(0)
        if a[-1] == "":
            a.pop(-1)
            b.pop(-1)

        a = array([float(i) for i in a])
        b = array([float(i) for i in b])
        if scale:
            a = scaler(a)
            b = scaler(b)
        return row['SampleID'], a, b
    if isinstance(filename, str):
        data = read_csv(filename, **kwargs)
    elif isinstance(filename, DataFrame):
        data = filename
    else:
        raise TypeError("Type not supported.")
    conv_data = []

    for idx, row in data.iterrows():
        conv_data.append(convert_row(row, scale))
    df = DataFrame(conv_data, columns=['SampleID', 'A', 'B'])
    df = df.set_index("SampleID")
    return df

def
read_causal_pairs
(
filename
,
scale
=
True
,
**
kwargs
)
:
def
convert_row
(
row
,
scale
)
:
a
=
row
[
"A"
]
.
split
(
" "
)
b
=
row
[
"B"
]
.
split
(
" "
)
if
a
[
0
]
==
""
:
a
.
pop
(
0
)
b
.
pop
(
0
)
if
a
[
1
]
==
""
:
a
.
pop
(
1
)
b
.
pop
(
1
)
a
=
array
(
[
float
(
i
)
for
i
in
a
]
)
b
=
array
(
[
float
(
i
)
for
i
in
b
]
)
if
scale
:
a
=
scaler
(
a
)
b
=
scaler
(
b
)
return
row
[
'SampleID'
]
,
a
,
b
if
isinstance
(
filename
,
str
)
:
data
=
read_csv
(
filename
,
**
kwargs
)
elif
isinstance
(
filename
,
DataFrame
)
:
data
=
filename
else
:
raise
TypeError
(
"Type not supported."
)
conv_data
=
[
]
for
idx
,
row
in
data
.
iterrows
(
)
:
conv_data
.
append
(
convert_row
(
row
,
scale
)
)
df
=
DataFrame
(
conv_data
,
columns
=
[
'SampleID'
,
'A'
,
'B'
]
)
df
=
df
.
set_index
(
"SampleID"
)
return
df

Convert a ChaLearn Cause effect pairs challenge format into numpy . ndarray .


def forward(self, pred, target):
        """Compute the loss model.

        :param pred: predicted Variable
        :param target: Target Variable
        :return: Loss
        """
        loss = th.FloatTensor([0])
        for i in range(1, self.moments):
            mk_pred = th.mean(th.pow(pred, i), 0)
            mk_tar = th.mean(th.pow(target, i), 0)

            loss.add_(th.mean((mk_pred - mk_tar) ** 2))  # L2

        return loss

def forward ( self , pred , target ) : loss = th . FloatTensor ( [ 0 ] ) for i in range ( 1 , self . moments ) : mk_pred = th . mean ( th . pow ( pred , i ) , 0 ) mk_tar = th . mean ( th . pow ( target , i ) , 0 ) loss . add_ ( th . mean ( ( mk_pred - mk_tar ) ** 2 ) ) return loss


def predict(self, x, *args, **kwargs):
        """Generic predict method, chooses which subfunction to use for a more
        suited.

        Depending on the type of `x` and of `*args`, this function process to execute
        different functions in the priority order:

        1. If ``args[0]`` is a ``networkx.(Di)Graph``, then ``self.orient_graph`` is executed.
        2. If ``args[0]`` exists, then ``self.predict_proba`` is executed.
        3. If ``x`` is a ``pandas.DataFrame``, then ``self.predict_dataset`` is executed.
        4. If ``x`` is a ``pandas.Series``, then ``self.predict_proba`` is executed.

        Args:
            x (numpy.array or pandas.DataFrame or pandas.Series): First variable or dataset.
            args (numpy.array or networkx.Graph): graph or second variable.

        Returns:
            pandas.Dataframe or networkx.Digraph: predictions output
        """
        if len(args) > 0:
            if type(args[0]) == nx.Graph or type(args[0]) == nx.DiGraph:
                return self.orient_graph(x, *args, **kwargs)
            else:
                return self.predict_proba(x, *args, **kwargs)
        elif type(x) == DataFrame:
            return self.predict_dataset(x, *args, **kwargs)
        elif type(x) == Series:
            return self.predict_proba(x.iloc[0], x.iloc[1], *args, **kwargs)

def predict ( self , x , * args , ** kwargs ) : if len ( args ) > 0 : if type ( args [ 0 ] ) == nx . Graph or type ( args [ 0 ] ) == nx . DiGraph : return self . orient_graph ( x , * args , ** kwargs ) else : return self . predict_proba ( x , * args , ** kwargs ) elif type ( x ) == DataFrame : return self . predict_dataset ( x , * args , ** kwargs ) elif type ( x ) == Series : return self . predict_proba ( x . iloc [ 0 ] , x . iloc [ 1 ] , * args , ** kwargs )

Generic predict method chooses which subfunction to use for a more suited .


def predict_dataset(self, x, **kwargs):
        """Generic dataset prediction function.

        Runs the score independently on all pairs.

        Args:
            x (pandas.DataFrame): a CEPC format Dataframe.
            kwargs (dict): additional arguments for the algorithms

        Returns:
            pandas.DataFrame: a Dataframe with the predictions.
        """
        printout = kwargs.get("printout", None)
        pred = []
        res = []
        x.columns = ["A", "B"]
        for idx, row in x.iterrows():
            a = scale(row['A'].reshape((len(row['A']), 1)))
            b = scale(row['B'].reshape((len(row['B']), 1)))

            pred.append(self.predict_proba(a, b, idx=idx))

            if printout is not None:
                res.append([row['SampleID'], pred[-1]])
                DataFrame(res, columns=['SampleID', 'Predictions']).to_csv(
                    printout, index=False)
        return pred

def predict_dataset ( self , x , ** kwargs ) : printout = kwargs . get ( "printout" , None ) pred = [ ] res = [ ] x . columns = [ "A" , "B" ] for idx , row in x . iterrows ( ) : a = scale ( row [ 'A' ] . reshape ( ( len ( row [ 'A' ] ) , 1 ) ) ) b = scale ( row [ 'B' ] . reshape ( ( len ( row [ 'B' ] ) , 1 ) ) ) pred . append ( self . predict_proba ( a , b , idx = idx ) ) if printout is not None : res . append ( [ row [ 'SampleID' ] , pred [ - 1 ] ] ) DataFrame ( res , columns = [ 'SampleID' , 'Predictions' ] ) . to_csv ( printout , index = False ) return pred


def orient_graph(self, df_data, graph, nb_runs=6, printout=None, **kwargs):
        """Orient an undirected graph using the pairwise method defined by the subclass.

        The pairwise method is ran on every undirected edge.

        Args:
            df_data (pandas.DataFrame): Data
            umg (networkx.Graph): Graph to orient
            nb_runs (int): number of times to rerun for each pair (bootstrap)
            printout (str): (optional) Path to file where to save temporary results

        Returns:
            networkx.DiGraph: a directed graph, which might contain cycles

        .. warning:
           Requirement : Name of the nodes in the graph correspond to name of
           the variables in df_data
        """
        if type(graph) == nx.DiGraph:
            edges = [a for a in list(graph.edges()) if (a[1], a[0]) in list(graph.edges())]
            oriented_edges = [a for a in list(graph.edges()) if (a[1], a[0]) not in list(graph.edges())]
            for a in edges:
                if (a[1], a[0]) in list(graph.edges()):
                    edges.remove(a)
            output = nx.DiGraph()
            for i in oriented_edges:
                output.add_edge(*i)

        elif type(graph) == nx.Graph:
            edges = list(graph.edges())
            output = nx.DiGraph()

        else:
            raise TypeError("Data type not understood.")

        res = []

        for idx, (a, b) in enumerate(edges):
            weight = self.predict_proba(
                df_data[a].values.reshape((-1, 1)), df_data[b].values.reshape((-1, 1)), idx=idx,
                nb_runs=nb_runs, **kwargs)
            if weight > 0:  # a causes b
                output.add_edge(a, b, weight=weight)
            else:
                output.add_edge(b, a, weight=abs(weight))
            if printout is not None:
                res.append([str(a) + '-' + str(b), weight])
                DataFrame(res, columns=['SampleID', 'Predictions']).to_csv(
                    printout, index=False)

        for node in list(df_data.columns.values):
            if node not in output.nodes():
                output.add_node(node)

        return output

def
orient_graph
(
self
,
df_data
,
graph
,
nb_runs
=
6
,
printout
=
,
**
kwargs
)
:
if
type
(
graph
)
==
nx
.
DiGraph
:
edges
=
[
a
for
a
in
list
(
graph
.
edges
(
)
)
if
(
a
[
1
]
,
a
[
0
]
)
in
list
(
graph
.
edges
(
)
)
]
oriented_edges
=
[
a
for
a
in
list
(
graph
.
edges
(
)
)
if
(
a
[
1
]
,
a
[
0
]
)
not
in
list
(
graph
.
edges
(
)
)
]
for
a
in
edges
:
if
(
a
[
1
]
,
a
[
0
]
)
in
list
(
graph
.
edges
(
)
)
:
edges
.
remove
(
a
)
output
=
nx
.
DiGraph
(
)
for
i
in
oriented_edges
:
output
.
add_edge
(
*
i
)
elif
type
(
graph
)
==
nx
.
Graph
:
edges
=
list
(
graph
.
edges
(
)
)
output
=
nx
.
DiGraph
(
)
else
:
raise
TypeError
(
"Data type not understood."
)
res
=
[
]
for
idx
,
(
a
,
b
)
in
enumerate
(
edges
)
:
weight
=
self
.
predict_proba
(
df_data
[
a
]
.
values
.
reshape
(
(
1
,
1
)
)
,
df_data
[
b
]
.
values
.
reshape
(
(
1
,
1
)
)
,
idx
=
idx
,
nb_runs
=
nb_runs
,
**
kwargs
)
if
weight
>
0
:
output
.
add_edge
(
a
,
b
,
weight
=
weight
)
else
:
output
.
add_edge
(
b
,
a
,
weight
=
abs
(
weight
)
)
if
printout
is
not
:
res
.
append
(
[
str
(
a
)
+
'-'
+
str
(
b
)
,
weight
]
)
DataFrame
(
res
,
columns
=
[
'SampleID'
,
'Predictions'
]
)
.
to_csv
(
printout
,
index
=
False
)
for
node
in
list
(
df_data
.
columns
.
values
)
:
if
node
not
in
output
.
nodes
(
)
:
output
.
add_node
(
node
)
return
output

Orient an undirected graph using the pairwise method defined by the subclass .


def orient_undirected_graph(self, data, graph):
        """Run the algorithm on an undirected graph.

        Args:
            data (pandas.DataFrame): DataFrame containing the data
            graph (networkx.Graph): Skeleton of the graph to orient

        Returns:
            networkx.DiGraph: Solution on the given skeleton.

        """
        # Building setup w/ arguments.
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        self.arguments['{SCORE}'] = self.score
        self.arguments['{BETA}'] = str(self.beta)
        self.arguments['{OPTIM}'] = str(self.optim).upper()
        self.arguments['{ALPHA}'] = str(self.alpha)

        whitelist = DataFrame(list(nx.edges(graph)), columns=["from", "to"])
        blacklist = DataFrame(list(nx.edges(nx.DiGraph(DataFrame(-nx.adj_matrix(graph, weight=None).to_dense() + 1,
                                                                 columns=list(graph.nodes()),
                                                                 index=list(graph.nodes()))))), columns=["from", "to"])
        results = self._run_bnlearn(data, whitelist=whitelist,
                                   blacklist=blacklist, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

def orient_undirected_graph ( self , data , graph ) : self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) self . arguments [ '{SCORE}' ] = self . score self . arguments [ '{BETA}' ] = str ( self . beta ) self . arguments [ '{OPTIM}' ] = str ( self . optim ) . upper ( ) self . arguments [ '{ALPHA}' ] = str ( self . alpha ) whitelist = DataFrame ( list ( nx . edges ( graph ) ) , columns = [ "from" , "to" ] ) blacklist = DataFrame ( list ( nx . edges ( nx . DiGraph ( DataFrame ( - nx . adj_matrix ( graph , weight = None ) . to_dense ( ) + 1 , columns = list ( graph . nodes ( ) ) , index = list ( graph . nodes ( ) ) ) ) ) ) , columns = [ "from" , "to" ] ) results = self . _run_bnlearn ( data , whitelist = whitelist , blacklist = blacklist , verbose = self . verbose ) return nx . relabel_nodes ( nx . DiGraph ( results ) , { idx : i for idx , i in enumerate ( data . columns ) } )

Run the algorithm on an undirected graph .


def orient_directed_graph(self, data, graph):
        """Run the algorithm on a directed_graph.

        Args:
            data (pandas.DataFrame): DataFrame containing the data
            graph (networkx.DiGraph): Skeleton of the graph to orient

        Returns:
            networkx.DiGraph: Solution on the given skeleton.

        .. warning::
           The algorithm is ran on the skeleton of the given graph.

        """
        warnings.warn("The algorithm is ran on the skeleton of the given graph.")
        return self.orient_undirected_graph(data, nx.Graph(graph))


def create_graph_from_data(self, data):
        """Run the algorithm on data.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by the algorithm.

        """
        # Building setup w/ arguments.
        self.arguments['{SCORE}'] = self.score
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        self.arguments['{BETA}'] = str(self.beta)
        self.arguments['{OPTIM}'] = str(self.optim).upper()
        self.arguments['{ALPHA}'] = str(self.alpha)

        results = self._run_bnlearn(data, verbose=self.verbose)
        graph = nx.DiGraph()
        graph.add_edges_from(results)
        return graph

def create_graph_from_data ( self , data ) : self . arguments [ '{SCORE}' ] = self . score self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) self . arguments [ '{BETA}' ] = str ( self . beta ) self . arguments [ '{OPTIM}' ] = str ( self . optim ) . upper ( ) self . arguments [ '{ALPHA}' ] = str ( self . alpha ) results = self . _run_bnlearn ( data , verbose = self . verbose ) graph = nx . DiGraph ( ) graph . add_edges_from ( results ) return graph


def computeGaussKernel(x):
    """Compute the gaussian kernel on a 1D vector."""
    xnorm = np.power(euclidean_distances(x, x), 2)
    return np.exp(-xnorm / (2.0))

def computeGaussKernel ( x ) : xnorm = np . power ( euclidean_distances ( x , x ) , 2 ) return np . exp ( - xnorm / ( 2.0 ) )

Compute the gaussian kernel on a 1D vector .


def normal_noise(points):
    """Init a noise variable."""
    return np.random.rand(1) * np.random.randn(points, 1) \
        + random.sample([2, -2], 1)

def normal_noise ( points ) : return np . random . rand ( 1 ) * np . random . randn ( points , 1 ) + random . sample ( [ 2 , - 2 ] , 1 )


def uniform_noise(points):
    """Init a uniform noise variable."""
    return np.random.rand(1) * np.random.uniform(points, 1) \
        + random.sample([2, -2], 1)

def uniform_noise ( points ) : return np . random . rand ( 1 ) * np . random . uniform ( points , 1 ) + random . sample ( [ 2 , - 2 ] , 1 )


def predict_dataset(self, df):
        """Runs Jarfo independently on all pairs.

        Args:
            x (pandas.DataFrame): a CEPC format Dataframe.
            kwargs (dict): additional arguments for the algorithms

        Returns:
            pandas.DataFrame: a Dataframe with the predictions.
        """
        if len(list(df.columns)) == 2:
            df.columns = ["A", "B"]
        if self.model is None:
            raise AssertionError("Model has not been trained before predictions")
        df2 = DataFrame()

        for idx, row in df.iterrows():
            df2 = df2.append(row, ignore_index=True)
            df2 = df2.append({'A': row["B"], 'B': row["A"]}, ignore_index=True)
        return predict.predict(deepcopy(df2), deepcopy(self.model))[::2]


def predict_proba(self, a, b, idx=0, **kwargs):
        """ Use Jarfo to predict the causal direction of a pair of vars.

        Args:
            a (numpy.ndarray): Variable 1
            b (numpy.ndarray): Variable 2
            idx (int): (optional) index number for printing purposes

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        return self.predict_dataset(DataFrame([[a, b]],
                                              columns=['A', 'B']))

def predict_proba ( self , a , b , idx = 0 , ** kwargs ) : return self . predict_dataset ( DataFrame ( [ [ a , b ] ] , columns = [ 'A' , 'B' ] ) )

Use Jarfo to predict the causal direction of a pair of vars .


def clr(M, **kwargs):
    """Implementation of the Context Likelihood or Relatedness Network algorithm.

    Args:
     mat (numpy.ndarray): matrix, if it is a square matrix, the program assumes
         it is a relevance matrix where mat(i,j) represents the similarity content
         between nodes i and j. Elements of matrix should be
         non-negative.

    Returns:
    mat_nd (numpy.ndarray): Output deconvolved matrix (direct dependency matrix). Its components
        represent direct edge weights of observed interactions.

    .. note::
       Ref:Jeremiah J. Faith, Boris Hayete, Joshua T. Thaden, Ilaria Mogno, Jamey
       Wierzbowski, Guillaume Cottarel, Simon Kasif, James J. Collins, and Timothy
       S. Gardner. Large-scale mapping and validation of escherichia coli
       transcriptional regulation from a compendium of expression profiles.
       PLoS Biology, 2007
    """
    R = np.zeros(M.shape)
    Id = [[0, 0] for i in range(M.shape[0])]
    for i in range(M.shape[0]):
        mu_i = np.mean(M[i, :])
        sigma_i = np.std(M[i, :])
        Id[i] = [mu_i, sigma_i]

    for i in range(M.shape[0]):
        for j in range(i + 1, M.shape[0]):
            z_i = np.max([0, (M[i, j] - Id[i][0]) / Id[i][0]])
            z_j = np.max([0, (M[i, j] - Id[j][0]) / Id[j][0]])
            R[i, j] = np.sqrt(z_i**2 + z_j**2)
            R[j, i] = R[i, j]  # Symmetric

    return R

def clr ( M , ** kwargs ) : R = np . zeros ( M . shape ) Id = [ [ 0 , 0 ] for i in range ( M . shape [ 0 ] ) ] for i in range ( M . shape [ 0 ] ) : mu_i = np . mean ( M [ i , : ] ) sigma_i = np . std ( M [ i , : ] ) Id [ i ] = [ mu_i , sigma_i ] for i in range ( M . shape [ 0 ] ) : for j in range ( i + 1 , M . shape [ 0 ] ) : z_i = np . max ( [ 0 , ( M [ i , j ] - Id [ i ] [ 0 ] ) / Id [ i ] [ 0 ] ] ) z_j = np . max ( [ 0 , ( M [ i , j ] - Id [ j ] [ 0 ] ) / Id [ j ] [ 0 ] ] ) R [ i , j ] = np . sqrt ( z_i ** 2 + z_j ** 2 ) R [ j , i ] = R [ i , j ] return R

Implementation of the Context Likelihood or Relatedness Network algorithm .


def aracne(m, **kwargs):
    """Implementation of the ARACNE algorithm.

    Args:
     mat (numpy.ndarray): matrix, if it is a square matrix, the program assumes
         it is a relevance matrix where mat(i,j) represents the similarity content
         between nodes i and j. Elements of matrix should be
         non-negative.

    Returns:
    mat_nd (numpy.ndarray): Output deconvolved matrix (direct dependency matrix). Its components
        represent direct edge weights of observed interactions.

    .. note::
       Ref: ARACNE: An Algorithm for the Reconstruction of Gene Regulatory Networks in a Mammalian Cellular Context
       Adam A Margolin, Ilya Nemenman, Katia Basso, Chris Wiggins, Gustavo Stolovitzky, Riccardo Dalla Favera and Andrea Califano
       DOI: https://doi.org/10.1186/1471-2105-7-S1-S7
    """
    I0 = kwargs.get('I0', 0.0)  # No default thresholding
    W0 = kwargs.get('W0', 0.05)

    # thresholding
    m = np.where(m > I0, m, 0)

    # Finding triplets and filtering them
    for i in range(m.shape[0]-2):
        for j in range(i+1, m.shape[0]-1):
            for k in range(j+1, m.shape[0]):
                triplet = [m[i, j], m[j, k], m[i, k]]
                min_index, min_value = min(enumerate(triplet), key=operator.itemgetter(1))
                if 0 < min_value < W0:
                    if min_index == 0:
                        m[i, j] = m[j, i] = 0.
                    elif min_index == 1:
                        m[j, k] = m[k, j] = 0.
                    else:
                        m[i, k] = m[k, i] = 0.
    return m

def aracne ( m , ** kwargs ) : I0 = kwargs . get ( 'I0' , 0.0 ) W0 = kwargs . get ( 'W0' , 0.05 ) m = np . where ( m > I0 , m , 0 ) for i in range ( m . shape [ 0 ] - 2 ) : for j in range ( i + 1 , m . shape [ 0 ] - 1 ) : for k in range ( j + 1 , m . shape [ 0 ] ) : triplet = [ m [ i , j ] , m [ j , k ] , m [ i , k ] ] min_index , min_value = min ( enumerate ( triplet ) , key = operator . itemgetter ( 1 ) ) if 0 < min_value < W0 : if min_index == 0 : m [ i , j ] = m [ j , i ] = 0. elif min_index == 1 : m [ j , k ] = m [ k , j ] = 0. else : m [ i , k ] = m [ k , i ] = 0. return m

Implementation of the ARACNE algorithm .


def remove_indirect_links(g, alg="aracne", **kwargs):
    """Apply deconvolution to a networkx graph.

    Args:
       g (networkx.Graph): Graph to apply deconvolution to
       alg (str): Algorithm to use ('aracne', 'clr', 'nd')
       kwargs (dict): extra options for algorithms

    Returns:
       networkx.Graph: graph with undirected links removed.
    """
    alg = {"aracne": aracne,
           "nd": network_deconvolution,
           "clr": clr}[alg]
    mat = np.array(nx.adjacency_matrix(g).todense())
    return nx.relabel_nodes(nx.DiGraph(alg(mat, **kwargs)),
                            {idx: i for idx, i in enumerate(list(g.nodes()))})

def remove_indirect_links ( g , alg = "aracne" , ** kwargs ) : alg = { "aracne" : aracne , "nd" : network_deconvolution , "clr" : clr } [ alg ] mat = np . array ( nx . adjacency_matrix ( g ) . todense ( ) ) return nx . relabel_nodes ( nx . DiGraph ( alg ( mat , ** kwargs ) ) , { idx : i for idx , i in enumerate ( list ( g . nodes ( ) ) ) } )

Apply deconvolution to a networkx graph .


def dagify_min_edge(g):
    """Input a graph and output a DAG.

    The heuristic is to reverse the edge with the lowest score of the cycle
    if possible, else remove it.

    Args:
        g (networkx.DiGraph): Graph to modify to output a DAG

    Returns:
        networkx.DiGraph: DAG made out of the input graph.
    """
    while not nx.is_directed_acyclic_graph(g):
        cycle = next(nx.simple_cycles(g))
        scores = []
        edges = []
        for i, j in zip(cycle[:1], cycle[:1]):
            edges.append((i, j))
            scores.append(g[i][j]['weight'])

        i, j = edges[scores.index(min(scores))]
        gc = deepcopy(g)
        gc.remove_edge(i, j)
        gc.add_edge(j, i)

        if len(list(nx.simple_cycles(gc))) < len(list(nx.simple_cycles(g))):
            g.add_edge(j, i, weight=min(scores))
        g.remove_edge(i, j)
    return g

def dagify_min_edge ( g ) : while not nx . is_directed_acyclic_graph ( g ) : cycle = next ( nx . simple_cycles ( g ) ) scores = [ ] edges = [ ] for i , j in zip ( cycle [ : 1 ] , cycle [ : 1 ] ) : edges . append ( ( i , j ) ) scores . append ( g [ i ] [ j ] [ 'weight' ] ) i , j = edges [ scores . index ( min ( scores ) ) ] gc = deepcopy ( g ) gc . remove_edge ( i , j ) gc . add_edge ( j , i ) if len ( list ( nx . simple_cycles ( gc ) ) ) < len ( list ( nx . simple_cycles ( g ) ) ) : g . add_edge ( j , i , weight = min ( scores ) ) g . remove_edge ( i , j ) return g


def weighted_mean_and_std(values, weights):
    """
    Returns the weighted average and standard deviation.

    values, weights -- numpy ndarrays with the same shape.
    """
    average = np.average(values, weights=weights, axis=0)
    variance = np.dot(weights, (values - average) ** 2) / weights.sum()  # Fast and numerically precise
    return (average, np.sqrt(variance))

def weighted_mean_and_std ( values , weights ) : average = np . average ( values , weights = weights , axis = 0 ) variance = np . dot ( weights , ( values - average ) ** 2 ) / weights . sum ( ) return ( average , np . sqrt ( variance ) )

Returns the weighted average and standard deviation .


def GNN_instance(x, idx=0, device=None, nh=20, **kwargs):
    """Run an instance of GNN, testing causal direction.

    :param m: data corresponding to the config : (N, 2) data, [:, 0] cause and [:, 1] effect
    :param pair_idx: print purposes
    :param run: numner of the run (for GPU dispatch)
    :param device: device on with the algorithm is going to be run on.
    :return:
    """
    device = SETTINGS.get_default(device=device)
    xy = scale(x).astype('float32')
    inputx = th.FloatTensor(xy[:, [0]]).to(device)
    target = th.FloatTensor(xy[:, [1]]).to(device)
    GNNXY = GNN_model(x.shape[0], device=device, nh=nh).to(device)
    GNNYX = GNN_model(x.shape[0], device=device, nh=nh).to(device)
    GNNXY.reset_parameters()
    GNNYX.reset_parameters()
    XY = GNNXY.run(inputx, target, **kwargs)
    YX = GNNYX.run(target, inputx, **kwargs)

    return [XY, YX]

def GNN_instance ( x , idx = 0 , device = None , nh = 20 , ** kwargs ) : device = SETTINGS . get_default ( device = device ) xy = scale ( x ) . astype ( 'float32' ) inputx = th . FloatTensor ( xy [ : , [ 0 ] ] ) . to ( device ) target = th . FloatTensor ( xy [ : , [ 1 ] ] ) . to ( device ) GNNXY = GNN_model ( x . shape [ 0 ] , device = device , nh = nh ) . to ( device ) GNNYX = GNN_model ( x . shape [ 0 ] , device = device , nh = nh ) . to ( device ) GNNXY . reset_parameters ( ) GNNYX . reset_parameters ( ) XY = GNNXY . run ( inputx , target , ** kwargs ) YX = GNNYX . run ( target , inputx , ** kwargs ) return [ XY , YX ]

Run an instance of GNN testing causal direction .


def forward(self, x):
        """Pass data through the net structure.

        :param x: input data: shape (:,1)
        :type x: torch.Variable
        :return: output of the shallow net
        :rtype: torch.Variable

        """
        self.noise.normal_()
        return self.layers(th.cat([x, self.noise], 1))

def forward ( self , x ) : self . noise . normal_ ( ) return self . layers ( th . cat ( [ x , self . noise ] , 1 ) )


def run(self, x, y, lr=0.01, train_epochs=1000, test_epochs=1000, idx=0, verbose=None, **kwargs):
        """Run the GNN on a pair x,y of FloatTensor data."""
        verbose = SETTINGS.get_default(verbose=verbose)
        optim = th.optim.Adam(self.parameters(), lr=lr)
        running_loss = 0
        teloss = 0

        for i in range(train_epochs + test_epochs):
            optim.zero_grad()
            pred = self.forward(x)
            loss = self.criterion(pred, y)
            running_loss += loss.item()

            if i < train_epochs:
                loss.backward()
                optim.step()
            else:
                teloss += running_loss

            # print statistics
            if verbose and not i % 300:
                print('Idx:{}; epoch:{}; score:{}'.
                      format(idx, i, running_loss/300))
                running_loss = 0.0

        return teloss / test_epochs

def
run
(
self
,
x
,
y
,
lr
=
0.01
,
train_epochs
=
1000
,
test_epochs
=
1000
,
idx
=
0
,
verbose
=
,
**
kwargs
)
:
verbose
=
SETTINGS
.
get_default
(
verbose
=
verbose
)
optim
=
th
.
optim
.
Adam
(
self
.
parameters
(
)
,
lr
=
lr
)
running_loss
=
0
teloss
=
0
for
i
in
range
(
train_epochs
+
test_epochs
)
:
optim
.
zero_grad
(
)
pred
=
self
.
forward
(
x
)
loss
=
self
.
criterion
(
pred
,
y
)
running_loss
+=
loss
.
item
(
)
if
i
<
train_epochs
:
loss
.
backward
(
)
optim
.
step
(
)
else
:
teloss
+=
running_loss
if
verbose
and
not
i
%
300
:
print
(
'Idx:{}; epoch:{}; score:{}'
.
format
(
idx
,
i
,
running_loss
/
300
)
)
running_loss
=
0.0
return
teloss
/
test_epochs

Run the GNN on a pair x y of FloatTensor data .


def predict_proba(self, a, b, nb_runs=6, nb_jobs=None, gpu=None,
                      idx=0, verbose=None, ttest_threshold=0.01,
                      nb_max_runs=16, train_epochs=1000, test_epochs=1000):
        """Run multiple times GNN to estimate the causal direction.

        Args:
            a (np.ndarray): Variable 1
            b (np.ndarray): Variable 2
            nb_runs (int): number of runs to execute per batch (before testing for significance with t-test).
            nb_jobs (int): number of runs to execute in parallel. (Initialized with ``cdt.SETTINGS.NB_JOBS``)
            gpu (bool): use gpu (Initialized with ``cdt.SETTINGS.GPU``)
            idx (int): (optional) index of the pair, for printing purposes
            verbose (bool): verbosity (Initialized with ``cdt.SETTINGS.verbose``)
            ttest_threshold (float): threshold to stop the boostraps before ``nb_max_runs`` if the difference is significant
            nb_max_runs (int): Max number of bootstraps
            train_epochs (int): Number of epochs during which the model is going to be trained
            test_epochs (int): Number of epochs during which the model is going to be tested

        Returns:
            float: Causal score of the pair (Value : 1 if a->b and -1 if b->a)
        """
        Nb_jobs, verbose, gpu = SETTINGS.get_default(('nb_jobs', nb_jobs), ('verbose', verbose), ('gpu', gpu))
        x = np.stack([a.ravel(), b.ravel()], 1)
        ttest_criterion = TTestCriterion(
            max_iter=nb_max_runs, runs_per_iter=nb_runs, threshold=ttest_threshold)

        AB = []
        BA = []

        while ttest_criterion.loop(AB, BA):
            if nb_jobs != 1:
                result_pair = Parallel(n_jobs=nb_jobs)(delayed(GNN_instance)(
                    x, idx=idx, device='cuda:{}'.format(run % gpu) if gpu else 'cpu',
                    verbose=verbose, train_epochs=train_epochs, test_epochs=test_epochs) for run in range(ttest_criterion.iter, ttest_criterion.iter + nb_runs))
            else:
                result_pair = [GNN_instance(x, idx=idx,
                                            device='cuda:0' if gpu else 'cpu',
                                            verbose=verbose,
                                            train_epochs=train_epochs,
                                            test_epochs=test_epochs)
                               for run in range(ttest_criterion.iter, ttest_criterion.iter + nb_runs)]
            AB.extend([runpair[0] for runpair in result_pair])
            BA.extend([runpair[1] for runpair in result_pair])

        if verbose:
            print("P-value after {} runs : {}".format(ttest_criterion.iter,
                                                      ttest_criterion.p_value))

        score_AB = np.mean(AB)
        score_BA = np.mean(BA)

        return (score_BA - score_AB) / (score_BA + score_AB)

def
predict_proba
(
self
,
a
,
b
,
nb_runs
=
6
,
nb_jobs
=
,
gpu
=
,
idx
=
0
,
verbose
=
,
ttest_threshold
=
0.01
,
nb_max_runs
=
16
,
train_epochs
=
1000
,
test_epochs
=
1000
)
:
Nb_jobs
,
verbose
,
gpu
=
SETTINGS
.
get_default
(
(
'nb_jobs'
,
nb_jobs
)
,
(
'verbose'
,
verbose
)
,
(
'gpu'
,
gpu
)
)
x
=
np
.
stack
(
[
a
.
ravel
(
)
,
b
.
ravel
(
)
]
,
1
)
ttest_criterion
=
TTestCriterion
(
max_iter
=
nb_max_runs
,
runs_per_iter
=
nb_runs
,
threshold
=
ttest_threshold
)
AB
=
[
]
BA
=
[
]
while
ttest_criterion
.
loop
(
AB
,
BA
)
:
if
nb_jobs
!=
1
:
result_pair
=
Parallel
(
n_jobs
=
nb_jobs
)
(
delayed
(
GNN_instance
)
(
x
,
idx
=
idx
,
device
=
'cuda:{}'
.
format
(
run
%
gpu
)
if
gpu
else
'cpu'
,
verbose
=
verbose
,
train_epochs
=
train_epochs
,
test_epochs
=
test_epochs
)
for
run
in
range
(
ttest_criterion
.
iter
,
ttest_criterion
.
iter
+
nb_runs
)
)
else
:
result_pair
=
[
GNN_instance
(
x
,
idx
=
idx
,
device
=
'cuda:0'
if
gpu
else
'cpu'
,
verbose
=
verbose
,
train_epochs
=
train_epochs
,
test_epochs
=
test_epochs
)
for
run
in
range
(
ttest_criterion
.
iter
,
ttest_criterion
.
iter
+
nb_runs
)
]
AB
.
extend
(
[
runpair
[
0
]
for
runpair
in
result_pair
]
)
BA
.
extend
(
[
runpair
[
1
]
for
runpair
in
result_pair
]
)
if
verbose
:
print
(
"P-value after {} runs : {}"
.
format
(
ttest_criterion
.
iter
,
ttest_criterion
.
p_value
)
)
score_AB
=
np
.
mean
(
AB
)
score_BA
=
np
.
mean
(
BA
)
return
(
score_BA
score_AB
)
/
(
score_BA
+
score_AB
)

Run multiple times GNN to estimate the causal direction .


def create_graph_from_data(self, data, **kwargs):
        """Apply causal discovery on observational data using CAM.

        Args:
            data (pandas.DataFrame): DataFrame containing the data

        Returns:
            networkx.DiGraph: Solution given by the CAM algorithm.
        """
        # Building setup w/ arguments.
        self.arguments['{SCORE}'] = self.scores[self.score]
        self.arguments['{CUTOFF}'] = str(self.cutoff)
        self.arguments['{VARSEL}'] = str(self.variablesel).upper()
        self.arguments['{SELMETHOD}'] = self.var_selection[self.selmethod]
        self.arguments['{PRUNING}'] = str(self.pruning).upper()
        self.arguments['{PRUNMETHOD}'] = self.var_selection[self.prunmethod]
        self.arguments['{NJOBS}'] = str(self.nb_jobs)
        self.arguments['{VERBOSE}'] = str(self.verbose).upper()
        results = self._run_cam(data, verbose=self.verbose)

        return nx.relabel_nodes(nx.DiGraph(results),
                                {idx: i for idx, i in enumerate(data.columns)})

def create_graph_from_data ( self , data , ** kwargs ) : self . arguments [ '{SCORE}' ] = self . scores [ self . score ] self . arguments [ '{CUTOFF}' ] = str ( self . cutoff ) self . arguments [ '{VARSEL}' ] = str ( self . variablesel ) . upper ( ) self . arguments [ '{SELMETHOD}' ] = self . var_selection [ self . selmethod ] self . arguments [ '{PRUNING}' ] = str ( self . pruning ) . upper ( ) self . arguments [ '{PRUNMETHOD}' ] = self . var_selection [ self . prunmethod ] self . arguments [ '{NJOBS}' ] = str ( self . nb_jobs ) self . arguments [ '{VERBOSE}' ] = str ( self . verbose ) . upper ( ) results = self . _run_cam ( data , verbose = self . verbose ) return nx . relabel_nodes ( nx . DiGraph ( results ) , { idx : i for idx , i in enumerate ( data . columns ) } )

Apply causal discovery on observational data using CAM .


def forward(self, x):
        """Passing data through the network.

        :param x: 2d tensor containing both (x,y) Variables
        :return: output of the net
        """

        features = self.conv(x).mean(dim=2)
        return self.dense(features)

def forward ( self , x ) : features = self . conv ( x ) . mean ( dim = 2 ) return self . dense ( features )


def predict_proba(self, a, b, device=None):
        """Infer causal directions using the trained NCC pairwise model.

        Args:
            a (numpy.ndarray): Variable 1
            b (numpy.ndarray): Variable 2
            device (str): Device to run the algorithm on (defaults to ``cdt.SETTINGS.default_device``)

        Returns:
            float: Causation score (Value : 1 if a->b and -1 if b->a)
        """
        device = SETTINGS.get_default(device=device)
        if self.model is None:
            print('Model has to be trained before doing any predictions')
            raise ValueError
        if len(np.array(a).shape) == 1:
            a = np.array(a).reshape((-1, 1))
            b = np.array(b).reshape((-1, 1))
        m = np.hstack((a, b))
        m = scale(m)
        m = m.astype('float32')
        m = th.from_numpy(m).t().unsqueeze(0)

        if th.cuda.is_available():
            m = m.cuda()

        return (self.model(m).data.cpu().numpy()-.5) * 2

Infer causal directions using the trained NCC pairwise model .


def phrase_to_filename(self, phrase):
        """Convert phrase to normilized file name."""
        # remove non-word characters
        name = re.sub(r"[^\w\s\.]", '', phrase.strip().lower())
        # replace whitespace with underscores
        name = re.sub(r"\s+", '_', name)

        return name + '.png'

def phrase_to_filename ( self , phrase ) : name = re . sub ( r"[^\w\s\.]" , '' , phrase . strip ( ) . lower ( ) ) name = re . sub ( r"\s+" , '_' , name ) return name + '.png'

Convert phrase to normilized file name .


def seed_url(self):
        """A URL that can be used to open the page.

        The URL is formatted from :py:attr:`URL_TEMPLATE`, which is then
        appended to :py:attr:`base_url` unless the template results in an
        absolute URL.

        :return: URL that can be used to open the page.
        :rtype: str

        """
        url = self.base_url
        if self.URL_TEMPLATE is not None:
            url = urlparse.urljoin(
                self.base_url, self.URL_TEMPLATE.format(**self.url_kwargs)
            )

        if not url:
            return None

        url_parts = list(urlparse.urlparse(url))
        query = urlparse.parse_qsl(url_parts[4])

        for k, v in self.url_kwargs.items():
            if v is None:
                continue
            if "{{{}}}".format(k) not in str(self.URL_TEMPLATE):
                for i in iterable(v):
                    query.append((k, i))

        url_parts[4] = urlencode(query)
        return urlparse.urlunparse(url_parts)

def seed_url ( self ) : url = self . base_url if self . URL_TEMPLATE is not None : url = urlparse . urljoin ( self . base_url , self . URL_TEMPLATE . format ( ** self . url_kwargs ) ) if not url : return None url_parts = list ( urlparse . urlparse ( url ) ) query = urlparse . parse_qsl ( url_parts [ 4 ] ) for k , v in self . url_kwargs . items ( ) : if v is None : continue if "{{{}}}" . format ( k ) not in str ( self . URL_TEMPLATE ) : for i in iterable ( v ) : query . append ( ( k , i ) ) url_parts [ 4 ] = urlencode ( query ) return urlparse . urlunparse ( url_parts )

A URL that can be used to open the page .


def open(self):
        """Open the page.

        Navigates to :py:attr:`seed_url` and calls :py:func:`wait_for_page_to_load`.

        :return: The current page object.
        :rtype: :py:class:`Page`
        :raises: UsageError

        """
        if self.seed_url:
            self.driver_adapter.open(self.seed_url)
            self.wait_for_page_to_load()
            return self
        raise UsageError("Set a base URL or URL_TEMPLATE to open this page.")


def wait_for_page_to_load(self):
        """Wait for the page to load."""
        self.wait.until(lambda _: self.loaded)
        self.pm.hook.pypom_after_wait_for_page_to_load(page=self)
        return self

def wait_for_page_to_load ( self ) : self . wait . until ( lambda _ : self . loaded ) self . pm . hook . pypom_after_wait_for_page_to_load ( page = self ) return self


def register():
    """ Register the Selenium specific driver implementation.

        This register call is performed by the init module if
        selenium is available.
    """
    registerDriver(
        ISelenium,
        Selenium,
        class_implements=[
            Firefox,
            Chrome,
            Ie,
            Edge,
            Opera,
            Safari,
            BlackBerry,
            PhantomJS,
            Android,
            Remote,
            EventFiringWebDriver,
        ],
    )

def register ( ) : registerDriver ( ISelenium , Selenium , class_implements = [ Firefox , Chrome , Ie , Edge , Opera , Safari , BlackBerry , PhantomJS , Android , Remote , EventFiringWebDriver , ] , )

Register the Selenium specific driver implementation .


def root(self):
        """Root element for the page region.

        Page regions should define a root element either by passing this on
        instantiation or by defining a :py:attr:`_root_locator` attribute. To
        reduce the chances of hitting :py:class:`~selenium.common.exceptions.StaleElementReferenceException`
        or similar you should use :py:attr:`_root_locator`, as this is looked up every
        time the :py:attr:`root` property is accessed.
        """
        if self._root is None and self._root_locator is not None:
            return self.page.find_element(*self._root_locator)
        return self._root

def root ( self ) : if self . _root is None and self . _root_locator is not None : return self . page . find_element ( * self . _root_locator ) return self . _root


def wait_for_region_to_load(self):
        """Wait for the page region to load."""
        self.wait.until(lambda _: self.loaded)
        self.pm.hook.pypom_after_wait_for_region_to_load(region=self)
        return self

def wait_for_region_to_load ( self ) : self . wait . until ( lambda _ : self . loaded ) self . pm . hook . pypom_after_wait_for_region_to_load ( region = self ) return self


def find_element(self, strategy, locator):
        """Finds an element on the page.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: An element.
        :rytpe: :py:class:`~selenium.webdriver.remote.webelement.WebElement` or :py:class:`~splinter.driver.webdriver.WebDriverElement`

        """
        return self.driver_adapter.find_element(strategy, locator, root=self.root)

def find_element ( self , strategy , locator ) : return self . driver_adapter . find_element ( strategy , locator , root = self . root )


def find_elements(self, strategy, locator):
        """Finds elements on the page.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target elements.
        :type strategy: str
        :type locator: str
        :return: List of :py:class:`~selenium.webdriver.remote.webelement.WebElement` or :py:class:`~splinter.element_list.ElementList`
        :rtype: list

        """
        return self.driver_adapter.find_elements(strategy, locator, root=self.root)

def find_elements ( self , strategy , locator ) : return self . driver_adapter . find_elements ( strategy , locator , root = self . root )


def is_element_present(self, strategy, locator):
        """Checks whether an element is present.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: ``True`` if element is present, else ``False``.
        :rtype: bool

        """
        return self.driver_adapter.is_element_present(strategy, locator, root=self.root)

def is_element_present ( self , strategy , locator ) : return self . driver_adapter . is_element_present ( strategy , locator , root = self . root )


def is_element_displayed(self, strategy, locator):
        """Checks whether an element is displayed.

        :param strategy: Location strategy to use. See :py:class:`~selenium.webdriver.common.by.By` or :py:attr:`~pypom.splinter_driver.ALLOWED_STRATEGIES`.
        :param locator: Location of target element.
        :type strategy: str
        :type locator: str
        :return: ``True`` if element is displayed, else ``False``.
        :rtype: bool

        """
        return self.driver_adapter.is_element_displayed(
            strategy, locator, root=self.root
        )

def is_element_displayed ( self , strategy , locator ) : return self . driver_adapter . is_element_displayed ( strategy , locator , root = self . root )

Checks whether an element is displayed .


def registerDriver(iface, driver, class_implements=[]):
    """ Register driver adapter used by page object"""
    for class_item in class_implements:
        classImplements(class_item, iface)

    component.provideAdapter(factory=driver, adapts=[iface], provides=IDriver)

def registerDriver ( iface , driver , class_implements = [ ] ) : for class_item in class_implements : classImplements ( class_item , iface ) component . provideAdapter ( factory = driver , adapts = [ iface ] , provides = IDriver )


def t_intnumber(self, t):
        r'-?\d+'
        t.value = int(t.value)
        t.type = 'NUMBER'
        return t

def t_intnumber ( self , t ) : r'-?\d+' t . value = int ( t . value ) t . type = 'NUMBER' return t


def t_stringdollar_rbrace(self, t):
        r'\}'
        t.lexer.braces -= 1

        if t.lexer.braces == 0:
            # End of the dollar brace, back to the rest of the string
            t.lexer.begin('string')

def t_stringdollar_rbrace ( self , t ) : r'\}' t . lexer . braces -= 1 if t . lexer . braces == 0 : t . lexer . begin ( 'string' )


def t_tabbedheredoc(self, t):
        r'<<-\S+\r?\n'
        t.lexer.is_tabbed = True
        self._init_heredoc(t)
        t.lexer.begin('tabbedheredoc')

def t_tabbedheredoc ( self , t ) : r'<<-\S+\r?\n' t . lexer . is_tabbed = True self . _init_heredoc ( t ) t . lexer . begin ( 'tabbedheredoc' )


def t_heredoc(self, t):
        r'<<\S+\r?\n'
        t.lexer.is_tabbed = False
        self._init_heredoc(t)
        t.lexer.begin('heredoc')

def t_heredoc ( self , t ) : r'<<\S+\r?\n' t . lexer . is_tabbed = False self . _init_heredoc ( t ) t . lexer . begin ( 'heredoc' )


def _pre_install():
    '''Initialize the parse table at install time'''

    # Generate the parsetab.dat file at setup time
    dat = join(setup_dir, 'src', 'hcl', 'parsetab.dat')
    if exists(dat):
        os.unlink(dat)

    sys.path.insert(0, join(setup_dir, 'src'))

    import hcl
    from hcl.parser import HclParser

    parser = HclParser()

def _pre_install ( ) : dat = join ( setup_dir , 'src' , 'hcl' , 'parsetab.dat' ) if exists ( dat ) : os . unlink ( dat ) sys . path . insert ( 0 , join ( setup_dir , 'src' ) ) import hcl from hcl . parser import HclParser parser = HclParser ( )


def append(self, linenumber, raw_text, cells):
        """Add another row of data from a test suite"""
        self.rows.append(Row(linenumber, raw_text, cells))

def append ( self , linenumber , raw_text , cells ) : self . rows . append ( Row ( linenumber , raw_text , cells ) )


def RobotFactory(path, parent=None):
    '''Return an instance of SuiteFile, ResourceFile, SuiteFolder

    Exactly which is returned depends on whether it's a file or
    folder, and if a file, the contents of the file. If there is a
    testcase table, this will return an instance of SuiteFile,
    otherwise it will return an instance of ResourceFile.
    '''

    if os.path.isdir(path):
        return SuiteFolder(path, parent)

    else:
        rf = RobotFile(path, parent)

        for table in rf.tables:
            if isinstance(table, TestcaseTable):
                rf.__class__ = SuiteFile
                return rf

        rf.__class__ = ResourceFile
        return rf

def RobotFactory ( path , parent = None ) : if os . path . isdir ( path ) : return SuiteFolder ( path , parent ) else : rf = RobotFile ( path , parent ) for table in rf . tables : if isinstance ( table , TestcaseTable ) : rf . __class__ = SuiteFile return rf rf . __class__ = ResourceFile return rf

Return an instance of SuiteFile ResourceFile SuiteFolder


def walk(self, *types):
        '''
        Iterator which visits all suites and suite files,
        yielding test cases and keywords
        '''
        requested = types if len(types) > 0 else [SuiteFile, ResourceFile, SuiteFolder, Testcase, Keyword]

        for thing in self.robot_files:
            if thing.__class__ in requested:
                yield thing
            if isinstance(thing, SuiteFolder):
                for child in thing.walk():
                    if child.__class__ in requested:
                        yield child
            else:
                for child in thing.walk(*types):
                    yield child

def walk ( self , * types ) : requested = types if len ( types ) > 0 else [ SuiteFile , ResourceFile , SuiteFolder , Testcase , Keyword ] for thing in self . robot_files : if thing . __class__ in requested : yield thing if isinstance ( thing , SuiteFolder ) : for child in thing . walk ( ) : if child . __class__ in requested : yield child else : for child in thing . walk ( * types ) : yield child

Iterator which visits all suites and suite files yielding test cases and keywords


def _load(self, path):

        '''
        The general idea is to do a quick parse, creating a list of
        tables. Each table is nothing more than a list of rows, with
        each row being a list of cells. Additional parsing such as
        combining rows into statements is done on demand. This first
        pass is solely to read in the plain text and organize it by table.
        '''

        self.tables = []
        current_table = DefaultTable(self)

        with Utf8Reader(path) as f:
            # N.B. the caller should be catching errors
            self.raw_text = f.read()

            f._file.seek(0) # bleh; wish this wasn't a private property
            matcher = Matcher(re.IGNORECASE)
            for linenumber, raw_text in enumerate(f.readlines()):
                linenumber += 1; # start counting at 1 rather than zero

                # this mimics what the robot TSV reader does --
                # it replaces non-breaking spaces with regular spaces,
                # and then strips trailing whitespace
                raw_text = raw_text.replace(u'\xA0', ' ')
                raw_text = raw_text.rstrip()

                # FIXME: I'm keeping line numbers but throwing away
                # where each cell starts. I should be preserving that
                # (though to be fair, robot is throwing that away so
                # I'll have to write my own splitter if I want to save
                # the character position)
                cells = TxtReader.split_row(raw_text)
                _heading_regex = r'^\s*\*+\s*(.*?)[ *]*$'

                if matcher(_heading_regex, cells[0]):
                    # we've found the start of a new table
                    table_name = matcher.group(1)
                    current_table = tableFactory(self, linenumber, table_name, raw_text)
                    self.tables.append(current_table)
                else:
                    current_table.append(Row(linenumber, raw_text, cells))

def
_load
(
self
,
path
)
:
self
.
tables
=
[
]
current_table
=
DefaultTable
(
self
)
with
Utf8Reader
(
path
)
as
f
:
self
.
raw_text
=
f
.
read
(
)
f
.
_file
.
seek
(
0
)
matcher
=
Matcher
(
re
.
IGNORECASE
)
for
linenumber
,
raw_text
in
enumerate
(
f
.
readlines
(
)
)
:
linenumber
+=
1
raw_text
=
raw_text
.
replace
(
u'\xA0'
,
' '
)
raw_text
=
raw_text
.
rstrip
(
)
cells
=
TxtReader
.
split_row
(
raw_text
)
_heading_regex
=
r'^\s*\*+\s*(.*?)[ *]*$'
if
matcher
(
_heading_regex
,
cells
[
0
]
)
:
table_name
=
matcher
.
group
(
1
)
current_table
=
tableFactory
(
self
,
linenumber
,
table_name
,
raw_text
)
self
.
tables
.
append
(
current_table
)
else
:
current_table
.
append
(
Row
(
linenumber
,
raw_text
,
cells
)
)

The general idea is to do a quick parse creating a list of tables . Each table is nothing more than a list of rows with each row being a list of cells . Additional parsing such as combining rows into statements is done on demand . This first pass is solely to read in the plain text and organize it by table .


def type(self):
        '''Return 'suite' or 'resource' or None

        This will return 'suite' if a testcase table is found;
        It will return 'resource' if at least one robot table
        is found. If no tables are found it will return None
        '''

        robot_tables = [table for table in self.tables if not isinstance(table, UnknownTable)]
        if len(robot_tables) == 0:
            return None

        for table in self.tables:
            if isinstance(table, TestcaseTable):
                return "suite"

        return "resource"

def type ( self ) : robot_tables = [ table for table in self . tables if not isinstance ( table , UnknownTable ) ] if len ( robot_tables ) == 0 : return None for table in self . tables : if isinstance ( table , TestcaseTable ) : return "suite" return "resource"


def keywords(self):
        '''Generator which returns all keywords in the suite'''
        for table in self.tables:
            if isinstance(table, KeywordTable):
                for keyword in table.keywords:
                    yield keyword

def keywords ( self ) : for table in self . tables : if isinstance ( table , KeywordTable ) : for keyword in table . keywords : yield keyword


def dump(self):
        '''Regurgitate the tables and rows'''
        for table in self.tables:
            print("*** %s ***" % table.name)
            table.dump()

def
dump
(
self
)
:
for
table
in
self
.
tables
:
print
(
"*** %s ***"
%
table
.
name
)
table
.
dump
(
)


def settings(self):
        '''Generator which returns all of the statements in all of the settings tables'''
        for table in self.tables:
            if isinstance(table, SettingTable):
                for statement in table.statements:
                    yield statement

def settings ( self ) : for table in self . tables : if isinstance ( table , SettingTable ) : for statement in table . statements : yield statement


def variables(self):
        '''Generator which returns all of the statements in all of the variables tables'''
        for table in self.tables:
            if isinstance(table, VariableTable):
                # FIXME: settings have statements, variables have rows WTF? :-(
                for statement in table.rows:
                    if statement[0] != "":
                        yield statement

def variables ( self ) : for table in self . tables : if isinstance ( table , VariableTable ) : for statement in table . rows : if statement [ 0 ] != "" : yield statement


def statements(self):
        '''Return a list of statements

        This is done by joining together any rows that
        have continuations
        '''
        # FIXME: no need to do this every time; we should cache the
        # result
        if len(self.rows) == 0:
            return []

        current_statement = Statement(self.rows[0])
        current_statement.startline = self.rows[0].linenumber
        current_statement.endline = self.rows[0].linenumber
        statements = []
        for row in self.rows[1:]:
            if len(row) > 0 and row[0] == "...":
                # we found a continuation
                current_statement += row[1:]
                current_statement.endline = row.linenumber
            else:
                if len(current_statement) > 0:
                    # append current statement to the list of statements...
                    statements.append(current_statement)
                # start a new statement
                current_statement = Statement(row)
                current_statement.startline = row.linenumber
                current_statement.endline = row.linenumber

        if len(current_statement) > 0:
            statements.append(current_statement)

        # trim trailing blank statements
        while (len(statements[-1]) == 0 or
               ((len(statements[-1]) == 1) and len(statements[-1][0]) == 0)):
            statements.pop()
        return statements

def statements ( self ) : if len ( self . rows ) == 0 : return [ ] current_statement = Statement ( self . rows [ 0 ] ) current_statement . startline = self . rows [ 0 ] . linenumber current_statement . endline = self . rows [ 0 ] . linenumber statements = [ ] for row in self . rows [ 1 : ] : if len ( row ) > 0 and row [ 0 ] == "..." : current_statement += row [ 1 : ] current_statement . endline = row . linenumber else : if len ( current_statement ) > 0 : statements . append ( current_statement ) current_statement = Statement ( row ) current_statement . startline = row . linenumber current_statement . endline = row . linenumber if len ( current_statement ) > 0 : statements . append ( current_statement ) while ( len ( statements [ - 1 ] ) == 0 or ( ( len ( statements [ - 1 ] ) == 1 ) and len ( statements [ - 1 ] [ 0 ] ) == 0 ) ) : statements . pop ( ) return statements


def append(self, row):
        '''
        The idea is, we recognize when we have a new testcase by
        checking the first cell. If it's not empty and not a comment,
        we have a new test case.

        '''
        if len(row) == 0:
            # blank line. Should we throw it away, or append a BlankLine object?
            return

        if (row[0] != "" and
            (not row[0].lstrip().startswith("#"))):
            # we have a new child table
            self._children.append(self._childClass(self.parent, row.linenumber, row[0]))
            if len(row.cells) > 1:
                # It appears the first row -- which contains the test case or
                # keyword name -- also has the first logical row of cells.
                # We'll create a Row, but we'll make the first cell empty instead
                # of leaving the name in it, since other code always assumes the
                # first cell is empty.
                #
                # To be honest, I'm not sure this is the Right Thing To Do, but
                # I'm too lazy to audit the code to see if it matters if we keep
                # the first cell intact. Sorry if this ends up causing you grief
                # some day...
                row[0] = ""
                self._children[-1].append(row.linenumber, row.raw_text, row.cells)

        elif len(self._children) == 0:
            # something before the first test case
            # For now, append it to self.comments; eventually we should flag
            # an error if it's NOT a comment
            self.comments.append(row)

        else:
            # another row for the testcase
            if len(row.cells) > 0:
                self._children[-1].append(row.linenumber, row.raw_text, row.cells)

def append ( self , row ) : if len ( row ) == 0 : return if ( row [ 0 ] != "" and ( not row [ 0 ] . lstrip ( ) . startswith ( "#" ) ) ) : self . _children . append ( self . _childClass ( self . parent , row . linenumber , row [ 0 ] ) ) if len ( row . cells ) > 1 : row [ 0 ] = "" self . _children [ - 1 ] . append ( row . linenumber , row . raw_text , row . cells ) elif len ( self . _children ) == 0 : self . comments . append ( row ) else : if len ( row . cells ) > 0 : self . _children [ - 1 ] . append ( row . linenumber , row . raw_text , row . cells )

The idea is we recognize when we have a new testcase by checking the first cell . If it s not empty and not a comment we have a new test case .


def report(self, obj, message, linenum, char_offset=0):
        """Report an error or warning"""
        self.controller.report(linenumber=linenum, filename=obj.path,
                               severity=self.severity, message=message,
                               rulename = self.__class__.__name__,
                               char=char_offset)

def report ( self , obj , message , linenum , char_offset = 0 ) : self . controller . report ( linenumber = linenum , filename = obj . path , severity = self . severity , message = message , rulename = self . __class__ . __name__ , char = char_offset )


def run(self, args):
        """Parse command line arguments, and run rflint"""

        self.args = self.parse_and_process_args(args)

        if self.args.version:
            print(__version__)
            return 0

        if self.args.rulefile:
            for filename in self.args.rulefile:
                self._load_rule_file(filename)

        if self.args.list:
            self.list_rules()
            return 0

        if self.args.describe:
            self._describe_rules(self.args.args)
            return 0

        self.counts = { ERROR: 0, WARNING: 0, "other": 0}

        for filename in self.args.args:
            if not (os.path.exists(filename)):
                sys.stderr.write("rflint: %s: No such file or directory\n" % filename)
                continue
            if os.path.isdir(filename):
                self._process_folder(filename)
            else:
                self._process_file(filename)

        if self.counts[ERROR] > 0:
            return self.counts[ERROR] if self.counts[ERROR] < 254 else 255

        return 0

Parse command line arguments and run rflint


def list_rules(self):
        """Print a list of all rules"""
        for rule in sorted(self.all_rules, key=lambda rule: rule.name):
            print(rule)
            if self.args.verbose:
                for line in rule.doc.split("\n"):
                    print("    ", line)

def
list_rules
(
self
)
:
for
rule
in
sorted
(
self
.
all_rules
,
key
=
lambda
rule
:
rule
.
name
)
:
print
(
rule
)
if
self
.
args
.
verbose
:
for
line
in
rule
.
doc
.
split
(
"\n"
)
:
print
(
"    "
,
line
)


def report(self, linenumber, filename, severity, message, rulename, char):
        """Report a rule violation"""

        if self._print_filename is not None:
            # we print the filename only once. self._print_filename
            # will get reset each time a new file is processed.
            print("+ " + self._print_filename)
            self._print_filename = None

        if severity in (WARNING, ERROR):
            self.counts[severity] += 1
        else:
            self.counts["other"] += 1

        print(self.args.format.format(linenumber=linenumber, filename=filename,
                                      severity=severity, message=message.encode('utf-8'),
                                      rulename=rulename, char=char))

def
report
(
self
,
linenumber
,
filename
,
severity
,
message
,
rulename
,
char
)
:
if
self
.
_print_filename
is
not
:
print
(
"+ "
+
self
.
_print_filename
)
self
.
_print_filename
=
if
severity
in
(
WARNING
,
ERROR
)
:
self
.
counts
[
severity
]
+=
1
else
:
self
.
counts
[
"other"
]
+=
1
print
(
self
.
args
.
format
.
format
(
linenumber
=
linenumber
,
filename
=
filename
,
severity
=
severity
,
message
=
message
.
encode
(
'utf-8'
)
,
rulename
=
rulename
,
char
=
char
)
)


def _get_rules(self, cls):
        """Returns a list of rules of a given class

        Rules are treated as singletons - we only instantiate each
        rule once.
        """

        result = []
        for rule_class in cls.__subclasses__():
            rule_name = rule_class.__name__.lower()
            if rule_name not in self._rules:
                rule = rule_class(self)
                self._rules[rule_name] = rule
            result.append(self._rules[rule_name])
        return result

def _get_rules ( self , cls ) : result = [ ] for rule_class in cls . __subclasses__ ( ) : rule_name = rule_class . __name__ . lower ( ) if rule_name not in self . _rules : rule = rule_class ( self ) self . _rules [ rule_name ] = rule result . append ( self . _rules [ rule_name ] ) return result

Returns a list of rules of a given class Rules are treated as singletons - we only instantiate each rule once .