From 8684c0b834ef4da54bf8246dbf918b553d9222b8 Mon Sep 17 00:00:00 2001 From: mcarrier Date: Thu, 26 Jan 2017 17:46:25 +0000 Subject: git-svn-id: svn+ssh://scm.gforge.inria.fr/svnroot/gudhi/branches/Nerve_GIC@2015 636b058d-ea47-450e-bf9e-a15bfbe3eedb Former-commit-id: fdaf0e66eaae7539080af7bada668f32e7ae1dc0 --- src/Nerve_GIC/example/bottleneckBootstrap.cpp | 274 ------------------ src/Nerve_GIC/example/density_smoother.cpp | 155 ---------- src/Nerve_GIC/example/graph_off.cpp | 49 ---- src/Nerve_GIC/example/km.py | 390 -------------------------- src/Nerve_GIC/example/mapper.cpp | 179 ------------ src/Nerve_GIC/example/mapper_parameter.cpp | 165 ----------- src/Nerve_GIC/example/quantile.cpp | 48 ---- src/Nerve_GIC/example/visu.py | 43 --- 8 files changed, 1303 deletions(-) delete mode 100644 src/Nerve_GIC/example/bottleneckBootstrap.cpp delete mode 100644 src/Nerve_GIC/example/density_smoother.cpp delete mode 100644 src/Nerve_GIC/example/graph_off.cpp delete mode 100755 src/Nerve_GIC/example/km.py delete mode 100755 src/Nerve_GIC/example/mapper.cpp delete mode 100644 src/Nerve_GIC/example/mapper_parameter.cpp delete mode 100644 src/Nerve_GIC/example/quantile.cpp delete mode 100755 src/Nerve_GIC/example/visu.py (limited to 'src/Nerve_GIC/example') diff --git a/src/Nerve_GIC/example/bottleneckBootstrap.cpp b/src/Nerve_GIC/example/bottleneckBootstrap.cpp deleted file mode 100644 index eac94e5e..00000000 --- a/src/Nerve_GIC/example/bottleneckBootstrap.cpp +++ /dev/null @@ -1,274 +0,0 @@ - #include "mapper.h" -#define ETA 0.001 -#define SHIFT 1 -#define DELTA 0 -#define CONSTANT 10 - -double GetUniform(){ - static default_random_engine re; - static uniform_real_distribution Dist(0,1); - return Dist(re); -} - -void SampleWithReplacement(int populationSize, int sampleSize, vector & samples){ - int m = 0; double u; - while (m < sampleSize){ - u = GetUniform(); - samples[m] = floor(u*populationSize); - m++; - } -} - -void SampleWithoutReplacement(int populationSize, int sampleSize, vector & samples){ - int& n = sampleSize; int& N = populationSize; - int t = 0; int m = 0; double u; - while (m < n){ - u = GetUniform(); - if ( (N - t)*u >= n - m ) - t++; - else{samples[m] = t; t++; m++;} - } -} - -void compute_estimator(Cloud & C, char* const & cloud, const bool & VNE, const int & Nsubs, \ - const double & gain){ - - int n = C.size(); - double** dist = new double*[n]; - for(int i = 0; i < n; i++) dist[i] = new double[n]; - double d; - Cover I; AdjacencyMatrix G; MapperElements M; - double maxf = C[0].func; double minf = C[0].func; - for(int i = 1; i < n; i++){ maxf = max(maxf,C[i].func); minf = min(minf,C[i].func);} - - char name1[100]; - if(VNE) sprintf(name1, "%s_VNdist", cloud); - else sprintf(name1, "%s_dist", cloud); - char* const name2 = name1; - ifstream input(name2, ios::out | ios::binary); - - if(input.good()){ - cout << " Reading distances for parameter selection..." << endl; - for(int i = 0; i < n; i++){ - for (int j = 0; j < n; j++){ - input.read((char*) &d,8); dist[i][j] = d; - } - } - input.close(); - } - else{ - cout << " Computing distances for parameter selection..." << endl; vector V; - input.close(); ofstream output(name2, ios::out | ios::binary); - if(VNE){ - int dim = C[0].coord.size(); - for(int i = 0; i < dim; i++){ - double meani = 0; - for (int j = 0; j < n; j++) meani += C[j].coord[i]/n; - double vari = 0; - for (int j = 0; j < n; j++) vari += pow(C[j].coord[i]-meani,2)/n; - V.push_back(vari); - } - } - - for(int i = 0; i < n; i++){ - if( (int) floor( 100*((double) i)/((double) n)+1 ) %10 == 0 ){ - cout << "\r" << floor( 100*((double) i)/((double) n) +1) << "%" << flush;} - for (int j = 0; j < n; j++){ - if(!VNE){d = C[i].EuclideanDistance(C[j]); dist[i][j] = d;} - else{d = C[i].VarianceNormalizedEuclideanDistance(C[j],V); dist[i][j] = d;} - output.write((char*) &d,8); - } - } - output.close(); - } - - int m = floor(n/pow(log(n)/log(CONSTANT),1+ETA)); - double lip = 0; double delta = 0; vector samples(m); - #pragma omp parallel for - for (int i = 0; i < Nsubs; i++){ - SampleWithoutReplacement(n,m,samples); - double hausdorff_dist = 0; - for (int j = 0; j < n; j++){ - Point p = C[j]; double mj = dist[j][samples[0]]; double Mi = abs(p.func-C[0].func)/dist[j][0]; - for (int k = 1; k < m; k++) mj = min(mj, dist[j][samples[k]]); - if(j < n-1) - for (int k = j+1; k < n; k++) Mi = max(Mi, abs(p.func-C[k].func)/dist[j][k]); - hausdorff_dist = max(hausdorff_dist, mj); lip = max(lip,Mi); - } - delta += hausdorff_dist; - } - delta /= Nsubs; double resolution; if(DELTA) resolution = lip*delta; else resolution = lip*delta/gain; - //cout << delta << " " << lip << " " << resolution << endl; - cout << " Done." << endl; - - G = build_neighborhood_graph_from_scratch_with_parameter(C,delta,name2,VNE); - - sort(C.begin(),C.end()); - I = Cover(C.begin()->func, (C.end()-1)->func, resolution, gain, SHIFT, 1); - I.proper_value(); - - map colors; colors.clear(); map num; num.clear(); - map > clusters; vector dum; dum.clear(); - for(int i = 0; i < C.size(); i++) clusters.insert(pair >(C[i],dum)); vector col(G.size()); - - M = MapperElts(G,I,clusters,col); - SparseGraph MG; - if (DELTA) MG = build_mapperDelta_graph(M,G,clusters,colors,num); else MG = build_mapper_graph(M,colors,num); - - char mappg[100]; sprintf(mappg,"%s_mapper.txt",cloud); - ofstream graphicg(mappg); - - double maxv, minv; maxv = numeric_limits::min(); minv = numeric_limits::max(); - for (map::iterator iit = colors.begin(); iit != colors.end(); iit++){ - if(iit->second > maxv) maxv = iit->second; - if(minv > iit->second) minv = iit->second; - } - - int k = 0; int ke = 0; - - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++){ - k++; for (int j = 0; j < it->second.size(); j++) ke++; - } - - graphicg << k << " " << ke << endl; int kk = 0; - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++){graphicg << kk << " " << colors[it->first] << endl; kk++;} - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++) - for (int j = 0; j < it->second.size(); j++) - graphicg << it->first << " " << it->second[j] << endl; -} - -void compute_bootstrapped_estimator(const vector & samp, char* const & cloud, const int & Nboot, double** dist, Cloud & Cboot, \ - const int & Nsubs, const double & gain){ - - int n = Cboot.size(); - Cover I; MapperElements M; - double maxf = Cboot[0].func; double minf = Cboot[0].func; - for(int i = 1; i < n; i++){ maxf = max(maxf,Cboot[i].func); minf = min(minf,Cboot[i].func);} - int m = floor(n/pow(log(n)/log(CONSTANT),1+ETA)); - double lip = 0; double delta = 0; vector samples(m); - #pragma omp parallel for - for (int i = 0; i < Nsubs; i++){ - SampleWithoutReplacement(n,m,samples); - double hausdorff_dist = 0; - for (int j = 0; j < n; j++){ - Point p = Cboot[j]; double mj = dist[samp[j]][samp[samples[0]]]; double Mi = abs(p.func-Cboot[0].func)/dist[samp[j]][samp[0]]; - for (int k = 1; k < m; k++) mj = min(mj, dist[samp[j]][samp[samples[k]]]); - if(j < n-1) - for (int k = j+1; k < n; k++) Mi = max(Mi, abs(p.func-Cboot[k].func)/dist[samp[j]][samp[k]]); - hausdorff_dist = max(hausdorff_dist, mj); lip = max(lip,Mi); - } - delta += hausdorff_dist; - } - delta /= Nsubs; double resolution; - if(DELTA) resolution = lip*delta; else resolution = lip*delta/gain; - //cout << delta << " " << lip << " " << resolution << endl; - - AdjacencyMatrix G; G.clear(); vector adj; - - for(int i = 0; i < n; i++){ - adj.clear(); - for(int j = 0; j < n; j++) - if(dist[samp[i]][samp[j]] <= delta) - adj.push_back(Cboot[j]); - G.insert(pair >(Cboot[i],adj)); - } - - sort(Cboot.begin(),Cboot.end()); - I = Cover(Cboot.begin()->func, (Cboot.end()-1)->func, resolution, gain, SHIFT, 1); - I.proper_value(); - - map colors; colors.clear(); map num; num.clear(); - map > clusters; vector dum; dum.clear(); - for(int i = 0; i < Cboot.size(); i++) clusters.insert(pair >(Cboot[i],dum)); vector col(n); - - M = MapperElts(G,I,clusters,col); - SparseGraph MG; - if(DELTA) MG = build_mapperDelta_graph(M,G,clusters,colors,num); else MG = build_mapper_graph(M,colors,num); - - char mappg[100]; sprintf(mappg,"%s_mapper_%d.txt",cloud,Nboot); - ofstream graphicg(mappg); - - double maxv, minv; maxv = numeric_limits::min(); minv = numeric_limits::max(); - for (map::iterator iit = colors.begin(); iit != colors.end(); iit++){ - if(iit->second > maxv) maxv = iit->second; - if(minv > iit->second) minv = iit->second; - } - - int k = 0; int ke = 0; - - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++){ - k++; for (int j = 0; j < it->second.size(); j++) ke++; - } - - graphicg << k << " " << ke << endl; int kk = 0; - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++){graphicg << kk << " " << colors[it->first] << endl; kk++;} - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++) - for (int j = 0; j < it->second.size(); j++) - graphicg << it->first << " " << it->second[j] << endl; - graphicg.close(); - -} - - -int main(int argc, char** argv){ - - if(argc <= 7 || argc >= 9){ - cout << "./bottleBoot " << endl; - return 0;} - - char* const cloud = argv[1]; bool normalized = atoi(argv[2]); char* const funct = argv[3]; double gain = atof(argv[5]); - int Nsubs = atoi(argv[6]); int Nboot = atoi(argv[7]); - - Cloud C, D, Cboot; C = read_cloud(cloud); int n = C.size(); - - if (strcmp(funct, "function:") == 0){ - char* const func = argv[4]; read_function_from_file(func,C); - } - if (strcmp(funct, "coordinate:") == 0){ - int number = atoi(argv[4]); read_coordinate(number,C); - } - if (strcmp(funct, "eccentricity") == 0){ - char* const matrix = argv[4]; compute_eccentricity(C,matrix); - } - - D = C; - - cout << "Computing estimator..." << endl; - compute_estimator(C,cloud,normalized,Nsubs,gain); - cout << "Estimator computed." << endl; - - char nam[100]; sprintf(nam,"%s_mapper.txt",cloud); char dg[100]; sprintf(dg,"%s_ExDg",cloud); - char command[100]; - sprintf(command,"cat %s | ../persistence/filtgraph 1 | ../persistence/pers 1 >> %s",nam,dg); system(command); - char list[100]; sprintf(list,"%s_quantile",cloud); - - char name[100]; - if(normalized) sprintf(name, "%s_VNdist", cloud); - else sprintf(name, "%s_dist", cloud); - ifstream input(name, ios::out | ios::binary); double d; - double** dist = new double*[n]; for(int i = 0; i < n; i++) dist[i] = new double[n]; - for(int i = 0; i < n; i++) for (int j = 0; j < n; j++){input.read((char*) &d,8); dist[i][j] = d;} - input.close(); - - for(int i = 0; i < Nboot; i++){ - - Cboot.clear(); - vector samples(n); SampleWithReplacement(n,n,samples); sort(samples.begin(), samples.end()); - for (int i = 0; i < n; i++) Cboot.push_back(D[samples[i]]); - - cout << "Computing " << i << "th bootstrapped estimator..." << endl; - compute_bootstrapped_estimator(samples,cloud,i,dist,Cboot,Nsubs,gain); - cout << "Done." << endl; - - char namei[100]; sprintf(namei,"%s_mapper_%d.txt",cloud,i); char dgi[100]; sprintf(dgi,"%s_ExDg_%d",cloud,i); - char command[100]; - sprintf(command,"cat %s | ../persistence/filtgraph 1 | ../persistence/pers 1 >> %s",namei,dgi); system(command); - sprintf(command,"../persistence/bottleneck_dist %s %s >> %s",dg,dgi,list); system(command); - sprintf(command, "rm %s %s",namei, dgi); system(command); - - } - - delete [] dist; - - return 0; -} diff --git a/src/Nerve_GIC/example/density_smoother.cpp b/src/Nerve_GIC/example/density_smoother.cpp deleted file mode 100644 index 4f3c4137..00000000 --- a/src/Nerve_GIC/example/density_smoother.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -double EuclideanDistance(const vector & V1, const vector & V2){ - assert(V1.size() == V2.size()); - double res = 0; - for(int i = 0; i < V1.size(); i++) res += pow(V1[i]-V2[i],2); - return sqrt(res); -} - -int main(int argc, char** argv){ - - char* const cloud = argv[1]; - char* const method = argv[2]; - - if(argc <= 4){cout << "Usage: " << endl; return 0;} - if(argc >= 6){cout << "Too many arguments !" << endl; return 0;} - - ifstream Cloud(cloud); - vector > C, distances; C.clear(); double d; - string line; - - int nb = 0; cout << "Reading cloud..." << endl; - while(getline(Cloud,line)){ - if(nb%100000 == 0) cout << " " << nb << endl; - vector P; - stringstream stream(line); - while(stream >> d) P.push_back(d); - C.push_back(P); nb++; - } - cout << endl; - - for(int i = 0; i < nb; i++){vector vect(nb); distances.push_back(vect);} - - char name[100]; sprintf(name,"%s_dist",cloud); - ifstream input(name, ios::out | ios::binary); - - if(input.good()){ - - cout << " Reading distances..." << endl; - - for(int i = 0; i < nb; i++){ - for (int j = 0; j < nb; j++){ - input.read((char*) &d,8); distances[i][j] = d; - } - } - - input.close(); - cout << " Done." << endl; - - } - - else{ - - cout << " Computing distances..." << endl; - input.close(); ofstream output(name, ios::out | ios::binary); - - for(int i = 0; i < nb-1; i++){ - if( (int) floor( 100*((double) i)/((double) nb)+1 ) %10 == 0 ){cout << "\r" << floor( 100*((double) i)/((double) nb) +1) << "%" << flush;} - for (int j = i+1; j < nb; j++){ - d = EuclideanDistance(C[i],C[j]); distances[i][j] = d; distances[j][i] = d; - output.write((char*) &d,8); - } - } - - output.close(); - cout << endl << " Done." << endl; - - } - - if(strcmp(method,"DTM") == 0){ - - int k = atoi(argv[3]); - double thresh = atof(argv[4]); - - char nameo[100]; sprintf(nameo,"%s_DTM_%d_%g",cloud,k,thresh); - ofstream output(nameo); vector densities; double M = 0; - - cout << "Computing DTM..." << endl; - for(int i = 0; i < nb; i++){ - if( (int) floor( 100*((double) i)/((double) nb)+1 ) %10 == 0 ){cout << "\r" << floor( 100*((double) i)/((double) nb) +1) << "%" << flush;} - double density = 0; - sort(distances[i].begin(),distances[i].end()); - for(int j = 0; j < k; j++) - density += pow(distances[i][j],2); - density = sqrt(k)/sqrt(density); - if(density >= M) M = density; - densities.push_back(density); - - } - cout << endl << " Done." << endl; - - for(int i = 0; i < nb; i++){ - if(densities[i] >= thresh*M){ - for(int j = 0; j < C[i].size(); j++) output << C[i][j] << " "; - output << endl; - } - } - - output.close(); - - } - - if(strcmp(method,"GaussianDE") == 0){ - - double bandwidth = atof(argv[3]); - double thresh = atof(argv[4]); - - char nameo[100]; sprintf(nameo,"%s_GDE_%g_%g",cloud,bandwidth,thresh); - ofstream output(nameo); vector densities; double M = 0; - - cout << "Computing GDE..." << endl; - for(int i = 0; i < nb; i++){ - if( (int) floor( 100*((double) i)/((double) nb)+1 ) %10 == 0 ){cout << "\r" << floor( 100*((double) i)/((double) nb) +1) << "%" << flush;} - double density = 0; - for(int j = 0; j < nb; j++) - density += exp(-pow(distances[i][j],2)/(2*pow(bandwidth,2))); - density /= sqrt(2*3.1415)*nb*bandwidth; - if(density >= M) M = density; - densities.push_back(density); - - } - cout << endl << " Done." << endl; - - for(int i = 0; i < nb; i++){ - if(densities[i] >= thresh*M){ - for(int j = 0; j < C[i].size(); j++) output << C[i][j] << " "; - output << endl; - } - } - - output.close(); - - } - - return 0; - -} diff --git a/src/Nerve_GIC/example/graph_off.cpp b/src/Nerve_GIC/example/graph_off.cpp deleted file mode 100644 index 574d9fc6..00000000 --- a/src/Nerve_GIC/example/graph_off.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -int main (int argc, char **argv) { - - char* const fileoff = argv[1]; ifstream input(fileoff); char ngoff[100]; sprintf(ngoff,"%s_NG", fileoff); ofstream output(ngoff); - char buf[256]; - vector > NG; - - input.getline(buf, 255); // skip "OFF" - int n, m; - input >> n >> m; - input.getline(buf, 255); // skip "0" - - // read vertices - double x,y,z; vector ng; int nn = n; - while(nn-->0) { - input >> x >> z >> y; NG.push_back(ng); - } - - // read triangles - int d, p, q, s; - while (m-->0) { - input >> d >> p >> q >> s; - NG[p].push_back(q); NG[p].push_back(s); - NG[q].push_back(p); NG[q].push_back(s); - NG[s].push_back(q); NG[s].push_back(p); - } - - for(int i = 0; i < n; i++){ - vector ng = NG[i]; - sort(ng.begin(),ng.end()); vector::iterator iter = unique(ng.begin(),ng.end()); ng.resize(distance(ng.begin(),iter)); - int size = ng.size(); - for(int j = 0; j < size; j++) - output << ng[j] << " "; - output << endl; - } - - return 0; - -} diff --git a/src/Nerve_GIC/example/km.py b/src/Nerve_GIC/example/km.py deleted file mode 100755 index d3cfad59..00000000 --- a/src/Nerve_GIC/example/km.py +++ /dev/null @@ -1,390 +0,0 @@ -from __future__ import division -import numpy as np -from collections import defaultdict -import json -import itertools -from sklearn import cluster, preprocessing, manifold -from datetime import datetime -import sys - -class KeplerMapper(object): - # With this class you can build topological networks from (high-dimensional) data. - # - # 1) Fit a projection/lens/function to a dataset and transform it. - # For instance "mean_of_row(x) for x in X" - # 2) Map this projection with overlapping intervals/hypercubes. - # Cluster the points inside the interval - # (Note: we cluster on the inverse image/original data to lessen projection loss). - # If two clusters/nodes have the same members (due to the overlap), then: - # connect these with an edge. - # 3) Visualize the network using HTML and D3.js. - # - # functions - # --------- - # fit_transform: Create a projection (lens) from a dataset - # map: Apply Mapper algorithm on this projection and build a simplicial complex - # visualize: Turns the complex dictionary into a HTML/D3.js visualization - - def __init__(self, verbose=2): - self.verbose = verbose - - self.chunk_dist = [] - self.overlap_dist = [] - self.d = [] - self.nr_cubes = 0 - self.overlap_perc = 0 - self.clusterer = False - - def fit_transform(self, X, projection="sum", scaler=preprocessing.MinMaxScaler()): - # Creates the projection/lens from X. - # - # Input: X. Input features as a numpy array. - # Output: projected_X. original data transformed to a projection (lens). - # - # parameters - # ---------- - # projection: Projection parameter is either a string, - # a scikit class with fit_transform, like manifold.TSNE(), - # or a list of dimension indices. - # scaler: if None, do no scaling, else apply scaling to the projection - # Default: Min-Max scaling - - self.scaler = scaler - self.projection = str(projection) - - # Detect if projection is a class (for scikit-learn) - if str(type(projection))[1:6] == "class": #TODO: de-ugly-fy - reducer = projection - if self.verbose > 0: - try: - projection.set_params(**{"verbose":self.verbose}) - except: - pass - print("\n..Projecting data using: \n\t%s\n"%str(projection)) - X = reducer.fit_transform(X) - - # Detect if projection is a string (for standard functions) - if isinstance(projection, str): - if self.verbose > 0: - print("\n..Projecting data using: %s"%(projection)) - # Stats lenses - if projection == "sum": # sum of row - X = np.sum(X, axis=1).reshape((X.shape[0],1)) - if projection == "mean": # mean of row - X = np.mean(X, axis=1).reshape((X.shape[0],1)) - if projection == "median": # mean of row - X = np.median(X, axis=1).reshape((X.shape[0],1)) - if projection == "max": # max of row - X = np.max(X, axis=1).reshape((X.shape[0],1)) - if projection == "min": # min of row - X = np.min(X, axis=1).reshape((X.shape[0],1)) - if projection == "std": # std of row - X = np.std(X, axis=1).reshape((X.shape[0],1)) - - if projection == "dist_mean": # Distance of x to mean of X - X_mean = np.mean(X, axis=0) - X = np.sum(np.sqrt((X - X_mean)**2), axis=1).reshape((X.shape[0],1)) - - # Detect if projection is a list (with dimension indices) - if isinstance(projection, list): - if self.verbose > 0: - print("\n..Projecting data using: %s"%(str(projection))) - X = X[:,np.array(projection)] - - # Scaling - if scaler is not None: - if self.verbose > 0: - print("\n..Scaling with: %s\n"%str(scaler)) - X = scaler.fit_transform(X) - - return X - - def map(self, projected_X, inverse_X=None, clusterer=cluster.DBSCAN(eps=0.5,min_samples=3), nr_cubes=10, overlap_perc=0.1): - # This maps the data to a simplicial complex. Returns a dictionary with nodes and links. - # - # Input: projected_X. A Numpy array with the projection/lens. - # Output: complex. A dictionary with "nodes", "links" and "meta information" - # - # parameters - # ---------- - # projected_X projected_X. A Numpy array with the projection/lens. Required. - # inverse_X Numpy array or None. If None then the projection itself is used for clustering. - # clusterer Scikit-learn API compatible clustering algorithm. Default: DBSCAN - # nr_cubes Int. The number of intervals/hypercubes to create. - # overlap_perc Float. The percentage of overlap "between" the intervals/hypercubes. - - start = datetime.now() - - # Helper function - def cube_coordinates_all(nr_cubes, nr_dimensions): - # Helper function to get origin coordinates for our intervals/hypercubes - # Useful for looping no matter the number of cubes or dimensions - # Example: if there are 4 cubes per dimension and 3 dimensions - # return the bottom left (origin) coordinates of 64 hypercubes, - # as a sorted list of Numpy arrays - # TODO: elegance-ify... - l = [] - for x in range(nr_cubes): - l += [x] * nr_dimensions - return [np.array(list(f)) for f in sorted(set(itertools.permutations(l,nr_dimensions)))] - - nodes = defaultdict(list) - links = defaultdict(list) - complex = {} - self.nr_cubes = nr_cubes - self.clusterer = clusterer - self.overlap_perc = overlap_perc - - if self.verbose > 0: - print("Mapping on data shaped %s using dimensions\n"%(str(projected_X.shape))) - - # If inverse image is not provided, we use the projection as the inverse image (suffer projection loss) - if inverse_X is None: - inverse_X = projected_X - - # We chop up the min-max column ranges into 'nr_cubes' parts - self.chunk_dist = (np.max(projected_X, axis=0) - np.min(projected_X, axis=0))/nr_cubes - - # We calculate the overlapping windows distance - self.overlap_dist = self.overlap_perc * self.chunk_dist - - # We find our starting point - self.d = np.min(projected_X, axis=0) - - # Use a dimension index array on the projected X - # (For now this uses the entire dimensionality, but we keep for experimentation) - di = np.array([x for x in range(projected_X.shape[1])]) - - # Prefix'ing the data with ID's - ids = np.array([x for x in range(projected_X.shape[0])]) - projected_X = np.c_[ids,projected_X] - inverse_X = np.c_[ids,inverse_X] - - # Subdivide the projected data X in intervals/hypercubes with overlap - if self.verbose > 0: - total_cubes = len(cube_coordinates_all(nr_cubes,projected_X.shape[1])) - print("Creating %s hypercubes."%total_cubes) - - for i, coor in enumerate(cube_coordinates_all(nr_cubes,di.shape[0])): - # Slice the hypercube - hypercube = projected_X[ np.invert(np.any((projected_X[:,di+1] >= self.d[di] + (coor * self.chunk_dist[di])) & - (projected_X[:,di+1] < self.d[di] + (coor * self.chunk_dist[di]) + self.chunk_dist[di] + self.overlap_dist[di]) == False, axis=1 )) ] - - if self.verbose > 1: - print("There are %s points in cube_%s / %s with starting range %s"% - (hypercube.shape[0],i,total_cubes,self.d[di] + (coor * self.chunk_dist[di]))) - - # If at least one sample inside the hypercube - if hypercube.shape[0] > 0: - # Cluster the data point(s) in the cube, skipping the id-column - # Note that we apply clustering on the inverse image (original data samples) that fall inside the cube. - inverse_x = inverse_X[[int(nn) for nn in hypercube[:,0]]] - - clusterer.fit(inverse_x[:,1:]) - - if self.verbose > 1: - print("Found %s clusters in cube_%s\n"%(np.unique(clusterer.labels_[clusterer.labels_ > -1]).shape[0],i)) - - #Now for every (sample id in cube, predicted cluster label) - for a in np.c_[hypercube[:,0],clusterer.labels_]: - if a[1] != -1: #if not predicted as noise - cluster_id = str(coor[0])+"_"+str(i)+"_"+str(a[1])+"_"+str(coor)+"_"+str(self.d[di] + (coor * self.chunk_dist[di])) # TODO: de-rudimentary-ify - nodes[cluster_id].append( int(a[0]) ) # Append the member id's as integers - else: - if self.verbose > 1: - print("Cube_%s is empty.\n"%(i)) - - # Create links when clusters from different hypercubes have members with the same sample id. - candidates = itertools.combinations(nodes.keys(),2) - for candidate in candidates: - # if there are non-unique members in the union - if len(nodes[candidate[0]]+nodes[candidate[1]]) != len(set(nodes[candidate[0]]+nodes[candidate[1]])): - links[candidate[0]].append( candidate[1] ) - - # Reporting - if self.verbose > 0: - nr_links = 0 - for k in links: - nr_links += len(links[k]) - print("\ncreated %s edges and %s nodes in %s."%(nr_links,len(nodes),str(datetime.now()-start))) - - complex["nodes"] = nodes - complex["links"] = links - complex["meta"] = self.projection - - return complex - - def visualize(self, complex, color_function="", path_html="mapper_visualization_output.html", title="My Data", - graph_link_distance=30, graph_gravity=0.1, graph_charge=-120, custom_tooltips=None, width_html=0, - height_html=0, show_tooltips=True, show_title=True, show_meta=True, res=0,gain=0,minimum=0,maximum=0): - # Turns the dictionary 'complex' in a html file with d3.js - # - # Input: complex. Dictionary (output from calling .map()) - # Output: a HTML page saved as a file in 'path_html'. - # - # parameters - # ---------- - # color_function string. Not fully implemented. Default: "" (distance to origin) - # path_html file path as string. Where to save the HTML page. - # title string. HTML page document title and first heading. - # graph_link_distance int. Edge length. - # graph_gravity float. "Gravity" to center of layout. - # graph_charge int. charge between nodes. - # custom_tooltips None or Numpy Array. You could use "y"-label array for this. - # width_html int. Width of canvas. Default: 0 (full width) - # height_html int. Height of canvas. Default: 0 (full height) - # show_tooltips bool. default:True - # show_title bool. default:True - # show_meta bool. default:True - - # Format JSON for D3 graph - json_s = {} - json_s["nodes"] = [] - json_s["links"] = [] - k2e = {} # a key to incremental int dict, used for id's when linking - - for e, k in enumerate(complex["nodes"]): - # Tooltip and node color formatting, TODO: de-mess-ify - if custom_tooltips is not None: - tooltip_s = "

Cluster %s

"%k + " ".join(str(custom_tooltips[complex["nodes"][k][0]]).split(" ")) - if color_function == "Lens average": - tooltip_i = int(30*(custom_tooltips[complex["nodes"][k][0]]-minimum)/(maximum-minimum)) - json_s["nodes"].append({"name": str(k), "tooltip": tooltip_s, "group": 2 * int(np.log(complex["nodes"][k][2])), "color": tooltip_i}) - else: - json_s["nodes"].append({"name": str(k), "tooltip": tooltip_s, "group": 2 * int(np.log(len(complex["nodes"][k]))), "color": str(k.split("_")[0])}) - else: - tooltip_s = "

Cluster %s

Contains %s members."%(k,len(complex["nodes"][k])) - json_s["nodes"].append({"name": str(k), "tooltip": tooltip_s, "group": 2 * int(np.log(len(complex["nodes"][k]))), "color": str(k.split("_")[0])}) - k2e[k] = e - for k in complex["links"]: - for link in complex["links"][k]: - json_s["links"].append({"source": k2e[k], "target":k2e[link],"value":1}) - - # Width and height of graph in HTML output - if width_html == 0: - width_css = "100%" - width_js = 'document.getElementById("holder").offsetWidth-20' - else: - width_css = "%spx" % width_html - width_js = "%s" % width_html - if height_html == 0: - height_css = "100%" - height_js = 'document.getElementById("holder").offsetHeight-20' - else: - height_css = "%spx" % height_html - height_js = "%s" % height_html - - # Whether to show certain UI elements or not - if show_tooltips == False: - tooltips_display = "display: none;" - else: - tooltips_display = "" - - if show_meta == False: - meta_display = "display: none;" - else: - meta_display = "" - - if show_title == False: - title_display = "display: none;" - else: - title_display = "" - - with open(path_html,"wb") as outfile: - html = """ - - - %s | KeplerMapper - - - -
-

%s

-

- Lens
%s

- Length of intervals
%s

- Overlap percentage
%s%%

- Color Function
%s -

-
- - """%(title,width_css, height_css, title_display, meta_display, tooltips_display, title,complex["meta"],res,gain*100,color_function,width_js,height_js,graph_charge,graph_link_distance,graph_gravity,json.dumps(json_s)) - outfile.write(html.encode("utf-8")) - if self.verbose > 0: - print("\nWrote d3.js graph to '%s'"%path_html) \ No newline at end of file diff --git a/src/Nerve_GIC/example/mapper.cpp b/src/Nerve_GIC/example/mapper.cpp deleted file mode 100755 index 05dd87dd..00000000 --- a/src/Nerve_GIC/example/mapper.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "mapper.h" -#define SHIFT 1 -#define DELTA 1 -#define RESOLUTION 1 - -int main(int argc, char** argv){ - - if(argc <= 10 || argc >= 12){cout << "./mapper " <<\ - " " << endl; return 0;} - - char* const cloud = argv[1]; - char* const funct = argv[2]; - bool normalized = atoi(argv[6]); - char* const graph = argv[4]; - int mask; - char* const covering = argv[7]; - - Cover I; AdjacencyMatrix G; Cloud C; - MapperElements M; - - cout << "Reading input cloud from file " << cloud << "..." << endl; - C = read_cloud(cloud); - cout << " Done." << endl; - - double r,g; char namefunc[100]; - - if (strcmp(funct, "function:") == 0){ - char* const func = argv[3]; - cout << "Reading input filter from file " << func << "..." << endl; - read_function_from_file(func,C); sprintf(namefunc,"%s",func); - } - if (strcmp(funct, "coordinate:") == 0){ - int number = atoi(argv[3]); - cout << "Using coordinate " << number << " as a filter..." << endl; - read_coordinate(number,C); sprintf(namefunc,"Coordinate %d",number); - } - if (strcmp(funct, "eccentricity:") == 0){ - char* const matrix = argv[3]; - cout << "Computing eccentricity with distance matrix " << matrix << "..." << endl; - compute_eccentricity(C,matrix); sprintf(namefunc,"eccentricity"); - } - cout << " Done." << endl; - - if (strcmp(graph, "graph:") == 0){ - char* const graph_name = argv[5]; - cout << "Reading neighborhood graph from file " << graph_name << "..." << endl; - G = build_neighborhood_graph_from_file(C,graph_name); - } - if (strcmp(graph, "percentage:") == 0){ - double delta = atof(argv[5]); - char name1[100]; sprintf(name1, "%s_dist", cloud); char* const name2 = name1; - cout << "Computing neighborhood graph with delta percentage = " << delta << "..." << endl; - G = build_neighborhood_graph_from_scratch_with_percentage(C,delta,name2,normalized); - } - if (strcmp(graph, "parameter:") == 0){ - double delta = atof(argv[5]); - char name1[100]; sprintf(name1, "%s_dist", cloud); char* const name2 = name1; - cout << "Computing neighborhood graph with delta parameter = " << delta << "..." << endl; - G = build_neighborhood_graph_from_scratch_with_parameter(C,delta,name2,normalized); - } - cout << " Done." << endl; - - cout << "Sorting cloud..." << endl; - sort(C.begin(),C.end()); - cout << " Done." << endl; - - if(strcmp(covering,"cover:") == 0){ - char* const cover = argv[8]; mask = atoi(argv[9]); - cout << "Reading user-defined cover from file " << cover << "..." << endl; - I = Cover(cover); I.sort_covering(); - assert (I.intervals[0].first <= C.begin()->func && I.intervals[I.intervals.size()-1].second >= (C.end()-1)->func); - } - else{ - double resolution = atof(argv[8]); r = resolution; - double gain = atof(argv[9]); mask = atoi(argv[10]); g = gain; - cout << "Computing uniform cover with resolution " << resolution << " and gain " << gain << "..." << endl; - I = Cover(C.begin()->func, (C.end()-1)->func, resolution, gain, SHIFT, RESOLUTION); - } - I.proper_value(); - /*for (int i = 0; i < I.res; i++) - cout << " " << I.intervals[i].first << " " << I.intervals[i].second << " " << I.value[i] << endl; - cout << " Done." << endl;*/ - - map > clusters; vector dum; dum.clear(); - for(int i = 0; i < G.size(); i++) clusters.insert(pair >(C[i],dum)); vector col(G.size()); - cout << "Computing Mapper nodes..." << endl; - M = MapperElts(G,I,clusters,col); - cout << " Done." << endl; - - cout << "Computing intersections..." << endl; - map colors; colors.clear(); map num; num.clear(); SparseGraph MG; - if(!DELTA) MG = build_mapper_graph(M,colors,num); - else MG = build_mapperDelta_graph(M,G,clusters,colors,num); - cout << " Done." << endl; - - /*cout << "Computing Nerve..." << endl; - SimplicialComplex Nerve = compute_Nerve(C,clusters); - for(int i = 0; i < Nerve.size(); i++){ - for(int j = 0; j < Nerve[i].size(); j++) cout << Nerve[i][j] << " "; - cout << endl; - }*/ - - /*cout << "Computing GIC..." << endl; - SimplicialComplex GIC = compute_GIC(G,clusters); - for(int i = 0; i < GIC.size(); i++){ - for(int j = 0; j < GIC[i].size(); j++) cout << GIC[i][j] << " "; - cout << endl; - }*/ - - //cout << "Checking intersection crossings..." << endl; - //vector > error_pairs = check_intersection_crossing(M,G); - //cout << "Done." << endl; - - cout << "Writing outputs..." << endl; - - char mapp[11] = "mapper.dot"; - char mappg[11] = "mapper.txt"; - ofstream graphic(mapp); graphic << "graph Mapper {" << endl; - ofstream graphicg(mappg); - - double maxv, minv; maxv = numeric_limits::min(); minv = numeric_limits::max(); - for (map::iterator iit = colors.begin(); iit != colors.end(); iit++){ - if(iit->second > maxv){maxv = iit->second;} - if(minv > iit->second){minv = iit->second;} - } - - int k = 0; vector nodes; nodes.clear(); - for (SparseGraph::iterator iit = MG.begin(); iit != MG.end(); iit++){ - if(num[iit->first] > mask){ - nodes.push_back(iit->first); - graphic << iit->first << "[shape=circle fontcolor=black color=black label=\"" - << iit->first /*<< ":" << num[iit->first]*/ << "\" style=filled fillcolor=\"" - << (1-(maxv-colors[iit->first])/(maxv-minv))*0.6 << ", 1, 1\"]" << endl; - k++; - } - } - int ke = 0; - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++) - for (int j = 0; j < it->second.size(); j++) - if(num[it->first] > mask && num[it->second[j]] > mask){ - graphic << " " << it->first << " -- " << it->second[j] << " [weight=15];" << endl; ke++;} - graphic << "}"; graphic.close(); - - graphicg << cloud << endl; - graphicg << namefunc << endl; - graphicg << r << " " << g << endl; - graphicg << k << " " << ke << endl; int kk = 0; - for (vector::iterator iit = nodes.begin(); iit != nodes.end(); iit++){ - graphicg << kk << " " << colors[*iit] << " " << num[*iit] << endl; kk++;} - for (SparseGraph::iterator it = MG.begin(); it != MG.end(); it++) - for (int j = 0; j < it->second.size(); j++) - if(num[it->first] > mask && num[it->second[j]] > mask) - graphicg << it->first << " " << it->second[j] << endl; - graphicg.close(); - - cout << " Done." << endl; - - char command[100]; - sprintf(command,"neato %s -Tpdf -o mapper.pdf",mapp); system(command); - sprintf(command,"python visu.py"); system(command); - sprintf(command,"firefox mapper_visualization_output.html"); system(command); - sprintf(command,"evince mapper.pdf"); system(command); - sprintf(command,"rm %s %s mapper_visualization_output.html mapper.pdf",mapp,mappg); system(command); - - /* - if (error_pairs.size() > 0) - for (vector >::iterator it = error_pairs.begin(); it != error_pairs.end(); it++) - if( find(nodes.begin(),nodes.end(),it->first)!=nodes.end() && find(nodes.begin(),nodes.end(),it->second)!=nodes.end() ) - graphic << " " << it->first << " -- " << it->second << " [weight=15];" << endl; - */ - - int dim = C[0].coord.size(); - if (dim <= 3){ - plotNG(dim,G); - plotCover(dim,G,col,I); - } - -return 0; -} diff --git a/src/Nerve_GIC/example/mapper_parameter.cpp b/src/Nerve_GIC/example/mapper_parameter.cpp deleted file mode 100644 index 2302d164..00000000 --- a/src/Nerve_GIC/example/mapper_parameter.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#include "mapper.h" -#define ETA 0.001 -#define VERBOSE 1 -#define DELTA 1 -#define RESOLUTION 1 -#define CONSTANT 10 - -double GetUniform(){ - static default_random_engine re; - static uniform_real_distribution Dist(0,1); - return Dist(re); -} - -void SampleWithoutReplacement(int populationSize, int sampleSize, vector & samples){ - int& n = sampleSize; int& N = populationSize; - int t = 0; int m = 0; double u; - while (m < n){ - u = GetUniform(); - if ( (N - t)*u >= n - m ) - t++; - else{samples[m] = t; t++; m++;} - } -} - -int main(int argc, char** argv){ - - if(argc <= 7 || argc >= 9){cout << "./param " << \ - " " << endl; return 0;} - - char* const cloud = argv[1]; - char* const funct = argv[2]; - bool VNE = atoi(argv[4]); - double g = atof(argv[5]); - char* const method = argv[6]; - - Cloud C; - - if(VERBOSE) cout << "Reading input cloud from file " << cloud << "..." << endl; - C = read_cloud(cloud); int n = C.size(); - if(VERBOSE) cout << " Done." << endl; - - if (strcmp(funct, "function:") == 0){ - char* const func = argv[3]; - if(VERBOSE) cout << "Reading input filter from file " << func << "..." << endl; - read_function_from_file(func,C); - } - if (strcmp(funct, "coordinate:") == 0){ - int number = atoi(argv[3]); - if(VERBOSE) cout << "Using coordinate " << number << " as a filter..." << endl; - read_coordinate(number,C); - } - if (strcmp(funct, "eccentricity:") == 0){ - char* const matrix = argv[3]; - cout << "Computing eccentricity with distance matrix " << matrix << "..." << endl; - compute_eccentricity(C,matrix); - } - if(VERBOSE) cout << " Done." << endl; - - double maxf = C[0].func; double minf = C[0].func; - for(int i = 1; i < n; i++){ maxf = max(maxf,C[i].func); minf = min(minf,C[i].func);} - - double delta = 0; double lip = 0; - - if (strcmp(method, "subsampling:") == 0){ - - char name[100]; - if(VNE) sprintf(name,"%s_VNdist",cloud); - else sprintf(name,"%s_dist",cloud); - ifstream input(name, ios::out | ios::binary); - vector > dist; dist.clear(); double d; - - if(input.good()){ - cout << "Reading distances..." << endl; - for(int i = 0; i < n; i++){ - vector dis; dis.clear(); - for (int j = 0; j < n; j++){input.read((char*) &d,8); dis.push_back(d);} - dist.push_back(dis); - } - input.close(); - } - else{ - cout << "Computing distances..." << endl; vector V; - input.close(); ofstream output(name, ios::out | ios::binary); - if(VNE){ - int dim = C[0].coord.size(); - for(int i = 0; i < dim; i++){ - double meani = 0; - for (int j = 0; j < n; j++) meani += C[j].coord[i]/n; - double vari = 0; - for (int j = 0; j < n; j++) vari += pow(C[j].coord[i]-meani,2)/n; - V.push_back(vari); - } - } - - for(int i = 0; i < n; i++){ - if( (int) floor( 100*((double) i)/((double) n)+1 ) %10 == 0 ){cout << "\r" << floor( 100*((double) i)/((double) n) +1) << "%" << flush;} - vector dis; dis.clear(); - for (int j = 0; j < n; j++){ - if(!VNE){d = C[i].EuclideanDistance(C[j]); dis.push_back(d);} - else{d = C[i].VarianceNormalizedEuclideanDistance(C[j],V); dis.push_back(d);} - output.write((char*) &d,8); - } - dist.push_back(dis); - } - output.close(); - } - - cout << "Done." << endl; - - int m = floor(n/pow(log(n)/log(CONSTANT),1+ETA)); m = min(m,n-1); - - if(VERBOSE) cout << "dimension = " << C[0].coord.size() << endl << "n = " << n << " and s(n) = " << m << endl; - if(VERBOSE) cout << "range = [" << minf << ", " << maxf << "]" << endl; - - vector samples(m); int N = atoi(argv[7]); - #pragma omp parallel for - for (int i = 0; i < N; i++){ - SampleWithoutReplacement(n,m,samples); - double hausdorff_dist = 0; - for (int j = 0; j < n; j++){ - Point p = C[j]; - double mj = dist[j][samples[0]]; - double Mi = abs(p.func-C[0].func)/(dist[j][0]); - for (int k = 1; k < m; k++){mj = min(mj, dist[j][samples[k]]);} - for (int k = j+1; k < n; k++){Mi = max(Mi, abs(p.func-C[k].func)/(dist[j][k]));} - hausdorff_dist = max(hausdorff_dist, mj); lip = max(lip,Mi); - } - delta += hausdorff_dist; - } - delta /= N; - - } - - if (strcmp(method, "graph:") == 0){ - char* const graph_name = argv[7]; - cout << "Reading neighborhood graph from file " << graph_name << "..." << endl; - pair P = compute_delta_from_file(C,graph_name); - delta = P.first; lip = P.second; - } - - if(VERBOSE) cout << "lip = " << lip << endl; - - if(VERBOSE) cout << "delta = " << delta << endl; - else cout << delta << endl; - - if(VERBOSE) cout << "g = " << g << endl; - else cout << g << endl; - - if(!DELTA){ - if(VERBOSE){ - if(RESOLUTION) cout << "r = " << lip*delta/g << endl; - else cout << "r = " << floor(g*(maxf-minf)/(lip*delta*(1-g))) << endl;} - else{ - if(RESOLUTION) cout << lip*delta/g << endl; - else cout << floor(g*(maxf-minf)/(lip*delta*(1-g))) << endl;}} - else{ - if(VERBOSE){ - if(RESOLUTION) cout << "r = " << lip*delta << endl; - else cout << "r = " << floor((maxf-minf)/(lip*delta*(1-g))) << endl;} - else{ - if(RESOLUTION) cout << lip*delta << endl; - else cout << floor((maxf-minf)/(lip*delta*(1-g))) << endl;}} - - return 0; -} diff --git a/src/Nerve_GIC/example/quantile.cpp b/src/Nerve_GIC/example/quantile.cpp deleted file mode 100644 index 14dee5f2..00000000 --- a/src/Nerve_GIC/example/quantile.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "mapper.h" - -bool myComp(const pair & P1, const pair & P2){ - if(P1.first == P2.first) return (P1.second <= P2.second); - else return P1.first < P2.first; -} - -int main(int argc, char** argv){ - - if(argc <= 3 || argc >= 5){cout << "./quant " << endl; return 0;} - - char* const file = argv[1]; - bool token = atoi(argv[2]); - double value = atof(argv[3]); - vector V; - vector > Q; - - double v; ifstream input(file); string line; - while(getline(input,line)){ - stringstream stream(line); stream >> v; V.push_back(v); - } - - int N = V.size(); - - if(!token){ - int count = 0; - for(int i = 0; i < N; i++) - if(V[i] <= value) - count++; - cout << count*1.0/N << endl; - } - else{ - for(int i = 0; i < N; i++){ - int counti = 0; - for(int j = 0; j < N; j++) - if(V[j] <= V[i]) - counti++; - Q.push_back(pair(counti*1.0/N,V[i])); - } - sort(Q.begin(),Q.end(),myComp); - int ind = 0; - while(ind < N && Q[ind].first <= value) ind++; - if(ind==N) cout << Q[ind-1].second << endl; - else cout << Q[ind].second << endl; - } - - return 0; -} diff --git a/src/Nerve_GIC/example/visu.py b/src/Nerve_GIC/example/visu.py deleted file mode 100755 index 1324e08b..00000000 --- a/src/Nerve_GIC/example/visu.py +++ /dev/null @@ -1,43 +0,0 @@ -import km -import numpy as np -from collections import defaultdict - -network = {} -mapper = km.KeplerMapper(verbose=0) -data = np.zeros((3,3)) -projected_data = mapper.fit_transform( data, projection="sum", scaler=None ) - -f = open('mapper.txt','r') -nodes = defaultdict(list) -links = defaultdict(list) -custom = defaultdict(list) - -dat = f.readline() -lens = f.readline() -param = [float(i) for i in f.readline().split(" ")] - -nums = [int(i) for i in f.readline().split(" ")] -num_nodes = nums[0] -num_edges = nums[1] - -for i in range(0,num_nodes): - point = [float(j) for j in f.readline().split(" ")] - nodes[ str(int(point[0])) ] = [ int(point[0]), point[1], int(point[2]) ] - links[ str(int(point[0])) ] = [] - custom[ int(point[0]) ] = point[1] - -m = min([custom[i] for i in range(0,num_nodes)]) -M = max([custom[i] for i in range(0,num_nodes)]) - -for i in range(0,num_edges): - edge = [int(j) for j in f.readline().split(" ")] - links[ str(edge[0]) ].append( str(edge[1]) ) - links[ str(edge[1]) ].append( str(edge[0]) ) - -network["nodes"] = nodes -network["links"] = links -network["meta"] = lens - -mapper.visualize(network, color_function = "Lens average", path_html="mapper_visualization_output.html", title=dat, -graph_link_distance=30, graph_gravity=0.1, graph_charge=-120, custom_tooltips=custom, width_html=0, -height_html=0, show_tooltips=True, show_title=True, show_meta=True, res=param[0],gain=param[1], minimum=m,maximum=M) \ No newline at end of file -- cgit v1.2.3