def returnDataCirc(): """ API route - data for the simple circular layout, can apply order optimisation method before returning order """ # Get the data from the db sets = getData(request) # Filter for only values of length 2 # for biconnected graph this is sufficient as all supersets (i.e. orders greater than 2) must contain these subsets sets = [s for s in sets if len(s['labels']) == 2] # Apply order optimisation if "order_opt" in request.args: if request.args['order_opt'] == "avsdf": order = AVSDF([s['labels'] for s in sets], local_adjusting=False).run_AVSDF() elif request.args['order_opt'] == "avsdf_la": order = AVSDF([s['labels'] for s in sets], local_adjusting=True).run_AVSDF() elif request.args['order_opt'] == "bb": order = BaurBrandes([s['labels'] for s in sets], local_adjusting=False).run_bb() elif request.args['order_opt'] == "bb_la": order = BaurBrandes([s['labels'] for s in sets], local_adjusting=True).run_bb() else: abort(500, description="Optimisation type not recognised") else: if 'majmin_agg' in request.args: if request.args['majmin_agg']: order = default_order_agg else: order = default_order else: order = default_order return jsonify({"sets": sets, "order": order})
def test_degree3(self): self.assertEqual(AVSDF(self.edge_list3)._degree("A"), 7)
def test_degree2_2(self): self.assertEqual(AVSDF(self.edge_list2)._degree(55), 0)
def test_degree2(self): self.assertEqual(AVSDF(self.edge_list2)._degree("D"), 2)
def test_degree1(self): self.assertEqual(AVSDF(self.edge_list1)._degree("B"), 1)
def test_adj_vertex3(self): self.assertCountEqual( AVSDF(self.edge_list3)._adjacent_vertices("B"), ["B", "H", "A"])
def test_adj_vertex2(self): self.assertCountEqual( AVSDF(self.edge_list2)._adjacent_vertices("D"), ["G", "H", "D"])
def test_adj_vertex1(self): self.assertCountEqual( AVSDF(self.edge_list1)._adjacent_vertices("C"), [])
def test_adj_edges3(self): self.assertCountEqual( AVSDF(self.edge_list3)._adjacent_edges("A"), [["A", "B"], ["A", "C"], ["A", "D"], ["A", "E"], ["A", "F"], ["A", "G"], ["A", "H"]])
def test_adj_edges2(self): self.assertCountEqual( AVSDF(self.edge_list2)._adjacent_edges("H"), [["H", "D"], ["B", "H"]])
def test_adj_edges1_1(self): self.assertEqual(AVSDF(self.edge_list1)._adjacent_edges("C"), [])
def test_adj_edges1(self): self.assertEqual( AVSDF(self.edge_list1)._adjacent_edges("A"), [["A", "B"]])
def test_edge_crossings_number3(self): self.assertEqual( AVSDF([])._count_crossings_edge(self.order3, self.edge_list3, ["A", "C"]), 1)
def test_edge_crossings_number2(self): self.assertEqual( AVSDF([])._count_crossings_edge(self.order2, self.edge_list2, ["H", "B"]), 0)
def test_total_crossing_number_count3(self): self.assertEqual( AVSDF([])._count_all_crossings(self.order3, self.edge_list3), 5)
def returnCircClust(): """ API route - get data for circular chart with clustered bundling Applies transformation and clustering to similar edges based on node positions to allow edges to be bundled together """ # Get data from db sets = getData(request) # Filter for doubletons sets = [s for s in sets if len(s['labels']) == 2] # Apply order optimisation if "order_opt" in request.args: if request.args['order_opt'] == "avsdf": order = AVSDF([s['labels'] for s in sets], local_adjusting=False).run_AVSDF() elif request.args['order_opt'] == "avsdf_la": order = AVSDF([s['labels'] for s in sets], local_adjusting=True).run_AVSDF() elif request.args['order_opt'] == "bb": order = BaurBrandes([s['labels'] for s in sets], local_adjusting=False).run_bb() elif request.args['order_opt'] == "bb_la": order = BaurBrandes([s['labels'] for s in sets], local_adjusting=True).run_bb() else: abort(500, description="Optimisation type not recognised") else: if 'majmin_agg' in request.args: if request.args['majmin_agg']: order = default_order_agg else: order = default_order else: order = default_order # Leave only maj/min chords to see what it looks like clutter wise #sets = [s for s in sets if "7" not in "".join(s['labels'])] #order = [o for o in order if "7" not in o] # Map vertex labels to order index order_map = {k: i for i, k in enumerate(order)} # Dataframe (easier to manipulate/apply clustering) df = pd.DataFrame(sets) # Sort by order as clustering will be affected by the order of the vertices in edge definitions df['labels'] = df['labels'].apply(lambda x: sorted( x, key=lambda x: (np.sin( (order_map[x] / len(order_map)) * 2 * np.pi)))) # Sort set labels in order s_labels_ordered = list(df['labels']) # Apply sin/cos transformation (takes into account circular nature of data) df['sin1'] = df['labels'].apply(lambda x: np.sin( (order_map[x[0]] / len(order_map)) * 2 * np.pi)) df['cos1'] = df['labels'].apply(lambda x: np.cos( (order_map[x[0]] / len(order_map)) * 2 * np.pi)) df['sin2'] = df['labels'].apply(lambda x: np.sin( (order_map[x[1]] / len(order_map)) * 2 * np.pi)) df['cos2'] = df['labels'].apply(lambda x: np.cos( (order_map[x[1]] / len(order_map)) * 2 * np.pi)) # Apply clustering to edges based on node values #labs = KMeans(n_clusters=40,random_state=44).fit(df[['sin1','cos1','sin2','cos2']]).labels_ labs = AgglomerativeClustering(n_clusters=None, distance_threshold=1).fit( df[['sin1', 'cos1', 'sin2', 'cos2']]).labels_ # Add cluster label to returned JSON sets_w_lab = [] for set_lab, s, lab in zip(s_labels_ordered, sets, labs): sets_w_lab.append({ "labels": set_lab, "values": s['values'], "tag": s['tag'], "km_label": int(lab) }) return jsonify({"sets": sets_w_lab, "order": order})