Skip to content

Commit 88bd9ad

Browse files
committed
add task+labeling at frontend
1 parent 88eece5 commit 88bd9ad

File tree

7 files changed

+117
-56
lines changed

7 files changed

+117
-56
lines changed

src/datasets/dataset_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def check_sufficiency(
192192
if attr is None:
193193
raise ValueError(f"Attribute '{attr}' of metainfo should be defined.")
194194

195-
def check_consistency_with_dataset(
195+
def check_consistency_with_ptg_dataset(
196196
self,
197197
dataset: Dataset
198198
) -> None:

src/datasets/known_format_datasets.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def edge_attributes(
149149
def check_validity(
150150
self
151151
) -> None:
152-
""" Check that dataset files (graph and attributes) are valid and consistent with .info.
152+
""" Check that dataset files (graph and attributes) are valid and consistent with metainfo.
153153
"""
154154
# Assuming info is OK
155155
count = self.info.count
@@ -286,6 +286,8 @@ def _read_single(
286286
node_index = 0
287287
with open(self.edges_path, 'r') as f:
288288
for line in f.readlines():
289+
if line.startswith('#'):
290+
continue
289291
node_index = self._read_edge(line, node_index, node_map, ptg_edge_index)
290292

291293
self._ptg_edge_index = [torch.tensor(np.asarray(ptg_edge_index))]
@@ -304,7 +306,7 @@ def _read_single(
304306
self.node_map = list(node_map.keys())
305307
# self.info.node_info = {"id": self.node_map}
306308

307-
assert node_index == self.info.nodes[0]
309+
assert node_index == self.info.nodes[0], f"Number of nodes in file {node_index} != {self.info.nodes[0]} - number of nodes in metainfo"
308310
assert len(self._ptg_edge_index) == self.info.count
309311

310312
def _read_multi(
@@ -465,11 +467,11 @@ def _labeling_tensor(
465467
g_ix: int = None
466468
) -> list[int] | None:
467469
""" Returns list of labels (not tensors) """
468-
y = []
469-
if self.dataset_var_config.labeling is None: # e.g. link prediction
470+
task = self.dataset_var_config.task
471+
if task == Task.EDGE_PREDICTION:
470472
return None
471473
# Read labels
472-
task = self.dataset_var_config.task
474+
y = []
473475
labeling_path = self.labels_dir / task / self.dataset_var_config.labeling
474476
with open(labeling_path, 'r') as f:
475477
labeling_dict = json.load(f)

src/datasets/ptg_datasets.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,11 @@ def induce_dataset_info(
164164
if hasattr(self.dataset, 'num_classes'):
165165
if self.dataset.num_classes == 0:
166166
raise NotImplementedError("Datasets without classes are not supported")
167-
task = Task.NODE_CLASSIFICATION if len(self.dataset) == 1 else Task.GRAPH_CLASSIFICATION
168-
res.labelings = {task: {"origin": self.dataset.num_classes}}
167+
classification_task = Task.NODE_CLASSIFICATION if len(self.dataset) == 1 else Task.GRAPH_CLASSIFICATION
168+
# TODO if edges have attributes, add edge classification
169+
res.labelings = {
170+
classification_task: {"origin": self.dataset.num_classes},
171+
}
169172
else:
170173
res.labelings = "?"
171174
msg += f"Cannot get num_classes Dataset of type {self.dataset.__class__}. "

src/datasets/visible_part.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,12 @@ def get_dataset_var_data(
324324
dataset_var_data.labels = {}
325325

326326
node_features = self.gen_dataset.node_features
327-
labels = self.gen_dataset.labels.tolist()
328-
329327
for ix in index.ixes:
330328
dataset_var_data.node_features[ix] = node_features[ix].tolist()
331-
dataset_var_data.labels[ix] = labels[ix]
329+
330+
if self.gen_dataset.labels:
331+
labels = self.gen_dataset.labels.tolist()
332+
for ix in index.ixes:
333+
dataset_var_data.labels[ix] = labels[ix]
332334

333335
return dataset_var_data

web_interface/back_front/dataset_blocks.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ def _finalize(
114114
features = FeatureConfig(**kwargs.pop('features'))
115115
kwargs['features'] = features
116116
self.dataset_var_config = DatasetVarConfig(**kwargs)
117+
# print(self.dataset_var_config.to_dict())
117118
return True
118119

119120
def _submit(

web_interface/static/js/presentation/dataset/visibleGraph.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ const PREDICTION_COLORMAP = 'binary'
33
const EMBEDDING_COLORMAP = 'bwr'
44
const CORRELATION_COLORMAP = 'bwr'
55
const EDGE_MINIBATCH_SIZE = 10000 // Not necessary
6-
const LIGHT_MODE_SCALE_THRESHOLD_SINGLE = 50 // When Scale < THR, light mode is on to improve visibility (for single graph)
6+
// todo make customizable
7+
const LIGHT_MODE_SCALE_THRESHOLD_SINGLE = 5 // When Scale < THR, light mode is on to improve visibility (for single graph)
78
const LIGHT_MODE_SCALE_THRESHOLD_MULTI = 20 // When Scale < THR, light mode is on to improve visibility (for multiple graph)
89
const EXPLANATION_EDGE_IMPORTANCE_THRESHOLD = 0.5 // When edge importance < THR, it is not drawn
910

@@ -448,7 +449,8 @@ class VisibleGraph {
448449
else if (satellite in this.datasetVar) {
449450
let values = this.datasetVar[satellite]
450451
if (satellite === 'labels') {
451-
let numClasses = this.datasetInfo["labelings"][this.labeling]
452+
// FIXME tmp
453+
let numClasses = this.datasetInfo["labelings"]["node-classification"][this.labeling]
452454
for (const [i, node] of Object.entries(this.nodePrimitives)) {
453455
node.setLabels(values[i], numClasses)
454456
for (const e of node.satellites[satellite].blocks)

web_interface/static/js/presentation/left_menu/dataset/menuDatasetVarView.js

Lines changed: 94 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ class MenuDatasetVarView extends MenuView {
55
this.datasetInfo = null
66

77
// Selectors
8+
this.task = null // which task is chosen
89
this.labeling = null // which labeling is chosen
10+
this.$oneHotNodeInput = null
11+
this.$tenOnesNodeInput = null
912
this.$nodeClusteringInput = null
1013
this.$nodeDegreeInput = null
11-
this.$oneHotNodeInput = null
12-
// this.$attackTypeSelect = null
1314
}
1415

1516
init(datasetInfo) {
@@ -104,15 +105,53 @@ class MenuDatasetVarView extends MenuView {
104105
if (this.datasetInfo.count === 1) {
105106
$cc.append($("<label></label>").html("<h4>Global structural</h4>"))
106107

108+
// 1-hot over nodes
107109
$cb = $("<div></div>").attr("class", "control-block")
108110
$cc.append($cb)
109111
id = this.idPrefix + "-node-1hot-input"
110112
size = this.datasetInfo["nodes"].sum()
111-
this.$oneHotNodeInput = $("<input>").attr("type", "checkbox").attr("id", id)
113+
this.$oneHotNodeInput = $("<input>")
114+
.attr("type", "checkbox").attr("id", id)
112115
$cb.append(this.$oneHotNodeInput)
113-
$cb.append($("<label></label>").text(`1-hot input (size=${size})`).attr("for", id))
114-
} else
116+
$cb.append($("<label></label>")
117+
.text(`1-hot ovre nodes (size=${size})`).attr("for", id))
118+
119+
// 10 ones
120+
$cb = $("<div></div>").attr("class", "control-block")
121+
$cc.append($cb)
122+
id = this.idPrefix + "-node-10ones-input"
123+
this.$tenOnesNodeInput = $("<input>")
124+
.attr("type", "checkbox").attr("id", id)
125+
$cb.append(this.$tenOnesNodeInput)
126+
$cb.append($("<label></label>")
127+
.text("10 ones (size=10)").attr("for", id))
128+
129+
// Degree
130+
$cb = $("<div></div>").attr("class", "control-block")
131+
$cc.append($cb)
132+
id = this.idPrefix + "-node-degree-input"
133+
this.$nodeDegreeInput = $("<input>")
134+
.attr("type", "checkbox").attr("id", id)
135+
$cb.append(this.$nodeDegreeInput)
136+
$cb.append($("<label></label>")
137+
.text("degree (size=1)").attr("for", id))
138+
139+
// Clustering
140+
$cb = $("<div></div>").attr("class", "control-block")
141+
$cc.append($cb)
142+
id = this.idPrefix + "-node-clustering-input"
143+
this.$nodeClusteringInput = $("<input>")
144+
.attr("type", "checkbox").attr("id", id)
145+
$cb.append(this.$nodeClusteringInput)
146+
$cb.append($("<label></label>")
147+
.text("clustering (size=1)").attr("for", id))
148+
}
149+
else {
115150
this.$oneHotNodeInput = null
151+
this.$tenOnesNodeInput = null
152+
this.$nodeClusteringInput = null
153+
this.$nodeDegreeInput = null
154+
}
116155

117156
// Node attributes
118157
$cc.append($("<label></label>").html("<h4>Node attributes</h4>"))
@@ -148,32 +187,43 @@ class MenuDatasetVarView extends MenuView {
148187
// 2. class labels
149188
$cc.append($("<div></div>").attr("class", "menu-separator"))
150189

151-
$cc.append($("<label></label>").html("<h3>Class labeling</h3>"))
152-
// TODO 2 cases
153-
let labelingClasses = this.datasetInfo["labelings"]
154-
for (const [labeling, classes] of Object.entries(labelingClasses)) {
155-
let $cb = $("<div></div>").attr("class", "control-block")
156-
$cc.append($cb)
157-
let id = this.idPrefix + "-labelings-" + nameToId(labeling)
158-
let $input = $("<input>").attr("type", "radio").attr("name", "dataset-variable-labelings").attr("id", id).attr("value", labeling)
159-
$cb.append($input)
160-
$cb.append($("<label></label>").text(labeling + ` (${classes} classes)`).attr("for", id))
161-
// TODO can do this if graph is small
162-
// $input.change(() => this.setLabels(labeling))
190+
$cc.append($("<label></label>").html("<h3>Task & labeling</h3>"))
191+
let taskLabelings = this.datasetInfo["labelings"]
192+
// Add edge prediciton
193+
taskLabelings["edge-prediction"] = {"default": null}
194+
let checked = false
195+
for (const [task, labelingValue] of Object.entries(taskLabelings)) {
196+
$cc.append($("<label></label>").html(`<h4>${task}</h4>`))
197+
for (const [labeling, value] of Object.entries(labelingValue)) {
198+
let $cb = $("<div></div>").attr("class", "control-block")
199+
$cc.append($cb)
200+
let id = this.idPrefix + "-labelings-" + nameToId(task + labeling)
201+
let $input = $("<input>").attr("type", "radio")
202+
.attr("name", "dataset-variable-labelings")
203+
.attr("id", id).attr("value", labeling)
204+
$cb.append($input)
205+
let text = labeling
206+
if (task.endsWith("classification"))
207+
text += ` (${value} classes)`
208+
209+
$cb.append($("<label></label>").text(text)
210+
.attr("for", id))
211+
$input.change(() => {
212+
this.task = task
213+
this.labeling = labeling
214+
})
215+
216+
// Check the first option
217+
if (!checked) {
218+
$input.change()
219+
$input.prop('checked', true)
220+
checked = true
221+
}
222+
}
163223
}
164-
this.labeling = Object.keys(labelingClasses)[0]
165-
$('#' + this.idPrefix + "-labelings-" + nameToId(this.labeling)).prop("checked", true)
166-
167-
// // 3. Add options for attack type
168-
// $cc.append($("<div></div>").attr("class", "menu-separator"))
169-
// $cb = $("<div></div>").attr("class", "control-block")
170-
// $cc.append($cb)
171-
// $cb.append($("<label></label>").text("Attack"))
172-
// this.$attackTypeSelect = $("<select></select>").attr("id", this.idPrefix + "-attack")
173-
// $cb.append(this.$attackTypeSelect)
174-
// // TODO need possible attack types here
175-
// let attack = "original"
176-
// this.$attackTypeSelect.append($("<option></option>").text(attack))
224+
// this.task = Object.keys(taskLabelings)[0]
225+
// this.labeling = Object.keys(taskLabelings)[0]
226+
// $('#' + this.idPrefix + "-labelings-" + nameToId(this.labeling)).prop("checked", true)
177227

178228
this.appendAcceptBreakButtons()
179229
// this.$acceptDiv.hide()
@@ -188,32 +238,33 @@ class MenuDatasetVarView extends MenuView {
188238
attrsChecked.push($('#' + id).is(':checked'))
189239
}
190240

191-
// If no attributes checked, check oneHotNodeInput
192-
if (attrs.length > 0 && !attrsChecked.reduce((a, v) => a || v, false)) {
193-
if (this.$oneHotNodeInput == null)
241+
// Fill features according to format
242+
let features = {"node_struct": [], "node_attr": []}
243+
// If no attributes , check oneHotNodeInput
244+
if (attrs.length === 0 || (attrs.length > 0 && !attrsChecked.reduce((a, v) => a || v, false))) {
245+
if (this.$tenOnesNodeInput == null)
194246
console.error("No attributes and no node 1-hot - features will be null!")
195247
else
196-
this.$oneHotNodeInput.prop('checked', true)
248+
this.$tenOnesNodeInput.prop('checked', true)
197249
}
198250

199-
// Fill features according to format
200-
let features = {"node_struct": [], "node_attr": []}
201-
// if (this.$nodeClusteringInput.is(":checked"))
202-
// features["node_struct"].push("clustering")
203-
// if (this.$nodeDegreeInput.is(":checked"))
204-
// features["node_struct"].push("degree")
205251
if (this.$oneHotNodeInput && this.$oneHotNodeInput.is(":checked"))
206252
features["node_struct"].push("one_hot")
253+
if (this.$tenOnesNodeInput && this.$tenOnesNodeInput.is(":checked"))
254+
features["node_struct"].push("10-ones")
255+
if (this.$nodeClusteringInput && this.$nodeClusteringInput.is(":checked"))
256+
features["node_struct"].push("clustering")
257+
if (this.$nodeDegreeInput && this.$nodeDegreeInput.is(":checked"))
258+
features["node_struct"].push("degree")
207259
for (let i = 0; i < attrs.length; i++) {
208260
if (attrsChecked[i])
209261
features["node_attr"].push(attrs[i])
210262
}
211-
this.labeling = $("input[name='dataset-variable-labelings']:checked").val()
212263

213264
let datasetVarConfig = {
214-
features: features,
265+
task: this.task,
215266
labeling: this.labeling,
216-
// dataset_attack_type: this.$attackTypeSelect.val(),
267+
features: features,
217268
dataset_ver_ind: 0, // TODO check
218269
}
219270
await controller.blockRequest(this.requestBlock, 'modify', datasetVarConfig)

0 commit comments

Comments
 (0)