-
Notifications
You must be signed in to change notification settings - Fork 99
/
Copy pathfixAnnotationLabelIDPatch.js
143 lines (127 loc) · 4.39 KB
/
fixAnnotationLabelIDPatch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const {MongoClient, ObjectID} = require("mongodb");
function randomId() {
// Math.random should be unique because of its seeding algorithm.
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
return `_${Math.random()
.toString(36)
.substr(2, 9)}`;
}
//
class FixAnnotationLabelIDPatch {
/**
* @constructor to initialize connection to database server
*/
constructor(mongoUrl="mongodb://ca-mongo", db="camic", recordPerBatch=20000) {
/** connection specifics */
this.mongoUrl = mongoUrl;
this.db = db;
this.labelMap = new Map();
/** connection configurations */
const configs = {
useUnifiedTopology: true,
useNewUrlParser: true,
};
this.client = new MongoClient(this.mongoUrl, configs);
// deal batch
this.totalBatch;
this.totalRecord;
this.currentBatch = 1;
this.recordPerBatch = recordPerBatch;
}
async run() {
console.log('FixAnnotationLabelIDPatch Start');
console.log(`waiting to connect ${this.mongoUrl}/${this.db}`);
await this.client.connect();
console.log(`[database:${this.db}] connected`);
// get connector
const connector = this.client.db(this.db);
// config_prelabel
const configCollection = connector.collection('configuration');
const query = {'config_name': 'preset_label'};
const opt = {};
const configData = await configCollection.findOne(query, opt);
// clear the label map
this.labelMap.clear();
configData.configuration.forEach((label)=>{
this.labelMap.set(label.type, label);
});
// preset label annotation without labelId
// provenance.analysis.labelId
// properties.annotations.labelId
const markCollection = connector.collection('mark');
this.totalRecord = await markCollection.countDocuments({
'provenance.analysis.source': 'human',
'provenance.analysis.type': 'label',
'provenance.analysis.labelId': {$exists: false},
});
// get total batch
this.totalBatch = Math.ceil(this.totalRecord/this.recordPerBatch);
console.log(`TOTAL Annotations Batches: ${this.totalBatch}`);
while (this.currentBatch <= this.totalBatch) {
const isCompleted = await this.runCurrentBatch(markCollection);
if (isCompleted) console.log(`Batch ${this.currentBatch} Completed`);
this.currentBatch++;
}
console.log('FixAnnotationLabelIDPatch End');
return true;
}
async runCurrentBatch(collection) {
console.log(`Running ${this.currentBatch} of ${this.totalBatch} Batches`);
// get current batch marks
const marks = await collection.find({
'provenance.analysis.source': 'human',
'provenance.analysis.type': 'label',
'provenance.analysis.labelId': {$exists: false},
}, {
geometries: 0,
skip: 0,
limit: this.recordPerBatch,
}).toArray();
for (let idx = 0; idx < marks.length; idx++) {
const mark = marks[idx];
console.log(`(${idx+1}/${marks.length}) => mark Id: ${mark._id}`);
const execId = mark.provenance.analysis.execution_id;
const executionId = execId.slice(execId.lastIndexOf('_'));
const labelType = mark.properties.annotations.notes;
// check if the label type on current marks exist on label map
var labelId;
if (this.labelMap.has(labelType)) {
const val = this.labelMap.get(labelType);
labelId = val.id;
} else {
// create a random Id for missing label type
labelId = randomId();
this.labelMap.set(labelType, {id: labelId});
}
// update annotation
const rs = await collection.updateOne({_id: new ObjectID(mark._id)}, {
'$set': {
'provenance.analysis.execution_id': executionId,
'provenance.analysis.labelId': labelId,
'provenance.analysis.name': labelType,
'properties.annotations.id': executionId,
'properties.annotations.labelId': labelId,
'properties.annotations.name': labelType,
},
});
if (rs.result.ok&&rs.result.nModified) {
console.log('update success');
} else {
console.error('update fail');
}
}
return true;
}
}
async function start() {
try {
const patch = new FixAnnotationLabelIDPatch();
const isCompleted = await patch.run();
if (isCompleted) process.exit();
} catch (error) {
console.error(error);
process.exit(1);
}
}
start();