Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 18 Next »

Functions available:

this.allowSubmission(Boolean)

this.changeFormValue(field_name, new_value)

this.enableField(field_name, Boolean)

this.disableField(field_name)

this.mandatoryField(field_name, Boolean)

this.changeInputValue(field_name, value)

let value =  JSON.stringify(finalValues)
this.updateAnnotations(value)

let errorMsgs = []if(errorMsgs.length > 0) {
  this.displayErrors(errorMsgs)
  this.disAllowSubmit(true)
} else {  
  this.disAllowSubmit(false)
}

this.changeAnnotationClasses(newClass);

let inputText = inputValues[field_name]

let currentUserId = localStorage.getItem("userId")
if(currentUserLevel === 1) {  
  this.changeFormValue(field_name, `${currentUserId}`)
}

For NER: 
let entities = _.get(annotations, "[0].value.annotations.entities", _.get(annotations, "annotations.entities", []))

To access form values in On-Change/on-Validation/On-save(also console the values coming from values and formValues then use as required):
  let fieldNameValue = values["field_name"]

To access previous values in the on change code: (Useful to check if a particular field's value has changed')
  let preValues = oldValues["field_name"]
  
To access annotations data in any annotation project
  let anns = annotations
  

Examples:

  1. Audio transcription validation: No special characters allowed, tags validations, etc.

let regexNotToMatch = {
  "Add at least one space before the normal start tag.": /[^ ]<[^\/]*[^\/]*>/g,
  "Add at least one space after the normal end tag.": /<\/\s*[^>]*>[^ ]/g,
  "Add at least one space before and after a single tag.": /[^ ]<[^>]*\/>[^ ]|[^ ]<[^>]*\/>|<[^>]*\/>[^ ]/g,
  "Numbers are not allowed.": /[0-9]/g,
  "Special character: ^ ( ) { } [ ] ; : $ % * = are not allowed.": /[\^(){}\[\];:$%*=]/g,
  "New line/Enter is not allowed.": /\n/g,
};
this.setState({ audioRegexNotToMatch: regexNotToMatch });

2. Generate 100 segments of transcription on load of a task:

let finalValues =[]
let i=0
while(i < 100 ) {
  i = i + 1
  finalValues.push( {
    "id": i,
    "curTime": 0,
    "endTime": i + 1,
    "startTime": i ,
    "UIstartTime": i + 1,
    "UIendTime": i,
    "split": 0,
    "audiourl": "",
    "pos": 0,
    "transliterationData": "abc def ghi jxy lzg".split(" ").map(w => ({
          "word": w,
          "tags": [],
          "languageTag": "",
          "editedText": ""
      }))
  })
}
 

let x =  JSON.stringify(finalValues)
this.updateAnnotations(x)

3. Load classes for annotation projects using custom code:

let newClass = {
  Books: JSON.stringify({
    "color": "#FFEBE8",
    "hotkey": "",
    "attributes": [
        {
            "name": "Price",
            "fieldType": "Text",
            "mandatoryField": false,
            "possible_value": [
                ""
            ],
            "default_value": ""
        }
    ]
  }),
  Car: JSON.stringify({
    "color": "#FF000",
    "hotkey": "c",
    "attributes": [
        {
            "name": "attr1",
            "fieldType": "DropDown",
            "mandatoryField": false,
            "possible_value": [
                "attr1_v1",
                "attr1_v2"
            ],
            "default_value": "attr1_v1"
        },
        {
            "name": "attr2",
            "fieldType": "DropDown",
            "mandatoryField": false,
            "possible_value": [
                "attr2_v1",
                "attr2_v2"
            ],
            "default_value": "attr2_v1"
        }
    ]
  }),
  Quills: JSON.stringify({
    "color": "#C23456",
    "hotkey": "q",
    "attributes": [
        {
            "name": "Colour",
            "fieldType": "Text",
            "mandatoryField": false,
            "possible_value": [
                "Blue",
                "Green",
                "Yellow",
                "Red",
                "White",
                "Orange"
            ],
            "default_value": "blue"
        }
    ]
  }),
  Tree: JSON.stringify({
    "color": "#CCC",
    "hotkey": "t",
    "attributes": [
        {
            "name": "attr1",
            "fieldType": "MultiDropDown",
            "mandatoryField": false,
            "possible_value": [
                "attr1_v1",
                "attr1_v2"
            ],
            "default_value": ""
        },
        {
            "name": "attr2",
            "fieldType": "Text",
            "mandatoryField": false,
            "possible_value": [
                ""
            ],
            "default_value": ""
        }
    ]
  }),
  Van: JSON.stringify({
    "color": "#F24110",
    "hotkey": "v",
    "attributes": [
        {
            "name": "Vans",
            "fieldType": "DropDown",
            "mandatoryField": false,
            "possible_value": [
                "Ferrari",
                "Kia",
                "MG"
            ],
            "default_value": ""
        }
    ]
  })
};

this.changeAnnotationClasses(newClass);

4. Add groups for image and video annotation using custom code:

let groupList = ["a", "b", "c", "d"]
localStorage.setItem("groups", JSON.stringify(groupList))

5. Load pre-annotations and classes from YOLO data

let yoloData = inputValues["yolo-data"]

// split yolo annotation data to array of individual anno data
let re = /\b[\w.]+(?:[^\w\n]+[\w.]+){0,4}\b/g
let arrYoloAnno = yoloData.match(re);

/* Start: configure unique classes from custom code*/
// let yoloClasses = []
// arrYoloAnno.forEach(y => {
//   let currentClass = y.substr(0, y.indexOf(" "))
//   if(!yoloClasses.includes(currentClass)){
//     yoloClasses.push(currentClass)
//   }
// })
// make class data
// let newClass = {}
// yoloClasses.forEach(c => {
//   let classValue = {
//     "color": '#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6), // random color
//     "hotkey": "",
//     "attributes": []
//   }
//   newClass[c] = JSON.stringify(classValue)
// })

// this.changeAnnotationClasses(newClass);
/* End */

/* Class data*/
let newClass = {
    "0": "Person",
    "1": "Class1",
    "2": "Class2",
    "3": "Class3",
    "4": "Class4",
    "5": "Class5",
    "6": "Class6",
    "7": "Class7",
    "8": "Class8",
    "9": "Class9",
    "99": "Face"
  }
/**/


/* Start: convert yolo data to TM anno format and setting it as pre anno */
/* 
The format of the YOLO label file is
Label_ID_1 X_CENTER_NORM Y_CENTER_NORM WIDTH_NORM HEIGHT_NORM
*/
let preAnno = arrYoloAnno.map((singleYoloAnno, ind) => {
  let singleAnnoSplitData = singleYoloAnno.split(" ")
  let X_CENTER = parseFloat(singleAnnoSplitData[1])
  let Y_CENTER = parseFloat(singleAnnoSplitData[2])
  let WIDTH_NORM = parseFloat(singleAnnoSplitData[3])/2
  let HEIGHT_NORM = parseFloat(singleAnnoSplitData[4])/2

  let firstPoint = [X_CENTER - WIDTH_NORM, Y_CENTER - HEIGHT_NORM]
  let secondPoint = [X_CENTER + WIDTH_NORM, Y_CENTER - HEIGHT_NORM]
  let thirdPoint = [X_CENTER + WIDTH_NORM, Y_CENTER + HEIGHT_NORM]
  let fourthPoint = [X_CENTER - WIDTH_NORM, Y_CENTER + HEIGHT_NORM]

  return ({
    "id":ind,
    "label":[newClass[singleAnnoSplitData[0]]],
    "shape":"rectangle",
    "points":[firstPoint,secondPoint,thirdPoint,fourthPoint],
    "notes":"",
    "annotationGroups":"",
    "attributes":{},
    "imageWidth":undefined,
    "imageHeight":undefined
  })
})
/* End */


let x =  JSON.stringify(preAnno)
this.updateAnnotations(x)

6. Load pre-annotations from an input field (When imported from cloud json files)

let preAnno = inputValues["Preannotations"]

if(!isNaN(currentUserLevel) && currentUserLevel == 1 && Array.isArray(annotations) && annotations.length > 0){
  let annoData = []
  let preAnnoArr = _.get(preAnno, "document.page[0].block", [])
  let tmAnnoFormat = preAnnoArr.map((val, i) => {
    return ({
      "id":i,
      "label":["car"],
      "shape":"rectangle",
      "points":[firstPoint,secondPoint,thirdPoint,fourthPoint],
      "notes":"",
      "annotationGroups":"",
      "attributes":{},
      "imageWidth":undefined,
      "imageHeight":undefined
    })
  })
  let x =  JSON.stringify(tmAnnoFormat)
  this.updateAnnotations(x)
}

7. Group label mandatory check for all objects

/* START */
let alertMessage = []
annotations.forEach(anno => {
  if(!_.get(anno, "annotationGroups") && !_.get(anno, "label", []).includes("other_value_text")) {
this.allowSubmit = false
    alertMessage.push(`One of the objects of class ${_.get(anno, "label", [])[0]} of shape ${_.get(anno, "shape", "")} has not been added to a group.`)
  }
})

if(alertMessage.length){
  this.displayErrors(alertMessage)
} else {
  this.allowSubmit = true
}
/* END */

8. NER: Load pre-annotations

let x = {"text":"Ceci","start":1,"end":5,"id":0,"ws":true}
var anns = {}
anns["version"] = 2
anns["annotations"] = {}
anns["annotations"]["entities"] = []
anns["annotations"]["entities"].push({
  "uuid": "1",
  "start_offset": x["start"],
  "end": x["end"],
  "entity_pos":"",
  "text": x["text"],
  "attributes":{},
  "taskId":"3517133",
  "entity_type":"ORG"
})
let updateAnnoData = [{
  "key": "3517133",
  "value": anns
}]
console.log('preanns', updateAnnoData)
this.updateAnnotations(updateAnnoData)

9. Track QC rejections using custom field.

let currentUserId = localStorage.getItem("userId")
if(currentUserLevel === 1){
  this.changeFormValue("annotator_id", `${currentUserId}`)
}
if(currentUserLevel === 2){
  this.changeFormValue("QA_id", `${currentUserId}`)
  if(rejectTaskDetails.commentHistory.length > 0){
    console.log("QA_Flag set to true on load")
    this.changeFormValue("QA_Flag", true)
  }
}

10. Format the NER output to plain text and write to an output field.

/* O/P format: "gemini(brand),100 grams(quantity) */
let entities = _.get(annotations, "[0].value.annotations.entities", _.get(annotations, "annotations.entities", []))
if (entities.length > 0) {
  entities.sort((a,b) => a.start_offset - b.start_offset)
  var requiredOp = entities.reduce((accumulator, currentValue) => accumulator + `${currentValue.text}(${currentValue.entity_type}),`, "")
  if(requiredOp[requiredOp.length - 1] == ","){
    requiredOp = requiredOp.slice(0, requiredOp.length-1)
  }
  this.changeFormValue("tagged_output", requiredOp)

11. Convert SRT to Taskmonk JSON and load pre-annotation for audio transcription.

function time2sec(dateTime) {
    let ms = dateTime.split(',')[1]
    let hh = dateTime.split(':')[0]
    let mm = dateTime.split(':')[1]
    let ss = dateTime.split(':')[2].split(',')[0]

    let ts = (parseInt(hh) * 3600) + (parseInt(mm) * 60) + parseInt(ss) + (parseInt(ms) / 1000)
    return ts
}

let finalValues = []
let inputArray = inputValues["TEXT"].split(/\n\s*\n/)


let i=0
while(i < inputArray.length) {
  i = i + 1
  if(inputArray[i]) {
  let startTime = time2sec(inputArray[i].split('\n')[1].split('-->')[0])
  let endTime = time2sec(inputArray[i].split('\n')[1].split('-->')[1])
  finalValues.push( {
    "id": i,
    "curTime": 0,
    "endTime": endTime,
    "startTime": startTime ,
    "UIstartTime": startTime,
    "UIendTime": endTime,
    "split": 0,
    "audiourl": "",
    "pos": 0,
    "transliterationData": inputArray[i].split('\n')[2].split(" ").map(w => ({
          "word": w,
          "tags": [],
          "languageTag": "",
          "editedText": ""
      }))
  })
  
  }
}
 
 
let x =  JSON.stringify(finalValues)
this.updateAnnotations(x)

12. On load custom code to convert gdrive sharing urls to viewing url.

function getIdFromUrl(url) { return url.match(/[-\w]{25,}/); }

let inputUrl = getIdFromUrl(inputValues["image"])[0]
this.changeInputValue("image", "https://drive.google.com/uc?export=view&id="+inputUrl)

13. Excel view: Update all visible tasks based on changes in one task

function getDupProdIds(tId, selectedInputValues, that) {
  let dupProdIds = []

  let selectedItemId = selectedInputValues["CATLG_ITEM_ID"]
  
  for (let i = 0; i < allTasks.length; i++) {
    let currentTaskInput = that.getInputValueByID(allTasks[i].taskValues.taskId)
    let currentTaskItemId = currentTaskInput["CATLG_ITEM_ID"]
    if(currentTaskItemId == selectedItemId)
      dupProdIds.push(currentTaskInput["productID"])
  }
  return dupProdIds
}
      
let that = this
let tIdsInputValues = this.getInputValueByID(tID)
let val = values["Select Action"];
if(val == "Duplicate"){
        let dpValuIds = getDupProdIds(tID, tIdsInputValues, that)
        //dpValuIds()
        console.log("dup", dpValuIds)
        this.changeFormValue("dup_productID", dpValuIds.join(), tID) 
} else {
        this.changeFormValue("dup_productID", tIdsInputValues["productID"], tID)
}

14. Enable/Disable Buttons:

The following custom code can be plugged in to disable/enable a few actions buttons conditionally.


i. To hide user action buttons

this.hideUserTaskButtons(["button 1 name", "button 2 name", …n])

ii. To unhide user action buttons

this.unhideUserTaskButtons(["button 1 name", "button 2 name", …n])

Available options for button names:

"SUBMIT & GET NEXT TASK"
"SAVE & EXIT"
"SKIP & GET NEXT TASK"
"SUBMIT TASK & EXIT"

15. Enable/Disable fields in Excel View/Bulk tasks.

let intentValue = values["Field_name"]
if (intentValue == "Field_name")
{ 

 this.enableField("Field_name",tID)
 this.enableField("Field_name",tID)
 this.mandatoryField("Field_name",true,tID)
 this.mandatoryField("Field_name",true,tID)
 } 
else if (intentValue == "Field_value" || intentValue == "Field_value" || intentValue == "Field_value" ||  intentValue == "Field_value" ||  intentValue == "Field_value" ) 
{
 this.disableField("Field_name",tID)
 this.disableField("Field_name",tID)
 this.changeFormValue("Field_name", " ",tID)
 this.changeFormValue("Field_name", " ",tID)
}

16. Extract ASIN,customID and keywords from Amazon URL’s

let getUrl = values["Competitor Exact URL"]

function ExtractASIN(url){
    var ASINreg = new RegExp(/(?:\/)([A-Z0-9]{10})(?:$|\/|\?)/)
    var  cMatch = url.match(ASINreg)
    if(cMatch == null){
        return null
    }
    return cMatch[1]
}

function ExtractCID(urls){
    var CustomCID = new RegExp(/customId=([A-Za-z0-9]+)/)
    var  cMatch1 = (urls).match(CustomCID)
    if(cMatch1 == null){
        return null
    }
    return cMatch1[1]
}
function ExtractKeywords(url) {
  const regex = /keywords=([^&]+)/;
  const match = url.match(regex);
  const keywords = match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;
  return keywords.replace(/\+/g, ' ');;
}
this.changeFormValue("Comp_ASIN", ExtractASIN(getUrl))
if (ExtractCID(getUrl)== null){
 this.changeFormValue("CustomID", "Not available")
 }
 else{
this.changeFormValue("CustomID", ExtractCID(getUrl))
}
if (ExtractKeywords(getUrl)== null){
 this.changeFormValue("Source_Of_Search", "Not available")
}
else {
this.changeFormValue("Source_Of_Search", ExtractKeywords(getUrl))
}

17. Generate rows in a name-value pair field

let lineItems = []
let i = 0
/* To generate two empty rows */
while(i < 2) {
    lineItems.push({
        "weight": "",
        "unit": ""
      })
      i += 1
  }
/* Variant is the field name */
if(Array.isArray(lineItems)){
  this.changeFormValue("Variant", JSON.stringify(lineItems))
}
  1. Calculation of IOU at level 3 for rejection logic

if(currentUserLevel == 3) {
  let totalIOU = 0
  let totalAnnotations = annotations.length
  
  for (let step = 0; step < totalAnnotations; step++) {
    // Current level annotation points for a box
    let ann1 = annotations[step]["points"]
    // Get previous level annotation points for the same box
    let ann2 = JSON.parse(initialValues["Annotations"])[step]["points"]
    
    let x1 = ann1[0][0]
    let x2 = ann1[2][0]
    let x3 = ann2[0][0]
    let x4 = ann2[2][0]
    
    let y1 = ann1[0][1]
    let y2 = ann1[2][1]
    let y3 = ann2[0][1]
    let y4 = ann2[2][1]
    
    let x_inter1 = Math.max(x1, x3)
    let x_inter2 = Math.min(x2, x4)
    
    let y_inter1 = Math.max(y1, y3)
    let y_inter2 = Math.min(y2, y4)
    
    console.log(x_inter1, y_inter2)
    let width = x_inter2 -x_inter1
    let height = y_inter2 - y_inter1
    
    let area_inter = width * height
    
    let width_box1 = x2 - x1
    let width_box2 = x4 - x3
    let height_box1 = y2 - y1
    let height_box2 = y4 - y3
    
    let area_box1 = width_box1 * height_box1
    let area_box2 = width_box2 * height_box2
    let area_union = area_box1 + area_box2 - area_inter
    let iou = area_inter / area_union
    totalIOU = totalIOU + iou
  }
  
  //Average IOU between level 3 and previous level annotations
  let avgIOU = totalIOU/totalAnnotations
  
  if (avgIOU < 0.90) {
    alert("IOU dropped below 0.9")
  }
}
  • No labels