diff --git a/.github/workflows/release-workflow.yml b/.github/workflows/release-workflow.yml index 98b46fe6..264f0413 100644 --- a/.github/workflows/release-workflow.yml +++ b/.github/workflows/release-workflow.yml @@ -62,7 +62,6 @@ jobs: else chmod u+x ../../portal_build/dist/run.exe fi - chmod u+x ../../portal_build/dist/run.exe # Install Node.js - uses: actions/setup-node@v1.4.4 diff --git a/Pipfile b/Pipfile index c205e950..98de8e19 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,6 @@ flask-cors = "==3.0.10" flask-restful = "==0.3.9" flask-socketio = "==5.1.0" jsonpickle = "==2.0.0" -numpy = "==1.21.6" onnx = "==1.12.0" onnx2torch = "==1.5.6" onnxruntime = "==1.14.1" diff --git a/package-lock.json b/package-lock.json index 30849ff4..fd830d36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "portal", - "version": "0.5.8", + "version": "0.5.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "portal", - "version": "0.5.8", + "version": "0.5.9", "hasInstallScript": true, "dependencies": { "cross-env": "^7.0.3", diff --git a/package.json b/package.json index ce3034fa..305bb656 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "portal", - "version": "0.5.8", + "version": "0.5.9", "author": "Datature", "private": true, "main": "./src/app/main.js", diff --git a/portal.py b/portal.py index 55b3341f..fc1fc79d 100644 --- a/portal.py +++ b/portal.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : portal.py @Author : Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Script to run portal from the command line. -''' +""" import os import sys diff --git a/portal_build/out/404.html b/portal_build/out/404.html index bfec1d2c..1becdc83 100644 --- a/portal_build/out/404.html +++ b/portal_build/out/404.html @@ -1 +1 @@ -404: This page could not be found

404

This page could not be found.

\ No newline at end of file +404: This page could not be found

404

This page could not be found.

\ No newline at end of file diff --git a/portal_build/out/_next/static/-okSBu0eZBiiVwwPyzfsk/_buildManifest.js b/portal_build/out/_next/static/E8-FaGr6X6QP36v3hGmg_/_buildManifest.js similarity index 60% rename from portal_build/out/_next/static/-okSBu0eZBiiVwwPyzfsk/_buildManifest.js rename to portal_build/out/_next/static/E8-FaGr6X6QP36v3hGmg_/_buildManifest.js index ab12eca8..0b09bf1e 100644 --- a/portal_build/out/_next/static/-okSBu0eZBiiVwwPyzfsk/_buildManifest.js +++ b/portal_build/out/_next/static/E8-FaGr6X6QP36v3hGmg_/_buildManifest.js @@ -1 +1 @@ -self.__BUILD_MANIFEST=function(s,a){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,a,"static/chunks/835-91f7fb22de8eba0dd168.js","static/css/5441740d7d3b11650f51.css","static/chunks/pages/index-cdaa5643ad13fe164f94.js"],"/_error":["static/chunks/pages/_error-601c334056601a913688.js"],"/error":["static/chunks/pages/error-fdcb7b6987fa4610b3f6.js"],"/loading":[s,a,"static/chunks/pages/loading-935ccd8c6cfed757f093.js"],sortedPages:["/","/_app","/_error","/error","/loading"]}}("static/chunks/d3fccaa0-63df7080f69094ec068d.js","static/chunks/706-4b659fb8192237151302.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file +self.__BUILD_MANIFEST=function(s,e){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,e,"static/chunks/835-91f7fb22de8eba0dd168.js","static/css/5441740d7d3b11650f51.css","static/chunks/pages/index-8da26dc3ba2af71eb1da.js"],"/_error":["static/chunks/pages/_error-601c334056601a913688.js"],"/error":["static/chunks/pages/error-fdcb7b6987fa4610b3f6.js"],"/loading":[s,e,"static/chunks/pages/loading-935ccd8c6cfed757f093.js"],sortedPages:["/","/_app","/_error","/error","/loading"]}}("static/chunks/d3fccaa0-63df7080f69094ec068d.js","static/chunks/706-4b659fb8192237151302.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file diff --git a/portal_build/out/_next/static/-okSBu0eZBiiVwwPyzfsk/_ssgManifest.js b/portal_build/out/_next/static/E8-FaGr6X6QP36v3hGmg_/_ssgManifest.js similarity index 100% rename from portal_build/out/_next/static/-okSBu0eZBiiVwwPyzfsk/_ssgManifest.js rename to portal_build/out/_next/static/E8-FaGr6X6QP36v3hGmg_/_ssgManifest.js diff --git a/portal_build/out/_next/static/FieKmwHUwLbNGcmRBcvct/_buildManifest.js b/portal_build/out/_next/static/FieKmwHUwLbNGcmRBcvct/_buildManifest.js new file mode 100644 index 00000000..0b09bf1e --- /dev/null +++ b/portal_build/out/_next/static/FieKmwHUwLbNGcmRBcvct/_buildManifest.js @@ -0,0 +1 @@ +self.__BUILD_MANIFEST=function(s,e){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,e,"static/chunks/835-91f7fb22de8eba0dd168.js","static/css/5441740d7d3b11650f51.css","static/chunks/pages/index-8da26dc3ba2af71eb1da.js"],"/_error":["static/chunks/pages/_error-601c334056601a913688.js"],"/error":["static/chunks/pages/error-fdcb7b6987fa4610b3f6.js"],"/loading":[s,e,"static/chunks/pages/loading-935ccd8c6cfed757f093.js"],sortedPages:["/","/_app","/_error","/error","/loading"]}}("static/chunks/d3fccaa0-63df7080f69094ec068d.js","static/chunks/706-4b659fb8192237151302.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file diff --git a/portal_build/out/_next/static/FieKmwHUwLbNGcmRBcvct/_ssgManifest.js b/portal_build/out/_next/static/FieKmwHUwLbNGcmRBcvct/_ssgManifest.js new file mode 100644 index 00000000..0511aa89 --- /dev/null +++ b/portal_build/out/_next/static/FieKmwHUwLbNGcmRBcvct/_ssgManifest.js @@ -0,0 +1 @@ +self.__SSG_MANIFEST=new Set,self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB(); \ No newline at end of file diff --git a/portal_build/out/_next/static/chunks/607.576e9e84426511ff810c.js b/portal_build/out/_next/static/chunks/607.9f07b963d28c2ca7e4ae.js similarity index 82% rename from portal_build/out/_next/static/chunks/607.576e9e84426511ff810c.js rename to portal_build/out/_next/static/chunks/607.9f07b963d28c2ca7e4ae.js index 0a4622a2..e0263ce2 100644 --- a/portal_build/out/_next/static/chunks/607.576e9e84426511ff810c.js +++ b/portal_build/out/_next/static/chunks/607.9f07b963d28c2ca7e4ae.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[607],{4607:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return we}});var a=n(5579),o=n(4121),i=n(809),s=n.n(i),r=n(2447),l=n(4047),c=n(2700),u=n(4706),d=n(8127),p=n(4102),h=n(775),f=n(6265),m=n(5243),g=(n(1787),n(7294)),v=n.n(g),y=n(2689),b=n(2609),S=n(9481),A=n.n(S),k=n(8770),Z=function(e,t){return function(e){return k._[e%k._.length]}(t)};var w=n(7316),O=n(6486),I=n(9231),T=function(){function e(t,n){return(0,l.Z)(this,e),(0,f.Z)(this,"_map",void 0),(0,f.Z)(this,"_annotator",void 0),null===e.instance&&(this._map=t,this._annotator=n,e.instance=this),e.instance}return(0,c.Z)(e,null,[{key:"map",get:function(){var t;void 0===e.instance._map&&(e.instance._map=null===(t=e.instance._annotator)||void 0===t?void 0:t.map);return e.instance._map}},{key:"annotator",get:function(){return e.instance._annotator}}]),e}();(0,f.Z)(T,"instance",null);var C=T,D=n(9999),N=n(3766),x=n(9984),R=n.n(x),P=v().createElement;function F(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var E=function(e){(0,d.Z)(n,e);var t=F(n);function n(e){return(0,l.Z)(this,n),t.call(this,e)}return(0,c.Z)(n,[{key:"render",value:function(){var e=P(y.zx,{icon:this.props.showSelected?"eye-open":"eye-off",onClick:this.props.callbacks.ToggleShowSelected});return P(v().Fragment,null,P(y.EG,{className:this.props.useDarkTheme?"bp3-dark":"",rightElement:e,values:this.props.filterArr,placeholder:"Enter filters here...",onChange:this.props.callbacks.SetFilterArr}))}}]),n}(v().Component),_=v().createElement;function L(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var j={fill:!0,minimal:!0,round:!1,interactive:!0,className:"annotator-tags"};function M(e,t){var n={backgroundColor:k._[t%k._.length],fontSize:"12px",display:"inline-block",borderRadius:"3px",textAlign:"center",padding:"2px",width:"15px",height:"8px"};return _("div",{style:n})}var V=function(e){(0,d.Z)(n,e);var t=L(n);function n(e){var a;return(0,l.Z)(this,n),(a=t.call(this,e)).state={selectedTag:0,selectedAnnotationID:"",annotations:[]},a.tagIDtoDisplayIndex={},a.tagNames={},a.annotationRefs={},a.tagCount={},a.hiddenTagCount={},a.setAnnotationTag=a.setAnnotationTag.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"setAnnotations",value:function(e){var t=this,n=Object.values(e._layers);n.sort((function(e,n){var a=t.tagIDtoDisplayIndex[e.options.annotationTag]-t.tagIDtoDisplayIndex[n.options.annotationTag];return 0!==a?a:e.options.annotationIDn.options.annotationID?1:0})),this.annotationRefs={},this.tagCount={},n.forEach((function(e){t.annotationRefs[e.options.annotationID]=v().createRef(),t.tagCount[e.options.annotationTag]=(t.tagCount[e.options.annotationTag]||0)+1}));var a=n.reduce((function(e,t,a){return 0===a||t.options.annotationTag!==n[a-1].options.annotationTag?e.push([t,1]):e.push([t,e[a-1][1]+1]),e}),[]);this.setState({annotations:a})}},{key:"setAnnotationTag",value:function(e){this.setState({selectedTag:e}),this.props.callbacks.SetAnnotationTag(e)}},{key:"setSelectedAnnotation",value:function(e){null!==e?(this.setState({selectedAnnotationID:e.options.annotationID}),this.annotationRefs[e.options.annotationID].current.scrollIntoView({block:"nearest"})):this.setState({selectedAnnotationID:""})}},{key:"generateTagHideIcon",value:function(e){var t=this,n=!(e in this.tagCount)||this.hiddenTagCount[e]!==this.tagCount[e];return _(y.JO,{icon:n?"eye-open":"eye-off",className:R().SpacedIcon,onClick:function(a){var o;a.stopPropagation(),(o=t.props.callbacks).SetAnnotationVisibility.apply(o,[!n].concat((0,D.Z)(t.state.annotations.map((function(e){return e[0]})).filter((function(t){return t.options.annotationTag===e})))))}})}},{key:"generateAnnotationHideIcon",value:function(e){var t=this,n=!this.props.hiddenAnnotations.has(e.options.annotationID);return _(y.JO,{icon:n?"eye-open":"eye-off",onClick:function(a){a.stopPropagation(),t.props.callbacks.SetAnnotationVisibility(!n,e)}})}},{key:"updateHiddenTagCount",value:function(){var e=this;this.hiddenTagCount={},this.state.annotations.forEach((function(t){if(e.props.hiddenAnnotations.has(t[0].options.annotationID)){var n=t[0].options.annotationTag;e.hiddenTagCount[n]=(e.hiddenTagCount[n]||0)+1}}))}},{key:"render",value:function(){var e=this;this.updateHiddenTagCount();var t=_("div",{className:["tag-list",R().TagList].join(" ")},Object.entries(this.props.projectTags).filter((function(t){var n=(0,o.Z)(t,2),a=n[0];n[1];return 0===e.props.filterArr.length||e.props.filterArr.some((function(e){return a.toLowerCase()===e.toLowerCase()}))===e.props.showSelected})).map((function(t,n){var i=(0,o.Z)(t,2),s=i[0],r=i[1];return e.tagIDtoDisplayIndex[r]=n,e.tagNames[r]=s,_(y.Vp,(0,a.Z)({className:R().MenuTag,key:r},j,{active:n===e.state.selectedTag,rightIcon:_("div",null,e.generateTagHideIcon(r),M(0,r)),onClick:function(){e.setAnnotationTag(n)}}),s)}))),n=_("div",{className:["tag-list",R().TagList].join(" ")},this.state.annotations.filter((function(t){var n=(0,o.Z)(t,2),a=n[0];n[1];return a.options.confidence>e.props.confidence&&(0===e.props.filterArr.length||e.props.showSelected===e.props.filterArr.some((function(t){return e.tagNames[a.options.annotationTag].toLowerCase().includes(t.toLowerCase())})))})).map((function(t){var n=(0,o.Z)(t,2),i=n[0],l=n[1];return _(y.Vp,(0,a.Z)({className:R().MenuTag,key:i.options.annotationID.split("-")[0],elementRef:e.annotationRefs[i.options.annotationID]},j,{active:i.options.annotationID===e.state.selectedAnnotationID,rightIcon:_("div",null,e.generateAnnotationHideIcon(i)),onClick:(0,r.Z)(s().mark((function t(){return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.props.callbacks.SetAnnotationVisibility(!0,i);case 2:i.fire("click");case 3:case"end":return t.stop()}}),t)})))}),_(y.JO,{icon:"rectangle"===i.options.annotationType?"widget":"polygon-filter",iconSize:12,style:{color:k._[i.options.annotationTag%k._.length],marginRight:"5px",marginBottom:"2px"}}),"".concat(e.tagNames[i.options.annotationTag]," ").concat(l))})));return _(v().Fragment,null,_(y.v2,{className:"main-menu bp3-elevation-1"},_(y.sN,{icon:"graph",text:"Annotator Controls"}),_(y.R,{title:"Assets Folder"}),this.props.isSyncing?_(y.$j,{size:30,className:R().Spin}):_(v().Fragment,null,_(y.sN,{icon:"folder-new",text:"Open Folder",label:_(y.M2,{combo:"O"}),onClick:this.props.callbacks.OpenFileManagement}),_(y.sN,{icon:"repeat",text:"Sync All Folders",label:_(y.M2,{combo:"S"}),onClick:this.props.callbacks.SyncAllFolders})),_(y.R,{title:"Inference"}),0===this.props.predictDone?_(y.u,{content:"Load Model and Image before analysing",position:N.Ly.TOP,disabled:this.props.isConnected&&this.props.loadedModel&&!(0,O.isEmpty)(this.props.assetList)},_("div",{className:R().InferenceMenuItem},_(y.sN,{disabled:!this.props.isConnected||!this.props.loadedModel||(0,O.isEmpty)(this.props.currentAsset),icon:"ring",text:"Analyze",label:_(y.M2,{combo:"A"}),className:"Re-Analyse"===this.props.userEditState?"bp3-active":"",onClick:function(){return e.props.callbacks.SingleAnalysis()}}),_(y.sN,{disabled:!this.props.isConnected||!this.props.loadedModel||(0,O.isEmpty)(this.props.assetList),icon:"heat-grid",text:"Bulk Analysis",label:_(y.M2,{combo:"B"}),className:"Bulk Analysis"===this.props.userEditState?"bp3-active":"",onClick:this.props.callbacks.BulkAnalysis}))):_(y.$j,{size:30,className:R().Spin}),_(y.R,{title:"Confidence Threshold"}),_(y.iR,{className:R().Slider,min:0,max:100,onChange:this.props.callbacks.ToggleConfidence,stepSize:1,labelStepSize:100,value:100*this.props.confidence,vertical:!1}),_(y.R,null),_(y.sN,{icon:"new-text-box",text:"Advanced Settings",onClick:this.props.callbacks.OpenAdvancedSettings}),_(y.R,{title:"Filter Tags"}),_(E,(0,a.Z)({showSelected:this.state.showSelected,filterArr:this.state.filterArr,callbacks:{SetFilterArr:this.setFilterArr,ToggleShowSelected:this.toggleShowSelected}},this.props)),_(y.R,null),_(y.mQ,{className:R().SelectionList},_(y.OK,{id:"annotation-objects",title:"Objects",panel:n}),_(y.OK,{id:"project-tags",title:"Tag Map",panel:t}))))}}]),n}(g.Component),U=n(5767),J=n.n(U),G=n(7019),H=n.n(G),z=v().createElement;function q(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var B=function(e){(0,d.Z)(n,e);var t=q(n);function n(e){var a;return(0,l.Z)(this,n),a=t.call(this,e),(0,f.Z)((0,u.Z)(a),"currentAssetID",void 0),a.currentAssetID="",a.highlightAsset=a.highlightAsset.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"highlightAsset",value:function(e){this.currentAssetID=e,this.forceUpdate()}},{key:"render",value:function(){var e=this;return z(v().Fragment,null,this.props.assetList.map((function(t){return n=t,a=t.assetUrl,o=e.props.useDarkTheme,i=e.props.callbacks.selectAssetCallback,s=e.currentAssetID,z(y.Zb,{className:["image-bar-thumbnail-card",H().Card].join(" "),key:a,onClick:function(){return i(n)}},z("div",{className:n.assetUrl===s?"image-bar-thumbnail image-bar-thumbnail-highlighted":"image-bar-thumbnail"},"video"===n.type?z(v().Fragment,null," ",z(y.JO,{className:H().StackTop,icon:"video",iconSize:y.Jh.STANDARD}),z("div",null,z(J(),{width:150,length:150,snapshotAtTime:1,videoUrl:n.thumbnailUrl}))):z("img",{src:n.thumbnailUrl,alt:n.filename}),z(y.Vp,{className:["image-bar-filename-tag",H().Tag].join(" "),fill:!0,style:{backgroundColor:o?"":"#CED9E0"},rightIcon:!!n.isCached&&z(y.u,{content:"Inference is Cached by Model",position:N.Ly.TOP},z(y.JO,{icon:"bookmark",color:o?"#0F9960":"#3DCC91"}))},z("span",{className:"bp3-ui-text bp3-monospace-text image-bar-filename-text"},n.filename))));var n,a,o,i,s})))}}]),n}(g.Component),K=n(451),W=n(1164),Y=n.n(W),Q=v().createElement;function $(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var X=function(e){(0,d.Z)(n,e);var t=$(n);function n(e){return(0,l.Z)(this,n),t.call(this,e)}return(0,c.Z)(n,[{key:"render",value:function(){var e=this;return Q(y.Vq,(0,a.Z)({icon:"cog",title:"Advanced Settings",canEscapeKeyClose:this.props.allowUserClose,canOutsideClickClose:this.props.allowUserClose,className:this.props.useDarkTheme?"bp3-dark":""},this.props),Q("div",{className:Y().Dialog},Q("div",{className:K.TmF},Q("div",null,"General"),Q("div",{className:Y().Section},Q(y.eQ,{className:Y().SubTitle},Q("div",null,"Bulk Analysis"),Q(y.u,{content:"Types of files to analyse in bulk",position:N.Ly.TOP},Q(y.JO,{icon:"help",className:Y().Icon}))),Q(y.Ee,{inline:!0,name:"bulkAnalysisStatus",onChange:function(t){e.props.callbacks.HandleChangeInSettings(t.currentTarget.value,"bulkAnalysisStatus")},selectedValue:this.props.inferenceOptions.bulkAnalysisStatus},Q(y.Y8,{label:"Image Only",value:"image"}),Q(y.Y8,{label:"Video Only",value:"video"}),Q(y.Y8,{label:"Image and Video",value:"both"}))),Q("div",{className:Y().Section},Q(y.eQ,{className:Y().SubTitle},Q("div",null,"IoU Threshold"),Q(y.u,{content:Q("div",null,"Intersection Over Union index, used to describe extent of overlap",Q("br",null),"between 2 boxes. A higher value means stricter threshold.",Q("br",null),"Click to learn more"),position:N.Ly.TOP},Q(y.JO,{icon:"help",className:Y().Icon,onClick:function(){window.open("https://docs.datature.io/portal/running-inferences#intersection-over-union-iou-threshold")}}))),Q(y.iR,{className:Y().Slider,min:0,max:1,onChange:function(t){e.props.callbacks.HandleChangeInSettings(Math.round(10*t)/10,"iou")},stepSize:.1,labelStepSize:1,value:this.props.inferenceOptions.iou,vertical:!1})),Q(y.iz,{className:Y().Divider}),Q("div",null,"Video"),Q("div",{className:Y().Section},Q(y.eQ,{className:Y().SubTitle},Q("div",null,"Frame Interval"),Q(y.u,{content:Q("div",null,"Predictions generated per frame. The higher the number,"," ",Q("br",null),"the higher the prediction speed and the lower the quality.",Q("br",null),"Click to learn more"),position:N.Ly.TOP},Q(y.JO,{icon:"help",className:Y().Icon,onClick:function(){window.open("https://docs.datature.io/portal/running-inferences#frame-interval")}}))),Q(y.iR,{className:Y().Slider,min:1,max:20,onChange:function(t){e.props.callbacks.HandleChangeInSettings(t,"frameInterval")},stepSize:1,labelStepSize:19,value:this.props.inferenceOptions.video.frameInterval,vertical:!1}))," ")))}}]),n}(v().Component),ee=n(361),te=n.n(ee),ne=n(9134),ae=n.n(ne),oe=n(5636),ie=n.n(oe),se=v().createElement;function re(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function le(e){for(var t=1;t0&&a.setState((function(e){var t=le({},e.notFoundFolder);return t.splice(n,1),{notFoundFolder:t}}))}a.props.callbacks.UpdateImage()})).catch((function(e){a.state.notFoundFolder.indexOf(t)<0&&a.setState((function(e){var n=e.notFoundFolder;return n.push(t),{notFoundFolder:n}}));var n="Failed to update folder.",o=b.S.DANGER;e.response&&(3002===e.response.data.error_code&&(o=b.S.PRIMARY),n="".concat(e.response.data.message)),(0,I.JJ)(n,o,3e3)}));case 3:a.refreshTree(),a.setState({isAPICalled:!1});case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),(0,f.Z)((0,u.Z)(a),"handleDeleteFolder",function(){var e=(0,r.Z)(s().mark((function e(t){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,(0,w.Q3)(t).then((function(e){200===e.status&&a.refreshTree(),a.props.callbacks.UpdateImage()})).catch((function(e){var t="Failed to delete folder.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)}));case 2:a.setState({isAPICalled:!1});case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),(0,f.Z)((0,u.Z)(a),"handleNodeCollapse",(function(e,t){var n=a.state.parsedTree,o=te()(n);a.forNodeAtPath(o,t,(function(e){e.isExpanded=!1})),a.setState({parsedTree:o})})),(0,f.Z)((0,u.Z)(a),"handleNodeExpand",(function(e,t){var n=a.state.parsedTree,o=te()(n);a.forNodeAtPath(o,t,(function(e){e.isExpanded=!0})),a.setState({parsedTree:o})})),a.state={parsedTree:[],isAPICalled:!1,text:"",notFoundFolder:[]},a.handleKeyDown=a.handleKeyDown.bind((0,u.Z)(a)),a.handleElectronFileDialog=a.handleElectronFileDialog.bind((0,u.Z)(a)),a.handleDeleteFolder=a.handleDeleteFolder.bind((0,u.Z)(a)),a.handleNodeCollapse=a.handleNodeCollapse.bind((0,u.Z)(a)),a.handleNodeExpand=a.handleNodeExpand.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"componentDidMount",value:function(){(this.refreshTree(),ae()())&&window.require("electron").ipcRenderer.on("select-dirs-reply",this.handleElectronRegisterListener)}},{key:"componentWillUnmount",value:function(){ae()()&&window.require("electron").ipcRenderer.removeListener("select-dirs-reply",this.handleElectronRegisterListener)}},{key:"createFile",value:function(e,t,n){var a=decodeURIComponent(e);return a=a.includes("\\")?"".concat(a,"\\").concat(t):"".concat(a,"/").concat(t),{id:encodeURIComponent(a),icon:se(y.JO,{icon:"document",intent:n?b.S.WARNING:b.S.NONE,className:n?[ie().NotFound,ie().Icon].join(" "):ie().Icon}),label:t}}},{key:"createFolder",value:function(e,t,n,a,o,i){var s=this,r=[];return n.forEach((function(t){r.push(s.createFile(e,t,i))})),a.forEach((function(e){r.push(s.createFolder(e.path,e.name,e.images,e.folders,!1,i))})),{id:"".concat(e),icon:se(y.JO,{icon:"folder-close",className:i?[ie().NotFound,ie().Icon].join(" "):ie().Icon}),isExpanded:!1,label:t,childNodes:r,secondaryLabel:se(v().Fragment,null,o?se(y.eQ,null,se(y.u,{content:"Sync"},se(y.zx,{icon:se(y.JO,{icon:"repeat",iconSize:10}),minimal:!0,onClick:function(){s.handleUpdateFolder("".concat(e))}})),se(y.u,{content:"Remove Folder"},se(y.zx,{icon:"small-cross",minimal:!0,onClick:function(){s.handleDeleteFolder("".concat(e))}}))):null)}}},{key:"setTreeNodeInfo",value:function(e){var t=this;return e.map((function(e){var n=!1;return t.state.notFoundFolder.indexOf(e.path)>=0&&(n=!0),t.createFolder(e.path,e.name,e.images,e.folders,!0,n)}))}},{key:"forNodeAtPath",value:function(e,t,n){n(y.mp.nodeFromPath(t,e))}},{key:"render",value:function(){var e=this,t=se(y.zx,{text:"Browse",icon:"folder-new",intent:"success",loading:!1,onClick:function(){e.handleElectronFileDialog()}}),n=se(y.u,{content:se(v().Fragment,null,se("p",null,"Type the path of the folder and press Enter"),se("b",null,"Example"),se("p",null,se("pre",null,"/user/example/folder"))),position:N.Ly.TOP},se(y.JO,{icon:"help",className:ie().HintIcon}));return se(v().Fragment,null,se(y.Vq,(0,a.Z)({icon:"folder-open",title:"File Management",canEscapeKeyClose:this.props.allowUserClose,canOutsideClickClose:this.props.allowUserClose,className:[ie().Dialog,this.props.useDarkTheme?"bp3-dark":""].join(" ")},this.props),se("div",{className:K.TmF},se(y.cw,{label:"Add new folder",labelFor:"label-input"},se(y.BZ,{id:"label-input",placeholder:"Enter folder path...",rightElement:ae()()?t:n,onKeyDown:this.handleKeyDown,value:this.state.text,onChange:function(t){e.setState({text:t.target.value})}})),se(y.iz,{className:ie().Divider}),se("div",null,"Current Folders"),this.state.isAPICalled?se(y.$j,null):se(y.mp,{contents:this.state.parsedTree,onNodeCollapse:this.handleNodeCollapse,onNodeExpand:this.handleNodeExpand,className:(K.FZf,ie().Tree)}))))}}]),n}(v().Component),de=v().createElement;function pe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function he(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var fe,me=function(e){(0,d.Z)(n,e);var t=he(n);function n(e){var a;return(0,l.Z)(this,n),a=t.call(this,e),(0,f.Z)((0,u.Z)(a),"getImageElement",(function(){var e;return null!==(e=document.querySelector(".leaflet-pane.leaflet-overlay-pane img.leaflet-image-layer"))&&void 0!==e?e:document.querySelector(".leaflet-pane.leaflet-overlay-pane video.leaflet-image-layer")})),(0,f.Z)((0,u.Z)(a),"setFilter",(function(e){var t=window.getComputedStyle(a.getImageElement()).filter.split(" ");3===t.length?("brightness"===e.filterName?t[0]="brightness(".concat(e.value,"%)"):"contrast"===e.filterName?t[1]="contrast(".concat(e.value,"%)"):t[2]="saturate(".concat(e.value,"%)"),a.getImageElement().style.filter=t.join(" "),a.setState((function(t){var n=function(e){for(var t=1;t=e.length?{done:!0}:{done:!1,value:e[a++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,r=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return s=e.done,e},e:function(e){r=!0,i=e},f:function(){try{s||null==n.return||n.return()}finally{if(r)throw i}}}}function Ae(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=new Array(t);n=t.length-1)){var o=e?-1:1,i=Math.min(Math.max(0,n+o),t.length-1);a.selectAsset(t[i]),a.setSelectedAnnotation(null);var s=document.getElementById("image-bar");null!==s&&(s.scrollLeft+=120*o)}})),(0,f.Z)((0,u.Z)(a),"handleProgressToast",(function(){var e,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],n=a.toaster.show(a.renderProgress(0));t?a.progressToastInterval=window.setInterval((function(){(0,w.Ig)().then((function(t){var o=t.data,i=o.progress,s=o.total;if(a.isFirstCallPerformed)if(1===i&&1===s)a.toaster.show(a.renderProgress(100),n),window.clearInterval(a.progressToastInterval),a.isFirstCallPerformed=!1,a.toaster.clear();else{e.report(i);var r=Math.ceil(e.estimate());a.toaster.show(a.renderProgress(100*i/s,ge(r)),n)}else a.isFirstCallPerformed=!0,(e=A()({min:i,max:s,historyTimeConstant:10})).start()}))}),500):a.progressToastInterval=window.setInterval((function(){if(null===a.state.uiState||a.state.predictDone===a.state.predictTotal)a.toaster.show(a.renderProgress(100),n),window.clearInterval(a.progressToastInterval);else{var e=15*Math.random()/a.state.multiplier;a.state.predictDone+e<.98*a.state.predictTotal&&a.setState((function(t){return{predictDone:t.predictDone+e,multiplier:t.multiplier+.18}}));var t=a.state.predictDone/a.state.predictTotal*100;a.toaster.show(a.renderProgress(t),n)}}),200)})),(0,f.Z)((0,u.Z)(a),"syncAllFolders",(0,r.Z)(s().mark((function e(){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a.setState({isSyncing:!0}),e.next=3,(0,w.T)().then((function(){a.updateImage()})).catch((function(e){var t="Failed to sync all folders.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)}));case 3:a.setState({isSyncing:!1});case 4:case"end":return e.stop()}}),e)})))),a.state={currentAssetAnnotations:[],userEditState:"None",changesMade:!1,assetList:[],cacheList:[],tagInfo:{modelHash:void 0,tags:{}},fileManagementOpen:!1,advancedSettingsOpen:!1,imageListCollapsed:!1,annotatedAssetsHidden:!1,killVideoPrediction:!1,isSyncing:!1,hiddenAnnotations:new Set,uiState:null,predictTotal:0,predictDone:0,multiplier:1,confidence:.5,annotationOptions:{isOutlined:!0,opacity:.45},filterArr:[],alwaysShowLabel:!1,showSelected:!0,inferenceOptions:{bulkAnalysisStatus:"both",cacheResults:!1,iou:.8,video:{frameInterval:1}},currAnnotationPlaybackId:0},a.toaster=new y.x7({},{}),a.progressToastInterval=600,a.currentTag=0,a.project=a.props.project,a.menubarRef=v().createRef(),a.menubarElement=void 0,a.isFirstCallPerformed=!1,a.currentAsset={},a.selectedAnnotation=null,a.annotationGroup=new m.FeatureGroup,a.imagebarRef=v().createRef(),a.backgroundImg=null,a.selectAsset=a.selectAsset.bind((0,u.Z)(a)),a.showToaster=a.showToaster.bind((0,u.Z)(a)),a.renderProgress=a.renderProgress.bind((0,u.Z)(a)),a.singleAnalysis=a.singleAnalysis.bind((0,u.Z)(a)),a.getInference=a.getInference.bind((0,u.Z)(a)),a.bulkAnalysis=a.bulkAnalysis.bind((0,u.Z)(a)),a.updateAnnotations=a.updateAnnotations.bind((0,u.Z)(a)),a.resetControls=a.resetControls.bind((0,u.Z)(a)),a.refreshProject=a.refreshProject.bind((0,u.Z)(a)),a.setAnnotationTag=a.setAnnotationTag.bind((0,u.Z)(a)),a.switchAnnotation=a.switchAnnotation.bind((0,u.Z)(a)),a.handleFileManagementOpen=a.handleFileManagementOpen.bind((0,u.Z)(a)),a.handleFileManagementClose=a.handleFileManagementClose.bind((0,u.Z)(a)),a.handleAdvancedSettingsOpen=a.handleAdvancedSettingsOpen.bind((0,u.Z)(a)),a.handleAdvancedSettingsClose=a.handleAdvancedSettingsClose.bind((0,u.Z)(a)),a.handlePlayPauseVideoOverlay=a.handlePlayPauseVideoOverlay.bind((0,u.Z)(a)),a.updateImage=a.updateImage.bind((0,u.Z)(a)),a.setAnnotationVisibility=a.setAnnotationVisibility.bind((0,u.Z)(a)),a.setAllAnnotationVisibility=a.setAllAnnotationVisibility.bind((0,u.Z)(a)),a.filterAnnotationVisibility=a.filterAnnotationVisibility.bind((0,u.Z)(a)),a.setAnnotationOptions=a.setAnnotationOptions.bind((0,u.Z)(a)),a.toggleShowSelected=a.toggleShowSelected.bind((0,u.Z)(a)),a.setAnnotatedAssetsHidden=a.setAnnotatedAssetsHidden.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"componentDidMount",value:function(){var e=(0,r.Z)(s().mark((function e(){var t,n=this;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:this.menubarElement=document.getElementById("image-bar"),this.menubarElement.addEventListener("onwheel"in document?"wheel":"mousewheel",this.handleVerticalScrolling),this.map=m.map("annotation-map",{scrollWheelZoom:!0,zoomAnimation:!1,zoomDelta:0,zoomSnap:0,minZoom:-3,maxZoom:3,crs:m.CRS.Simple,attributionControl:!1,zoomControl:!1,doubleClickZoom:!1}).setView(Ze(5e3,5e3),0),this.annotationGroup.addTo(this.map),this.map.on("mouseup",(function(){if(n.videoOverlay){var e=n.videoOverlay.getElement();e!==document.activeElement&&(null===e||void 0===e||e.focus())}})),"",t=[Ze(3e4,0),Ze(0,23e3)],this.imageOverlay=m.imageOverlay("",t),this.videoOverlay=m.videoOverlay("",t,{interactive:!0}),new C(this.map,this),setTimeout((function(){return n.updateImage()}),200);case 11:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"componentDidUpdate",value:function(){var e=this;this.props.loadedModel&&this.props.loadedModel.hash!==this.state.tagInfo.modelHash&&((0,w.PF)(this.props.loadedModel.hash).then((function(t){var n,a={modelHash:null===(n=e.props.loadedModel)||void 0===n?void 0:n.hash,tags:t.data};e.setState({tagInfo:a,advancedSettingsOpen:!1}),Object.keys(e.state.tagInfo.tags).length>0&&(e.currentTag=0),e.annotationGroup.tags=e.state.tagInfo.tags})).catch((function(e){var t="Failed to obtain loaded model tags.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)})),this.updateImage()),this.props.loadedModel||void 0===this.state.tagInfo.modelHash||(this.setState({tagInfo:{modelHash:void 0,tags:{}}}),this.annotationGroup.tags=this.state.tagInfo.tags)}},{key:"componentWillUnmount",value:function(){void 0!==this.menubarElement&&this.menubarElement.removeEventListener("onwheel"in document?"wheel":"mousewheel",this.handleVerticalScrolling)}},{key:"handlePlayPauseVideoOverlay",value:function(){var e,t=null===(e=this.videoOverlay)||void 0===e?void 0:e.getElement();t&&t.onplaying&&(t.paused?t.play():t.pause())}},{key:"handleAdvancedSettingsClose",value:function(){this.setState({advancedSettingsOpen:!1})}},{key:"handleAdvancedSettingsOpen",value:function(){this.setState({advancedSettingsOpen:!0})}},{key:"handleFileManagementClose",value:function(){this.setState({fileManagementOpen:!1})}},{key:"handleFileManagementOpen",value:function(){this.setState({fileManagementOpen:!0})}},{key:"setUserState",value:function(e){this.state.userEditState!==e&&("None"!==e?(this.resetControls(),this.setState({userEditState:e})):this.setState({userEditState:e}))}},{key:"setAnnotationTag",value:function(e){return this.currentTag=e,this.currentTag}},{key:"setAnnotationOptions",value:function(e){var t=this;this.setState((function(t){var n=t.annotationOptions;switch(typeof e){case"boolean":n.isOutlined=!!e||!t.annotationOptions.isOutlined;break;case"number":n.opacity=e}return{annotationOptions:n}}),(function(){return t.filterAnnotationVisibility()}))}},{key:"setSelectedAnnotation",value:function(e){this.selectedAnnotation&&(this.selectedAnnotation.options.fillOpacity=.35,this.selectedAnnotation.fire("mouseout")),this.selectedAnnotation=e,this.selectedAnnotation&&(this.selectedAnnotation.options.fillOpacity=.7),null!==this.menubarRef.current&&this.menubarRef.current.setSelectedAnnotation(e)}},{key:"setAnnotationVisibility",value:function(e){for(var t=this,n=arguments.length,a=new Array(n>1?n-1:0),o=1;o0&&void 0!==o[0])||o[0],0===this.state.predictDone&&"Predicting"!==this.state.uiState){e.next=4;break}return(0,I.JJ)("Inference is already running",b.S.WARNING,3e3),e.abrupt("return");case 4:if(!(0,O.isEmpty)(this.currentAsset)||this.props.loadedModel){e.next=7;break}return(0,I.JJ)("There is no model and image loaded",b.S.WARNING,3e3),e.abrupt("return");case 7:if(!(0,O.isEmpty)(this.currentAsset)){e.next=10;break}return(0,I.JJ)("There is no image loaded",b.S.WARNING,3e3),e.abrupt("return");case 10:if(this.props.loadedModel){e.next=13;break}return(0,I.JJ)("There is no model loaded",b.S.WARNING,3e3),e.abrupt("return");case 13:return this.setState({predictTotal:100,predictDone:.01,multiplier:1,uiState:"Predicting"}),n&&"video"===this.currentAsset.type?(this.handleProgressToast(!0),null===(a=this.videoOverlay.getElement())||void 0===a||a.pause()):n&&this.handleProgressToast(),e.next=17,this.getInference(this.currentAsset,n);case 17:return e.next=19,this.updateImage();case 19:"video"===this.currentAsset.type&&(null===(t=this.videoOverlay.getElement())||void 0===t||t.play()),this.setState({predictDone:0,uiState:null,killVideoPrediction:!1});case 21:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"getInference",value:function(){var e=(0,r.Z)(s().mark((function e(t){var n,a,o,i=this,r=arguments;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=!(r.length>1&&void 0!==r[1])||r[1],a=!(r.length>2&&void 0!==r[2])||r[2],this.props.loadedModel){e.next=4;break}return e.abrupt("return");case 4:if(o=this.props.loadedModel.hash,this.setState({hiddenAnnotations:new Set}),"image"!==t.type||"video"===this.state.inferenceOptions.bulkAnalysisStatus&&!a){e.next=9;break}return e.next=9,(0,w.hu)(o,t.localPath,n,this.state.inferenceOptions.iou,"json").then((function(e){i.currentAsset.url===t.url&&a&&i.updateAnnotations(e.data)})).catch((function(e){var t="Failed to predict image.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)}));case 9:if("video"!==t.type||"image"===this.state.inferenceOptions.bulkAnalysisStatus&&!a){e.next=12;break}return e.next=12,(0,w.ym)(o,t.localPath,n,this.state.inferenceOptions.video.frameInterval,this.state.inferenceOptions.iou).then((function(e){if(i.currentAsset.url===t.url&&a){var n=i.videoOverlay.getElement();"requestVideoFrameCallback"in HTMLVideoElement.prototype&&n.requestVideoFrameCallback((function t(a,o){var s=i.state.inferenceOptions.video.frameInterval/e.data.fps,r=Math.floor(o.mediaTime/s),l=Math.floor(r*s*1e3).toString();e.data.frames[l]&&i.updateAnnotations(e.data.frames[l]);var c=n.requestVideoFrameCallback(t);i.setState({currAnnotationPlaybackId:c})}))}})).catch((function(e){var t="Failed to predict video.",n=b.S.DANGER;e.response&&(t="".concat(e.response.data.message)),"STOPPEDPROCESS"===e.response.data.error&&(n=b.S.PRIMARY),(0,I.JJ)(t,n,3e3)}));case 12:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"showToaster",value:function(e){this.toaster.show(e)}},{key:"filterAnnotationVisibility",value:function(){var e=this;this.annotationGroup.clearLayers();var t=(0,O.invert)(this.state.tagInfo.tags);this.state.currentAssetAnnotations.filter((function(n){return!e.state.hiddenAnnotations.has(n.options.annotationID)&&(0===e.state.filterArr.length||e.state.showSelected===e.state.filterArr.some((function(e){return t[n.options.annotationTag].toLowerCase().includes(e.toLowerCase())})))&&n.options.confidence>=e.state.confidence})).forEach((function(t){var n=(0,O.cloneDeep)(t);n.options.fillOpacity=e.state.annotationOptions.opacity,n.options.weight=e.state.annotationOptions.isOutlined?t.options.weight:0,e.annotationGroup.addLayer(n)}));var n=(0,O.invert)(this.state.tagInfo.tags);this.annotationGroup.eachLayer((function(t){t.unbindTooltip(),t.bindTooltip("\n ").concat(n[t.options.annotationTag],"\n "),{interactive:!e.state.alwaysShowLabel,permanent:e.state.alwaysShowLabel,opacity:.9,direction:"center"})}))}},{key:"isAssetVisible",value:function(){return!this.state.annotatedAssetsHidden}},{key:"selectAsset",value:function(e){var t=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=!(e.assetUrl!==this.currentAsset.assetUrl);console.log("asset",e.url),console.log("currentasset",this.currentAsset.url),console.log("single analysis",n);var o=this.videoOverlay.getElement();a||(this.setState({currentAssetAnnotations:[]}),this.annotationGroup.eachLayer((function(e){t.annotationGroup.removeLayer(e)})),this.updateMenuBarAnnotations(),o&&o.cancelVideoFrameCallback(this.state.currAnnotationPlaybackId));var i=0===Object.keys(this.currentAsset).length;if(this.imagebarRef.highlightAsset(e.assetUrl),this.annotationGroup.clearLayers(),this.annotationGroup.tags=this.state.tagInfo.tags,"image"===e.type){this.map.hasLayer(this.imageOverlay)||(this.videoOverlay.remove(),this.imageOverlay.addTo(this.map));var s=new Image;this.imageOverlay.setUrl(e.assetUrl),s.src=e.assetUrl,s.onload=function(){t.imageOverlay.setBounds(new m.LatLngBounds([[0,0],[s.height,s.width]])),t.currentAsset=be(be({},e),{},{metadata:{width:s.width,height:s.height}}),a||(t.map.setMinZoom(-5),t.map.invalidateSize(),setTimeout((function(){t.map.fitBounds(t.imageOverlay.getBounds(),{padding:new m.Point(20,20)})}),150),t.map.setMinZoom(-3),e.isCached&&n&&t.singleAnalysis(!1)),i&&t.setState({})},this.backgroundImg=document.querySelector(".leaflet-pane.leaflet-overlay-pane img.leaflet-image-layer")}if("video"===e.type){this.map.hasLayer(this.videoOverlay)||(this.imageOverlay.remove(),this.videoOverlay.addTo(this.map));var r=document.createElement("video");r.setAttribute("src",e.assetUrl),this.videoOverlay.setUrl(e.assetUrl),r.onloadedmetadata=function(){t.videoOverlay.setBounds(new m.LatLngBounds([[0,0],[r.videoHeight,r.videoWidth]])),t.currentAsset=be(be({},e),{},{metadata:{width:r.videoWidth,height:r.videoHeight}});var o=t.videoOverlay.getElement();o&&(o.controls=!0,o.setAttribute("controlsList","nofullscreen nodownload")),a?null===o||void 0===o||o.focus():(t.map.setMinZoom(-5),t.map.invalidateSize(),setTimeout((function(){t.map.fitBounds(t.videoOverlay.getBounds(),{padding:new m.Point(20,20)}),t.map.setMinZoom(-3),null===o||void 0===o||o.focus()}),150),e.isCached&&n&&t.singleAnalysis(!1)),i&&t.setState({})},this.backgroundImg=document.querySelector(".leaflet-pane.leaflet-overlay-pane video.leaflet-image-layer")}}},{key:"updateMenuBarAnnotations",value:function(){null!==this.menubarRef.current&&this.menubarRef.current.setAnnotations(this.annotationGroup)}},{key:"selectAnnotationTagByHash",value:function(e){var t=Object.values(this.state.tagInfo.tags).indexOf(e);-1!==t&&(this.currentTag=t,null!==this.menubarRef.current&&this.menubarRef.current.setAnnotationTag(t))}},{key:"refreshProject",value:function(){var e=(0,r.Z)(s().mark((function e(){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:this.selectAsset(this.currentAsset);case 1:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"addNewTag",value:function(e,t){this.setState((function(n){var a=be({},n.tagInfo.tags);return a[e]=t,{tagInfo:{modelHash:n.tagInfo.modelHash,tags:a}}}))}},{key:"resetControls",value:function(){this.setUserState("None"),this.setSelectedAnnotation(null)}},{key:"renderProgress",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",a={className:"bp3-text-muted ".concat(this.props.useDarkTheme?"bp3-dark":""),icon:"predictive-analysis",message:ve(y.ko,{className:"predict-prog",intent:e<100?"primary":"success",value:e/100}),onDismiss:function(e){e||(t.killVideoPrediction(),window.clearInterval(t.progressToastInterval)),t.isFirstCallPerformed=!1},timeout:e<100?0:600};return""!==n&&(a.action={text:n}),a}},{key:"renderHotkeys",value:function(){var e=this;return ve(y.SV,null,ve(y.qm,{global:!0,combo:"o",label:"Open Folder",onKeyDown:this.handleFileManagementOpen}),ve(y.qm,{global:!0,combo:"s",label:"Sync All Folders",onKeyDown:this.syncAllFolders}),ve(y.qm,{global:!0,combo:"A",label:"Analyze",onKeyDown:function(){return e.singleAnalysis()}}),ve(y.qm,{global:!0,combo:"b",label:"Bulk Analysis",onKeyDown:this.bulkAnalysis}),ve(y.qm,{global:!0,combo:"esc",label:"Exit Current Mode",onKeyDown:this.resetControls}),ve(y.qm,{global:!0,combo:"h",label:"Show / Hide Annotations",onKeyDown:function(){e.map.hasLayer(e.annotationGroup)?e.map.removeLayer(e.annotationGroup):e.map.addLayer(e.annotationGroup)}}),ve(y.qm,{global:!0,combo:"l",label:"Show / Hide Label",onKeyDown:function(){e.setState((function(e){return{alwaysShowLabel:!e.alwaysShowLabel}}),(function(){e.filterAnnotationVisibility()}))}}),ve(y.qm,{global:!0,combo:"left",label:"Load previous asset",onKeyDown:function(){return e.switchAnnotation(!0)}}),ve(y.qm,{global:!0,combo:"right",label:"Load previous asset",onKeyDown:function(){return e.switchAnnotation(!1)}}),ve(y.qm,{global:!0,combo:"space",label:"Play/Pause Video",onKeyDown:this.handlePlayPauseVideoOverlay}),Object.entries(this.state.tagInfo.tags).map((function(t,n){var a=(0,o.Z)(t,1)[0];if(!(n>9))return ve(y.qm,{key:a,global:!0,combo:"".concat(n+1),label:"Shortcut : ".concat(a),onKeyDown:function(){e.currentTag=n,null!=e.menubarRef.current&&e.menubarRef.current.setAnnotationTag(n)}})})))}},{key:"render",value:function(){var e=this,t=this.props.useDarkTheme?"":"light-",n=this.state.imageListCollapsed?"collapsed-":"",o=this.state.assetList.filter((function(){return e.isAssetVisible()}));return ve("div",null,ve(y.x7,(0,a.Z)({},this.state,{ref:this.refHandlers.toaster})),ve("div",{className:"workspace"},ve("div",{className:[n,"image-list"].join(""),id:"image-list"},ve(y.zx,{className:[t,"collapse-button"].join(""),large:!0,icon:this.state.imageListCollapsed?"caret-up":"caret-down",onClick:function(){e.setState((function(e){return{imageListCollapsed:!e.imageListCollapsed}}))}}),ve("div",{className:[t,"collapse-button-effect"].join("")}),ve(y.Zb,{className:[n,"image-bar"].join(""),id:"image-bar"},ve(B,(0,a.Z)({ref:function(t){e.imagebarRef=t},assetList:o,callbacks:{selectAssetCallback:this.selectAsset}},this.props)))),ve("div",{className:this.state.imageListCollapsed?"expanded-annotator-space":"annotator-space"},0===Object.keys(this.currentAsset).length?ve(y.Zb,{className:"annotator-non-ideal"},ve("div",{className:"bp3-non-ideal-state"},ve("div",{className:"bp3-non-ideal-state-visual"},ve("span",null,ve(y.JO,{icon:"media",iconSize:60}))),ve("h4",{className:"bp3-heading bp3-text-muted"},"Select an Image to Annotate"))):null,ve(y.Zb,{className:"main-annotator"},ve("div",{id:"annotation-map",className:"style-annotator"}),this.backgroundImg?ve("div",{className:"annotator-settings-button"},ve(me,{annotationOptions:this.state.annotationOptions,callbacks:{setAnnotatedAssetsHidden:this.setAnnotatedAssetsHidden,setAnnotationOptions:this.setAnnotationOptions}})):null)),ve("div",{className:"annotator-controls"},ve(V,{ref:this.menubarRef,isSyncing:this.state.isSyncing,projectTags:this.state.tagInfo.tags,userEditState:this.state.userEditState,changesMade:this.state.changesMade,uiState:this.state.uiState,predictDone:this.state.predictDone,predictTotal:this.state.predictTotal,hiddenAnnotations:this.state.hiddenAnnotations,confidence:this.state.confidence,filterArr:this.state.filterArr,showSelected:this.state.showSelected,useDarkTheme:this.props.useDarkTheme,isConnected:this.props.isConnected,loadedModel:this.props.loadedModel,currentAsset:this.currentAsset,assetList:this.state.assetList,callbacks:{ResetControls:this.resetControls,OpenFileManagement:this.handleFileManagementOpen,SetAnnotationTag:this.setAnnotationTag,OpenAdvancedSettings:this.handleAdvancedSettingsOpen,SetAnnotationVisibility:this.setAnnotationVisibility,SingleAnalysis:this.singleAnalysis,BulkAnalysis:this.bulkAnalysis,ToggleConfidence:this.toggleConfidence,SetFilterArr:this.setFilterArr,ToggleShowSelected:this.toggleShowSelected,SyncAllFolders:this.syncAllFolders}}),this.state.fileManagementOpen?ve(ue,(0,a.Z)({onClose:this.handleFileManagementClose,isOpen:!0,allowUserClose:!0,callbacks:{RefreshProject:this.refreshProject,UpdateImage:this.updateImage}},this.props)):null,this.state.advancedSettingsOpen?ve(X,(0,a.Z)({inferenceOptions:this.state.inferenceOptions,onClose:this.state.advancedSettingsOpen?this.handleAdvancedSettingsClose:this.handleAdvancedSettingsOpen,isOpen:!0,allowUserClose:!0,callbacks:{HandleChangeInSettings:this.handleChangeInAdvancedSettings}},this.props)):null)))}}]),n}(g.Component))||fe},5636:function(e){e.exports={Dialog:"filemodal_Dialog__2rWYe",Divider:"filemodal_Divider__jky9p",Tree:"filemodal_Tree__209ZG",NotFound:"filemodal_NotFound__28dHw",Icon:"filemodal_Icon__2nHDp",HintIcon:"filemodal_HintIcon__38we2"}},7019:function(e){e.exports={Card:"imagebar_Card__3TthZ",StackTop:"imagebar_StackTop__3s46r",Tag:"imagebar_Tag__hH6pd"}},9984:function(e){e.exports={SpacedIcon:"menu_SpacedIcon__2TTAc",SelectionList:"menu_SelectionList__1AqpU",Spin:"menu_Spin__t3d2N",Slider:"menu_Slider__3eu1p",Icon:"menu_Icon__2akHD",InferenceMenuItem:"menu_InferenceMenuItem__1hZUs",TagList:"menu_TagList__3yjBd"}},1164:function(e){e.exports={Dialog:"settingsmodal_Dialog__2B1jD",Divider:"settingsmodal_Divider__2LpZ6",Section:"settingsmodal_Section__27Rr4",Icon:"settingsmodal_Icon__1i0mE",Slider:"settingsmodal_Slider__3nRpn",SubTitle:"settingsmodal_SubTitle__2Ifm8"}}}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[607],{4607:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return we}});var a=n(5579),o=n(4121),i=n(809),s=n.n(i),r=n(2447),l=n(4047),c=n(2700),u=n(4706),d=n(8127),p=n(4102),h=n(775),f=n(6265),m=n(5243),g=(n(1787),n(7294)),v=n.n(g),y=n(2689),b=n(2609),S=n(9481),A=n.n(S),k=n(8770),Z=function(e,t){return function(e){return k._[e%k._.length]}(t)};var w=n(7316),O=n(6486),I=n(9231),T=function(){function e(t,n){return(0,l.Z)(this,e),(0,f.Z)(this,"_map",void 0),(0,f.Z)(this,"_annotator",void 0),null===e.instance&&(this._map=t,this._annotator=n,e.instance=this),e.instance}return(0,c.Z)(e,null,[{key:"map",get:function(){var t;void 0===e.instance._map&&(e.instance._map=null===(t=e.instance._annotator)||void 0===t?void 0:t.map);return e.instance._map}},{key:"annotator",get:function(){return e.instance._annotator}}]),e}();(0,f.Z)(T,"instance",null);var C=T,D=n(9999),N=n(3766),x=n(9984),R=n.n(x),P=v().createElement;function F(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var E=function(e){(0,d.Z)(n,e);var t=F(n);function n(e){return(0,l.Z)(this,n),t.call(this,e)}return(0,c.Z)(n,[{key:"render",value:function(){var e=P(y.zx,{icon:this.props.showSelected?"eye-open":"eye-off",onClick:this.props.callbacks.ToggleShowSelected});return P(v().Fragment,null,P(y.EG,{className:this.props.useDarkTheme?"bp3-dark":"",rightElement:e,values:this.props.filterArr,placeholder:"Enter filters here...",onChange:this.props.callbacks.SetFilterArr}))}}]),n}(v().Component),_=v().createElement;function L(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var j={fill:!0,minimal:!0,round:!1,interactive:!0,className:"annotator-tags"};function M(e,t){var n={backgroundColor:k._[t%k._.length],fontSize:"12px",display:"inline-block",borderRadius:"3px",textAlign:"center",padding:"2px",width:"15px",height:"8px"};return _("div",{style:n})}var V=function(e){(0,d.Z)(n,e);var t=L(n);function n(e){var a;return(0,l.Z)(this,n),(a=t.call(this,e)).state={selectedTag:0,selectedAnnotationID:"",annotations:[]},a.tagIDtoDisplayIndex={},a.tagNames={},a.annotationRefs={},a.tagCount={},a.hiddenTagCount={},a.setAnnotationTag=a.setAnnotationTag.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"setAnnotations",value:function(e){var t=this,n=Object.values(e._layers);n.sort((function(e,n){var a=t.tagIDtoDisplayIndex[e.options.annotationTag]-t.tagIDtoDisplayIndex[n.options.annotationTag];return 0!==a?a:e.options.annotationIDn.options.annotationID?1:0})),this.annotationRefs={},this.tagCount={},n.forEach((function(e){t.annotationRefs[e.options.annotationID]=v().createRef(),t.tagCount[e.options.annotationTag]=(t.tagCount[e.options.annotationTag]||0)+1}));var a=n.reduce((function(e,t,a){return 0===a||t.options.annotationTag!==n[a-1].options.annotationTag?e.push([t,1]):e.push([t,e[a-1][1]+1]),e}),[]);this.setState({annotations:a})}},{key:"setAnnotationTag",value:function(e){this.setState({selectedTag:e}),this.props.callbacks.SetAnnotationTag(e)}},{key:"setSelectedAnnotation",value:function(e){null!==e?(this.setState({selectedAnnotationID:e.options.annotationID}),this.annotationRefs[e.options.annotationID].current.scrollIntoView({block:"nearest"})):this.setState({selectedAnnotationID:""})}},{key:"generateTagHideIcon",value:function(e){var t=this,n=!(e in this.tagCount)||this.hiddenTagCount[e]!==this.tagCount[e];return _(y.JO,{icon:n?"eye-open":"eye-off",className:R().SpacedIcon,onClick:function(a){var o;a.stopPropagation(),(o=t.props.callbacks).SetAnnotationVisibility.apply(o,[!n].concat((0,D.Z)(t.state.annotations.map((function(e){return e[0]})).filter((function(t){return t.options.annotationTag===e})))))}})}},{key:"generateAnnotationHideIcon",value:function(e){var t=this,n=!this.props.hiddenAnnotations.has(e.options.annotationID);return _(y.JO,{icon:n?"eye-open":"eye-off",onClick:function(a){a.stopPropagation(),t.props.callbacks.SetAnnotationVisibility(!n,e)}})}},{key:"updateHiddenTagCount",value:function(){var e=this;this.hiddenTagCount={},this.state.annotations.forEach((function(t){if(e.props.hiddenAnnotations.has(t[0].options.annotationID)){var n=t[0].options.annotationTag;e.hiddenTagCount[n]=(e.hiddenTagCount[n]||0)+1}}))}},{key:"render",value:function(){var e=this;this.updateHiddenTagCount();var t=_("div",{className:["tag-list",R().TagList].join(" ")},Object.entries(this.props.projectTags).filter((function(t){var n=(0,o.Z)(t,2),a=n[0];n[1];return 0===e.props.filterArr.length||e.props.filterArr.some((function(e){return a.toLowerCase()===e.toLowerCase()}))===e.props.showSelected})).map((function(t,n){var i=(0,o.Z)(t,2),s=i[0],r=i[1];return e.tagIDtoDisplayIndex[r]=n,e.tagNames[r]=s,_(y.Vp,(0,a.Z)({className:R().MenuTag,key:r},j,{active:n===e.state.selectedTag,rightIcon:_("div",null,e.generateTagHideIcon(r),M(0,r)),onClick:function(){e.setAnnotationTag(n)}}),s)}))),n=_("div",{className:["tag-list",R().TagList].join(" ")},this.state.annotations.filter((function(t){var n=(0,o.Z)(t,2),a=n[0];n[1];return a.options.confidence>e.props.confidence&&(0===e.props.filterArr.length||e.props.showSelected===e.props.filterArr.some((function(t){return e.tagNames[a.options.annotationTag].toLowerCase().includes(t.toLowerCase())})))})).map((function(t){var n=(0,o.Z)(t,2),i=n[0],l=n[1];return _(y.Vp,(0,a.Z)({className:R().MenuTag,key:i.options.annotationID.split("-")[0],elementRef:e.annotationRefs[i.options.annotationID]},j,{active:i.options.annotationID===e.state.selectedAnnotationID,rightIcon:_("div",null,e.generateAnnotationHideIcon(i)),onClick:(0,r.Z)(s().mark((function t(){return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.props.callbacks.SetAnnotationVisibility(!0,i);case 2:i.fire("click");case 3:case"end":return t.stop()}}),t)})))}),_(y.JO,{icon:"rectangle"===i.options.annotationType?"widget":"polygon-filter",iconSize:12,style:{color:k._[i.options.annotationTag%k._.length],marginRight:"5px",marginBottom:"2px"}}),"".concat(e.tagNames[i.options.annotationTag]," ").concat(l))})));return _(v().Fragment,null,_(y.v2,{className:"main-menu bp3-elevation-1"},_(y.sN,{icon:"graph",text:"Annotator Controls"}),_(y.R,{title:"Assets Folder"}),this.props.isSyncing?_(y.$j,{size:30,className:R().Spin}):_(v().Fragment,null,_(y.sN,{icon:"folder-new",text:"Open Folder",label:_(y.M2,{combo:"O"}),onClick:this.props.callbacks.OpenFileManagement}),_(y.sN,{icon:"repeat",text:"Sync All Folders",label:_(y.M2,{combo:"S"}),onClick:this.props.callbacks.SyncAllFolders})),_(y.R,{title:"Inference"}),0===this.props.predictDone?_(y.u,{content:"Load Model and Image before analysing",position:N.Ly.TOP,disabled:this.props.isConnected&&this.props.loadedModel&&!(0,O.isEmpty)(this.props.assetList)},_("div",{className:R().InferenceMenuItem},_(y.sN,{disabled:!this.props.isConnected||!this.props.loadedModel||(0,O.isEmpty)(this.props.currentAsset),icon:"ring",text:"Analyze",label:_(y.M2,{combo:"A"}),className:"Re-Analyse"===this.props.userEditState?"bp3-active":"",onClick:function(){return e.props.callbacks.SingleAnalysis()}}),_(y.sN,{disabled:!this.props.isConnected||!this.props.loadedModel||(0,O.isEmpty)(this.props.assetList),icon:"heat-grid",text:"Bulk Analysis",label:_(y.M2,{combo:"B"}),className:"Bulk Analysis"===this.props.userEditState?"bp3-active":"",onClick:this.props.callbacks.BulkAnalysis}))):_(y.$j,{size:30,className:R().Spin}),_(y.R,{title:"Confidence Threshold"}),_(y.iR,{className:R().Slider,min:0,max:100,onChange:this.props.callbacks.ToggleConfidence,stepSize:1,labelStepSize:100,value:100*this.props.confidence,vertical:!1}),_(y.R,null),_(y.sN,{icon:"new-text-box",text:"Advanced Settings",onClick:this.props.callbacks.OpenAdvancedSettings}),_(y.R,{title:"Filter Tags"}),_(E,(0,a.Z)({showSelected:this.state.showSelected,filterArr:this.state.filterArr,callbacks:{SetFilterArr:this.setFilterArr,ToggleShowSelected:this.toggleShowSelected}},this.props)),_(y.R,null),_(y.mQ,{className:R().SelectionList},_(y.OK,{id:"annotation-objects",title:"Objects",panel:n}),_(y.OK,{id:"project-tags",title:"Tag Map",panel:t}))))}}]),n}(g.Component),U=n(5767),J=n.n(U),G=n(7019),H=n.n(G),z=v().createElement;function q(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var B=function(e){(0,d.Z)(n,e);var t=q(n);function n(e){var a;return(0,l.Z)(this,n),a=t.call(this,e),(0,f.Z)((0,u.Z)(a),"currentAssetID",void 0),a.currentAssetID="",a.highlightAsset=a.highlightAsset.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"highlightAsset",value:function(e){this.currentAssetID=e,this.forceUpdate()}},{key:"render",value:function(){var e=this;return z(v().Fragment,null,this.props.assetList.map((function(t){return n=t,a=t.assetUrl,o=e.props.useDarkTheme,i=e.props.callbacks.selectAssetCallback,s=e.currentAssetID,z(y.Zb,{className:["image-bar-thumbnail-card",H().Card].join(" "),key:a,onClick:function(){return i(n)}},z("div",{className:n.assetUrl===s?"image-bar-thumbnail image-bar-thumbnail-highlighted":"image-bar-thumbnail"},"video"===n.type?z(v().Fragment,null," ",z(y.JO,{className:H().StackTop,icon:"video",iconSize:y.Jh.STANDARD}),z("div",null,z(J(),{width:150,length:150,snapshotAtTime:1,videoUrl:n.thumbnailUrl}))):z("img",{src:n.thumbnailUrl,alt:n.filename}),z(y.Vp,{className:["image-bar-filename-tag",H().Tag].join(" "),fill:!0,style:{backgroundColor:o?"":"#CED9E0"},rightIcon:!!n.isCached&&z(y.u,{content:"Inference is Cached by Model",position:N.Ly.TOP},z(y.JO,{icon:"bookmark",color:o?"#0F9960":"#3DCC91"}))},z("span",{className:"bp3-ui-text bp3-monospace-text image-bar-filename-text"},n.filename))));var n,a,o,i,s})))}}]),n}(g.Component),K=n(451),W=n(1164),Y=n.n(W),Q=v().createElement;function $(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var X=function(e){(0,d.Z)(n,e);var t=$(n);function n(e){return(0,l.Z)(this,n),t.call(this,e)}return(0,c.Z)(n,[{key:"render",value:function(){var e=this;return Q(y.Vq,(0,a.Z)({icon:"cog",title:"Advanced Settings",canEscapeKeyClose:this.props.allowUserClose,canOutsideClickClose:this.props.allowUserClose,className:this.props.useDarkTheme?"bp3-dark":""},this.props),Q("div",{className:Y().Dialog},Q("div",{className:K.TmF},Q("div",null,"General"),Q("div",{className:Y().Section},Q(y.eQ,{className:Y().SubTitle},Q("div",null,"Bulk Analysis"),Q(y.u,{content:"Types of files to analyse in bulk",position:N.Ly.TOP},Q(y.JO,{icon:"help",className:Y().Icon}))),Q(y.Ee,{inline:!0,name:"bulkAnalysisStatus",onChange:function(t){e.props.callbacks.HandleChangeInSettings(t.currentTarget.value,"bulkAnalysisStatus")},selectedValue:this.props.inferenceOptions.bulkAnalysisStatus},Q(y.Y8,{label:"Image Only",value:"image"}),Q(y.Y8,{label:"Video Only",value:"video"}),Q(y.Y8,{label:"Image and Video",value:"both"}))),Q("div",{className:Y().Section},Q(y.eQ,{className:Y().SubTitle},Q("div",null,"IoU Threshold"),Q(y.u,{content:Q("div",null,"Intersection Over Union index, used to describe extent of overlap",Q("br",null),"between 2 boxes. A higher value means stricter threshold.",Q("br",null),"Click to learn more"),position:N.Ly.TOP},Q(y.JO,{icon:"help",className:Y().Icon,onClick:function(){window.open("https://docs.datature.io/portal/running-inferences#intersection-over-union-iou-threshold")}}))),Q(y.iR,{className:Y().Slider,min:0,max:1,onChange:function(t){e.props.callbacks.HandleChangeInSettings(Math.round(10*t)/10,"iou")},stepSize:.1,labelStepSize:1,value:this.props.inferenceOptions.iou,vertical:!1})),Q(y.iz,{className:Y().Divider}),Q("div",null,"Video"),Q("div",{className:Y().Section},Q(y.eQ,{className:Y().SubTitle},Q("div",null,"Frame Interval"),Q(y.u,{content:Q("div",null,"Predictions generated per frame. The higher the number,"," ",Q("br",null),"the higher the prediction speed and the lower the quality.",Q("br",null),"Click to learn more"),position:N.Ly.TOP},Q(y.JO,{icon:"help",className:Y().Icon,onClick:function(){window.open("https://docs.datature.io/portal/running-inferences#frame-interval")}}))),Q(y.iR,{className:Y().Slider,min:1,max:20,onChange:function(t){e.props.callbacks.HandleChangeInSettings(t,"frameInterval")},stepSize:1,labelStepSize:19,value:this.props.inferenceOptions.video.frameInterval,vertical:!1}))," ")))}}]),n}(v().Component),ee=n(361),te=n.n(ee),ne=n(9134),ae=n.n(ne),oe=n(5636),ie=n.n(oe),se=v().createElement;function re(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function le(e){for(var t=1;t0&&a.setState((function(e){var t=le({},e.notFoundFolder);return t.splice(n,1),{notFoundFolder:t}}))}a.props.callbacks.UpdateImage()})).catch((function(e){a.state.notFoundFolder.indexOf(t)<0&&a.setState((function(e){var n=e.notFoundFolder;return n.push(t),{notFoundFolder:n}}));var n="Failed to update folder.",o=b.S.DANGER;e.response&&(3002===e.response.data.error_code&&(o=b.S.PRIMARY),n="".concat(e.response.data.message)),(0,I.JJ)(n,o,3e3)}));case 3:a.refreshTree(),a.setState({isAPICalled:!1});case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),(0,f.Z)((0,u.Z)(a),"handleDeleteFolder",function(){var e=(0,r.Z)(s().mark((function e(t){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,(0,w.Q3)(t).then((function(e){200===e.status&&a.refreshTree(),a.props.callbacks.UpdateImage()})).catch((function(e){var t="Failed to delete folder.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)}));case 2:a.setState({isAPICalled:!1});case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),(0,f.Z)((0,u.Z)(a),"handleNodeCollapse",(function(e,t){var n=a.state.parsedTree,o=te()(n);a.forNodeAtPath(o,t,(function(e){e.isExpanded=!1})),a.setState({parsedTree:o})})),(0,f.Z)((0,u.Z)(a),"handleNodeExpand",(function(e,t){var n=a.state.parsedTree,o=te()(n);a.forNodeAtPath(o,t,(function(e){e.isExpanded=!0})),a.setState({parsedTree:o})})),a.state={parsedTree:[],isAPICalled:!1,text:"",notFoundFolder:[]},a.handleKeyDown=a.handleKeyDown.bind((0,u.Z)(a)),a.handleElectronFileDialog=a.handleElectronFileDialog.bind((0,u.Z)(a)),a.handleDeleteFolder=a.handleDeleteFolder.bind((0,u.Z)(a)),a.handleNodeCollapse=a.handleNodeCollapse.bind((0,u.Z)(a)),a.handleNodeExpand=a.handleNodeExpand.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"componentDidMount",value:function(){(this.refreshTree(),ae()())&&window.require("electron").ipcRenderer.on("select-dirs-reply",this.handleElectronRegisterListener)}},{key:"componentWillUnmount",value:function(){ae()()&&window.require("electron").ipcRenderer.removeListener("select-dirs-reply",this.handleElectronRegisterListener)}},{key:"createFile",value:function(e,t,n){var a=decodeURIComponent(e);return a=a.includes("\\")?"".concat(a,"\\").concat(t):"".concat(a,"/").concat(t),{id:encodeURIComponent(a),icon:se(y.JO,{icon:"document",intent:n?b.S.WARNING:b.S.NONE,className:n?[ie().NotFound,ie().Icon].join(" "):ie().Icon}),label:t}}},{key:"createFolder",value:function(e,t,n,a,o,i){var s=this,r=[];return n.forEach((function(t){r.push(s.createFile(e,t,i))})),a.forEach((function(e){r.push(s.createFolder(e.path,e.name,e.images,e.folders,!1,i))})),{id:"".concat(e),icon:se(y.JO,{icon:"folder-close",className:i?[ie().NotFound,ie().Icon].join(" "):ie().Icon}),isExpanded:!1,label:t,childNodes:r,secondaryLabel:se(v().Fragment,null,o?se(y.eQ,null,se(y.u,{content:"Sync"},se(y.zx,{icon:se(y.JO,{icon:"repeat",iconSize:10}),minimal:!0,onClick:function(){s.handleUpdateFolder("".concat(e))}})),se(y.u,{content:"Remove Folder"},se(y.zx,{icon:"small-cross",minimal:!0,onClick:function(){s.handleDeleteFolder("".concat(e))}}))):null)}}},{key:"setTreeNodeInfo",value:function(e){var t=this;return e.map((function(e){var n=!1;return t.state.notFoundFolder.indexOf(e.path)>=0&&(n=!0),t.createFolder(e.path,e.name,e.images,e.folders,!0,n)}))}},{key:"forNodeAtPath",value:function(e,t,n){n(y.mp.nodeFromPath(t,e))}},{key:"render",value:function(){var e=this,t=se(y.zx,{text:"Browse",icon:"folder-new",intent:"success",loading:!1,onClick:function(){e.handleElectronFileDialog()}}),n=se(y.u,{content:se(v().Fragment,null,se("p",null,"Type the path of the folder and press Enter"),se("b",null,"Example"),se("p",null,se("pre",null,"/user/example/folder"))),position:N.Ly.TOP},se(y.JO,{icon:"help",className:ie().HintIcon}));return se(v().Fragment,null,se(y.Vq,(0,a.Z)({icon:"folder-open",title:"File Management",canEscapeKeyClose:this.props.allowUserClose,canOutsideClickClose:this.props.allowUserClose,className:[ie().Dialog,this.props.useDarkTheme?"bp3-dark":""].join(" ")},this.props),se("div",{className:K.TmF},se(y.cw,{label:"Add new folder",labelFor:"label-input"},se(y.BZ,{id:"label-input",placeholder:"Enter folder path...",rightElement:ae()()?t:n,onKeyDown:this.handleKeyDown,value:this.state.text,onChange:function(t){e.setState({text:t.target.value})}})),se(y.iz,{className:ie().Divider}),se("div",null,"Current Folders"),this.state.isAPICalled?se(y.$j,null):se(y.mp,{contents:this.state.parsedTree,onNodeCollapse:this.handleNodeCollapse,onNodeExpand:this.handleNodeExpand,className:(K.FZf,ie().Tree)}))))}}]),n}(v().Component),de=v().createElement;function pe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function he(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var o=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,o)}else n=a.apply(this,arguments);return(0,p.Z)(this,n)}}var fe,me=function(e){(0,d.Z)(n,e);var t=he(n);function n(e){var a;return(0,l.Z)(this,n),a=t.call(this,e),(0,f.Z)((0,u.Z)(a),"getImageElement",(function(){var e;return null!==(e=document.querySelector(".leaflet-pane.leaflet-overlay-pane img.leaflet-image-layer"))&&void 0!==e?e:document.querySelector(".leaflet-pane.leaflet-overlay-pane video.leaflet-image-layer")})),(0,f.Z)((0,u.Z)(a),"setFilter",(function(e){var t=window.getComputedStyle(a.getImageElement()).filter.split(" ");3===t.length?("brightness"===e.filterName?t[0]="brightness(".concat(e.value,"%)"):"contrast"===e.filterName?t[1]="contrast(".concat(e.value,"%)"):t[2]="saturate(".concat(e.value,"%)"),a.getImageElement().style.filter=t.join(" "),a.setState((function(t){var n=function(e){for(var t=1;t=e.length?{done:!0}:{done:!1,value:e[a++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,r=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return s=e.done,e},e:function(e){r=!0,i=e},f:function(){try{s||null==n.return||n.return()}finally{if(r)throw i}}}}function Ae(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=new Array(t);n=t.length-1)){var o=e?-1:1,i=Math.min(Math.max(0,n+o),t.length-1);a.selectAsset(t[i]),a.setSelectedAnnotation(null);var s=document.getElementById("image-bar");null!==s&&(s.scrollLeft+=120*o)}})),(0,f.Z)((0,u.Z)(a),"handleProgressToast",(function(){var e,t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],n=a.toaster.show(a.renderProgress(0));t?a.progressToastInterval=window.setInterval((function(){(0,w.Ig)().then((function(t){var o=t.data,i=o.progress,s=o.total;if(a.isFirstCallPerformed)if(1===i&&1===s)a.toaster.show(a.renderProgress(100),n),window.clearInterval(a.progressToastInterval),a.isFirstCallPerformed=!1,a.toaster.clear();else{e.report(i);var r=Math.ceil(e.estimate());a.toaster.show(a.renderProgress(100*i/s,ge(r)),n)}else a.isFirstCallPerformed=!0,(e=A()({min:i,max:s,historyTimeConstant:10})).start()}))}),500):a.progressToastInterval=window.setInterval((function(){if(null===a.state.uiState||a.state.predictDone===a.state.predictTotal)a.toaster.show(a.renderProgress(100),n),window.clearInterval(a.progressToastInterval);else{var e=15*Math.random()/a.state.multiplier;a.state.predictDone+e<.98*a.state.predictTotal&&a.setState((function(t){return{predictDone:t.predictDone+e,multiplier:t.multiplier+.18}}));var t=a.state.predictDone/a.state.predictTotal*100;a.toaster.show(a.renderProgress(t),n)}}),200)})),(0,f.Z)((0,u.Z)(a),"syncAllFolders",(0,r.Z)(s().mark((function e(){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a.setState({isSyncing:!0}),e.next=3,(0,w.T)().then((function(){a.updateImage()})).catch((function(e){var t="Failed to sync all folders.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)}));case 3:a.setState({isSyncing:!1});case 4:case"end":return e.stop()}}),e)})))),a.state={currentAssetAnnotations:[],userEditState:"None",changesMade:!1,assetList:[],cacheList:[],tagInfo:{modelHash:void 0,tags:{}},fileManagementOpen:!1,advancedSettingsOpen:!1,imageListCollapsed:!1,annotatedAssetsHidden:!1,killVideoPrediction:!1,isSyncing:!1,hiddenAnnotations:new Set,uiState:null,predictTotal:0,predictDone:0,multiplier:1,confidence:.5,annotationOptions:{isOutlined:!0,opacity:.45},filterArr:[],alwaysShowLabel:!1,showSelected:!0,inferenceOptions:{bulkAnalysisStatus:"both",cacheResults:!1,iou:.8,video:{frameInterval:1}},currAnnotationPlaybackId:0},a.toaster=new y.x7({},{}),a.progressToastInterval=600,a.currentTag=0,a.project=a.props.project,a.menubarRef=v().createRef(),a.menubarElement=void 0,a.isFirstCallPerformed=!1,a.currentAsset={},a.selectedAnnotation=null,a.annotationGroup=new m.FeatureGroup,a.imagebarRef=v().createRef(),a.backgroundImg=null,a.selectAsset=a.selectAsset.bind((0,u.Z)(a)),a.showToaster=a.showToaster.bind((0,u.Z)(a)),a.renderProgress=a.renderProgress.bind((0,u.Z)(a)),a.singleAnalysis=a.singleAnalysis.bind((0,u.Z)(a)),a.getInference=a.getInference.bind((0,u.Z)(a)),a.bulkAnalysis=a.bulkAnalysis.bind((0,u.Z)(a)),a.updateAnnotations=a.updateAnnotations.bind((0,u.Z)(a)),a.resetControls=a.resetControls.bind((0,u.Z)(a)),a.refreshProject=a.refreshProject.bind((0,u.Z)(a)),a.setAnnotationTag=a.setAnnotationTag.bind((0,u.Z)(a)),a.switchAnnotation=a.switchAnnotation.bind((0,u.Z)(a)),a.handleFileManagementOpen=a.handleFileManagementOpen.bind((0,u.Z)(a)),a.handleFileManagementClose=a.handleFileManagementClose.bind((0,u.Z)(a)),a.handleAdvancedSettingsOpen=a.handleAdvancedSettingsOpen.bind((0,u.Z)(a)),a.handleAdvancedSettingsClose=a.handleAdvancedSettingsClose.bind((0,u.Z)(a)),a.handlePlayPauseVideoOverlay=a.handlePlayPauseVideoOverlay.bind((0,u.Z)(a)),a.updateImage=a.updateImage.bind((0,u.Z)(a)),a.setAnnotationVisibility=a.setAnnotationVisibility.bind((0,u.Z)(a)),a.setAllAnnotationVisibility=a.setAllAnnotationVisibility.bind((0,u.Z)(a)),a.filterAnnotationVisibility=a.filterAnnotationVisibility.bind((0,u.Z)(a)),a.setAnnotationOptions=a.setAnnotationOptions.bind((0,u.Z)(a)),a.toggleShowSelected=a.toggleShowSelected.bind((0,u.Z)(a)),a.setAnnotatedAssetsHidden=a.setAnnotatedAssetsHidden.bind((0,u.Z)(a)),a}return(0,c.Z)(n,[{key:"componentDidMount",value:function(){var e=(0,r.Z)(s().mark((function e(){var t,n=this;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:this.menubarElement=document.getElementById("image-bar"),this.menubarElement.addEventListener("onwheel"in document?"wheel":"mousewheel",this.handleVerticalScrolling),this.map=m.map("annotation-map",{scrollWheelZoom:!0,zoomAnimation:!1,zoomDelta:0,zoomSnap:0,minZoom:-3,maxZoom:3,crs:m.CRS.Simple,attributionControl:!1,zoomControl:!1,doubleClickZoom:!1}).setView(Ze(5e3,5e3),0),this.annotationGroup.addTo(this.map),this.map.on("mouseup",(function(){if(n.videoOverlay){var e=n.videoOverlay.getElement();e!==document.activeElement&&(null===e||void 0===e||e.focus())}})),"",t=[Ze(3e4,0),Ze(0,23e3)],this.imageOverlay=m.imageOverlay("",t),this.videoOverlay=m.videoOverlay("",t,{interactive:!0}),new C(this.map,this),setTimeout((function(){return n.updateImage()}),200);case 11:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"componentDidUpdate",value:function(){var e=this;this.props.loadedModel&&this.props.loadedModel.hash!==this.state.tagInfo.modelHash&&((0,w.PF)(this.props.loadedModel.hash).then((function(t){var n,a={modelHash:null===(n=e.props.loadedModel)||void 0===n?void 0:n.hash,tags:t.data};e.setState({tagInfo:a,advancedSettingsOpen:!1}),Object.keys(e.state.tagInfo.tags).length>0&&(e.currentTag=0),e.annotationGroup.tags=e.state.tagInfo.tags})).catch((function(e){var t="Failed to obtain loaded model tags.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)})),this.updateImage()),this.props.loadedModel||void 0===this.state.tagInfo.modelHash||(this.setState({tagInfo:{modelHash:void 0,tags:{}}}),this.annotationGroup.tags=this.state.tagInfo.tags)}},{key:"componentWillUnmount",value:function(){void 0!==this.menubarElement&&this.menubarElement.removeEventListener("onwheel"in document?"wheel":"mousewheel",this.handleVerticalScrolling)}},{key:"handlePlayPauseVideoOverlay",value:function(){var e,t=null===(e=this.videoOverlay)||void 0===e?void 0:e.getElement();t&&t.onplaying&&(t.paused?t.play():t.pause())}},{key:"handleAdvancedSettingsClose",value:function(){this.setState({advancedSettingsOpen:!1})}},{key:"handleAdvancedSettingsOpen",value:function(){this.setState({advancedSettingsOpen:!0})}},{key:"handleFileManagementClose",value:function(){this.setState({fileManagementOpen:!1})}},{key:"handleFileManagementOpen",value:function(){this.setState({fileManagementOpen:!0})}},{key:"setUserState",value:function(e){this.state.userEditState!==e&&("None"!==e?(this.resetControls(),this.setState({userEditState:e})):this.setState({userEditState:e}))}},{key:"setAnnotationTag",value:function(e){return this.currentTag=e,this.currentTag}},{key:"setAnnotationOptions",value:function(e){var t=this;this.setState((function(t){var n=t.annotationOptions;switch(typeof e){case"boolean":n.isOutlined=!!e||!t.annotationOptions.isOutlined;break;case"number":n.opacity=e}return{annotationOptions:n}}),(function(){return t.filterAnnotationVisibility()}))}},{key:"setSelectedAnnotation",value:function(e){this.selectedAnnotation&&(this.selectedAnnotation.options.fillOpacity=.35,this.selectedAnnotation.fire("mouseout")),this.selectedAnnotation=e,this.selectedAnnotation&&(this.selectedAnnotation.options.fillOpacity=.7),null!==this.menubarRef.current&&this.menubarRef.current.setSelectedAnnotation(e)}},{key:"setAnnotationVisibility",value:function(e){for(var t=this,n=arguments.length,a=new Array(n>1?n-1:0),o=1;o0&&void 0!==o[0])||o[0],0===this.state.predictDone&&"Predicting"!==this.state.uiState){e.next=4;break}return(0,I.JJ)("Inference is already running",b.S.WARNING,3e3),e.abrupt("return");case 4:if(!(0,O.isEmpty)(this.currentAsset)||this.props.loadedModel){e.next=7;break}return(0,I.JJ)("There is no model and image loaded",b.S.WARNING,3e3),e.abrupt("return");case 7:if(!(0,O.isEmpty)(this.currentAsset)){e.next=10;break}return(0,I.JJ)("There is no image loaded",b.S.WARNING,3e3),e.abrupt("return");case 10:if(this.props.loadedModel){e.next=13;break}return(0,I.JJ)("There is no model loaded",b.S.WARNING,3e3),e.abrupt("return");case 13:return this.setState({predictTotal:100,predictDone:.01,multiplier:1,uiState:"Predicting"}),n&&"video"===this.currentAsset.type?(this.handleProgressToast(!0),null===(a=this.videoOverlay.getElement())||void 0===a||a.pause()):n&&this.handleProgressToast(),e.next=17,this.getInference(this.currentAsset,n);case 17:return e.next=19,this.updateImage();case 19:"video"===this.currentAsset.type&&(null===(t=this.videoOverlay.getElement())||void 0===t||t.play()),this.setState({predictDone:0,uiState:null,killVideoPrediction:!1});case 21:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"getInference",value:function(){var e=(0,r.Z)(s().mark((function e(t){var n,a,o,i=this,r=arguments;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=!(r.length>1&&void 0!==r[1])||r[1],a=!(r.length>2&&void 0!==r[2])||r[2],this.props.loadedModel){e.next=4;break}return e.abrupt("return");case 4:if(o=this.props.loadedModel.hash,this.setState({hiddenAnnotations:new Set}),"image"!==t.type||"video"===this.state.inferenceOptions.bulkAnalysisStatus&&!a){e.next=9;break}return e.next=9,(0,w.hu)(o,t.localPath,n,this.state.inferenceOptions.iou,"json").then((function(e){i.currentAsset.url===t.url&&a&&i.updateAnnotations(e.data)})).catch((function(e){var t="Failed to predict image.";e.response&&(t="".concat(e.response.data.message)),(0,I.JJ)(t,b.S.DANGER,3e3)}));case 9:if("video"!==t.type||"image"===this.state.inferenceOptions.bulkAnalysisStatus&&!a){e.next=12;break}return e.next=12,(0,w.ym)(o,t.localPath,n,this.state.inferenceOptions.video.frameInterval,this.state.inferenceOptions.iou).then((function(e){if(i.currentAsset.url===t.url&&a){var n=i.videoOverlay.getElement();"requestVideoFrameCallback"in HTMLVideoElement.prototype&&n.requestVideoFrameCallback((function t(a,o){var s=i.state.inferenceOptions.video.frameInterval/e.data.fps,r=Math.floor(o.mediaTime/s),l=Math.floor(r*s*1e3).toString();e.data.frames[l]&&i.updateAnnotations(e.data.frames[l]);var c=n.requestVideoFrameCallback(t);i.setState({currAnnotationPlaybackId:c})}))}})).catch((function(e){var t="Failed to predict video.",n=b.S.DANGER;e.response&&(t="".concat(e.response.data.message)),"STOPPEDPROCESS"===e.response.data.error&&(n=b.S.PRIMARY),(0,I.JJ)(t,n,3e3)}));case 12:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"showToaster",value:function(e){this.toaster.show(e)}},{key:"filterAnnotationVisibility",value:function(){var e=this;this.annotationGroup.clearLayers();var t=(0,O.invert)(this.state.tagInfo.tags);this.state.currentAssetAnnotations.filter((function(n){return!e.state.hiddenAnnotations.has(n.options.annotationID)&&(0===e.state.filterArr.length||e.state.showSelected===e.state.filterArr.some((function(e){return t[n.options.annotationTag].toLowerCase().includes(e.toLowerCase())})))&&n.options.confidence>=e.state.confidence})).forEach((function(t){var n=(0,O.cloneDeep)(t);n.options.fillOpacity=e.state.annotationOptions.opacity,n.options.weight=e.state.annotationOptions.isOutlined?t.options.weight:0,e.annotationGroup.addLayer(n)}));var n=(0,O.invert)(this.state.tagInfo.tags);this.annotationGroup.eachLayer((function(t){t.unbindTooltip(),t.bindTooltip("\n ").concat(n[t.options.annotationTag],"\n "),{interactive:!e.state.alwaysShowLabel,permanent:e.state.alwaysShowLabel,opacity:.9,direction:"center"})}))}},{key:"isAssetVisible",value:function(){return!this.state.annotatedAssetsHidden}},{key:"selectAsset",value:function(e){var t=this,n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=!(e.assetUrl!==this.currentAsset.assetUrl),o=this.videoOverlay.getElement();a||(this.setState({currentAssetAnnotations:[]}),this.annotationGroup.eachLayer((function(e){t.annotationGroup.removeLayer(e)})),this.updateMenuBarAnnotations(),o&&o.cancelVideoFrameCallback(this.state.currAnnotationPlaybackId));var i=0===Object.keys(this.currentAsset).length;if(this.imagebarRef.highlightAsset(e.assetUrl),this.annotationGroup.clearLayers(),this.annotationGroup.tags=this.state.tagInfo.tags,"image"===e.type){this.map.hasLayer(this.imageOverlay)||(this.videoOverlay.remove(),this.imageOverlay.addTo(this.map));var s=new Image;this.imageOverlay.setUrl(e.assetUrl),s.src=e.assetUrl,s.onload=function(){t.imageOverlay.setBounds(new m.LatLngBounds([[0,0],[s.height,s.width]])),t.currentAsset=be(be({},e),{},{metadata:{width:s.width,height:s.height}}),a||(t.map.setMinZoom(-5),t.map.invalidateSize(),setTimeout((function(){t.map.fitBounds(t.imageOverlay.getBounds(),{padding:new m.Point(20,20)})}),150),t.map.setMinZoom(-3),e.isCached&&n&&t.singleAnalysis(!1)),i&&t.setState({})},this.backgroundImg=document.querySelector(".leaflet-pane.leaflet-overlay-pane img.leaflet-image-layer")}if("video"===e.type){this.map.hasLayer(this.videoOverlay)||(this.imageOverlay.remove(),this.videoOverlay.addTo(this.map));var r=document.createElement("video");r.setAttribute("src",e.assetUrl),this.videoOverlay.setUrl(e.assetUrl),r.onloadedmetadata=function(){t.videoOverlay.setBounds(new m.LatLngBounds([[0,0],[r.videoHeight,r.videoWidth]])),t.currentAsset=be(be({},e),{},{metadata:{width:r.videoWidth,height:r.videoHeight}});var o=t.videoOverlay.getElement();o&&(o.controls=!0,o.setAttribute("controlsList","nofullscreen nodownload")),a?null===o||void 0===o||o.focus():(t.map.setMinZoom(-5),t.map.invalidateSize(),setTimeout((function(){t.map.fitBounds(t.videoOverlay.getBounds(),{padding:new m.Point(20,20)}),t.map.setMinZoom(-3),null===o||void 0===o||o.focus()}),150),e.isCached&&n&&t.singleAnalysis(!1)),i&&t.setState({})},this.backgroundImg=document.querySelector(".leaflet-pane.leaflet-overlay-pane video.leaflet-image-layer")}}},{key:"updateMenuBarAnnotations",value:function(){null!==this.menubarRef.current&&this.menubarRef.current.setAnnotations(this.annotationGroup)}},{key:"selectAnnotationTagByHash",value:function(e){var t=Object.values(this.state.tagInfo.tags).indexOf(e);-1!==t&&(this.currentTag=t,null!==this.menubarRef.current&&this.menubarRef.current.setAnnotationTag(t))}},{key:"refreshProject",value:function(){var e=(0,r.Z)(s().mark((function e(){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:this.selectAsset(this.currentAsset);case 1:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"addNewTag",value:function(e,t){this.setState((function(n){var a=be({},n.tagInfo.tags);return a[e]=t,{tagInfo:{modelHash:n.tagInfo.modelHash,tags:a}}}))}},{key:"resetControls",value:function(){this.setUserState("None"),this.setSelectedAnnotation(null)}},{key:"renderProgress",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",a={className:"bp3-text-muted ".concat(this.props.useDarkTheme?"bp3-dark":""),icon:"predictive-analysis",message:ve(y.ko,{className:"predict-prog",intent:e<100?"primary":"success",value:e/100}),onDismiss:function(e){e||(t.killVideoPrediction(),window.clearInterval(t.progressToastInterval)),t.isFirstCallPerformed=!1},timeout:e<100?0:600};return""!==n&&(a.action={text:n}),a}},{key:"renderHotkeys",value:function(){var e=this;return ve(y.SV,null,ve(y.qm,{global:!0,combo:"o",label:"Open Folder",onKeyDown:this.handleFileManagementOpen}),ve(y.qm,{global:!0,combo:"s",label:"Sync All Folders",onKeyDown:this.syncAllFolders}),ve(y.qm,{global:!0,combo:"A",label:"Analyze",onKeyDown:function(){return e.singleAnalysis()}}),ve(y.qm,{global:!0,combo:"b",label:"Bulk Analysis",onKeyDown:this.bulkAnalysis}),ve(y.qm,{global:!0,combo:"esc",label:"Exit Current Mode",onKeyDown:this.resetControls}),ve(y.qm,{global:!0,combo:"h",label:"Show / Hide Annotations",onKeyDown:function(){e.map.hasLayer(e.annotationGroup)?e.map.removeLayer(e.annotationGroup):e.map.addLayer(e.annotationGroup)}}),ve(y.qm,{global:!0,combo:"l",label:"Show / Hide Label",onKeyDown:function(){e.setState((function(e){return{alwaysShowLabel:!e.alwaysShowLabel}}),(function(){e.filterAnnotationVisibility()}))}}),ve(y.qm,{global:!0,combo:"left",label:"Load previous asset",onKeyDown:function(){return e.switchAnnotation(!0)}}),ve(y.qm,{global:!0,combo:"right",label:"Load previous asset",onKeyDown:function(){return e.switchAnnotation(!1)}}),ve(y.qm,{global:!0,combo:"space",label:"Play/Pause Video",onKeyDown:this.handlePlayPauseVideoOverlay}),Object.entries(this.state.tagInfo.tags).map((function(t,n){var a=(0,o.Z)(t,1)[0];if(!(n>9))return ve(y.qm,{key:a,global:!0,combo:"".concat(n+1),label:"Shortcut : ".concat(a),onKeyDown:function(){e.currentTag=n,null!=e.menubarRef.current&&e.menubarRef.current.setAnnotationTag(n)}})})))}},{key:"render",value:function(){var e=this,t=this.props.useDarkTheme?"":"light-",n=this.state.imageListCollapsed?"collapsed-":"",o=this.state.assetList.filter((function(){return e.isAssetVisible()}));return ve("div",null,ve(y.x7,(0,a.Z)({},this.state,{ref:this.refHandlers.toaster})),ve("div",{className:"workspace"},ve("div",{className:[n,"image-list"].join(""),id:"image-list"},ve(y.zx,{className:[t,"collapse-button"].join(""),large:!0,icon:this.state.imageListCollapsed?"caret-up":"caret-down",onClick:function(){e.setState((function(e){return{imageListCollapsed:!e.imageListCollapsed}}))}}),ve("div",{className:[t,"collapse-button-effect"].join("")}),ve(y.Zb,{className:[n,"image-bar"].join(""),id:"image-bar"},ve(B,(0,a.Z)({ref:function(t){e.imagebarRef=t},assetList:o,callbacks:{selectAssetCallback:this.selectAsset}},this.props)))),ve("div",{className:this.state.imageListCollapsed?"expanded-annotator-space":"annotator-space"},0===Object.keys(this.currentAsset).length?ve(y.Zb,{className:"annotator-non-ideal"},ve("div",{className:"bp3-non-ideal-state"},ve("div",{className:"bp3-non-ideal-state-visual"},ve("span",null,ve(y.JO,{icon:"media",iconSize:60}))),ve("h4",{className:"bp3-heading bp3-text-muted"},"Select an Image to Annotate"))):null,ve(y.Zb,{className:"main-annotator"},ve("div",{id:"annotation-map",className:"style-annotator"}),this.backgroundImg?ve("div",{className:"annotator-settings-button"},ve(me,{annotationOptions:this.state.annotationOptions,callbacks:{setAnnotatedAssetsHidden:this.setAnnotatedAssetsHidden,setAnnotationOptions:this.setAnnotationOptions}})):null)),ve("div",{className:"annotator-controls"},ve(V,{ref:this.menubarRef,isSyncing:this.state.isSyncing,projectTags:this.state.tagInfo.tags,userEditState:this.state.userEditState,changesMade:this.state.changesMade,uiState:this.state.uiState,predictDone:this.state.predictDone,predictTotal:this.state.predictTotal,hiddenAnnotations:this.state.hiddenAnnotations,confidence:this.state.confidence,filterArr:this.state.filterArr,showSelected:this.state.showSelected,useDarkTheme:this.props.useDarkTheme,isConnected:this.props.isConnected,loadedModel:this.props.loadedModel,currentAsset:this.currentAsset,assetList:this.state.assetList,callbacks:{ResetControls:this.resetControls,OpenFileManagement:this.handleFileManagementOpen,SetAnnotationTag:this.setAnnotationTag,OpenAdvancedSettings:this.handleAdvancedSettingsOpen,SetAnnotationVisibility:this.setAnnotationVisibility,SingleAnalysis:this.singleAnalysis,BulkAnalysis:this.bulkAnalysis,ToggleConfidence:this.toggleConfidence,SetFilterArr:this.setFilterArr,ToggleShowSelected:this.toggleShowSelected,SyncAllFolders:this.syncAllFolders}}),this.state.fileManagementOpen?ve(ue,(0,a.Z)({onClose:this.handleFileManagementClose,isOpen:!0,allowUserClose:!0,callbacks:{RefreshProject:this.refreshProject,UpdateImage:this.updateImage}},this.props)):null,this.state.advancedSettingsOpen?ve(X,(0,a.Z)({inferenceOptions:this.state.inferenceOptions,onClose:this.state.advancedSettingsOpen?this.handleAdvancedSettingsClose:this.handleAdvancedSettingsOpen,isOpen:!0,allowUserClose:!0,callbacks:{HandleChangeInSettings:this.handleChangeInAdvancedSettings}},this.props)):null)))}}]),n}(g.Component))||fe},5636:function(e){e.exports={Dialog:"filemodal_Dialog__2rWYe",Divider:"filemodal_Divider__jky9p",Tree:"filemodal_Tree__209ZG",NotFound:"filemodal_NotFound__28dHw",Icon:"filemodal_Icon__2nHDp",HintIcon:"filemodal_HintIcon__38we2"}},7019:function(e){e.exports={Card:"imagebar_Card__3TthZ",StackTop:"imagebar_StackTop__3s46r",Tag:"imagebar_Tag__hH6pd"}},9984:function(e){e.exports={SpacedIcon:"menu_SpacedIcon__2TTAc",SelectionList:"menu_SelectionList__1AqpU",Spin:"menu_Spin__t3d2N",Slider:"menu_Slider__3eu1p",Icon:"menu_Icon__2akHD",InferenceMenuItem:"menu_InferenceMenuItem__1hZUs",TagList:"menu_TagList__3yjBd"}},1164:function(e){e.exports={Dialog:"settingsmodal_Dialog__2B1jD",Divider:"settingsmodal_Divider__2LpZ6",Section:"settingsmodal_Section__27Rr4",Icon:"settingsmodal_Icon__1i0mE",Slider:"settingsmodal_Slider__3nRpn",SubTitle:"settingsmodal_SubTitle__2Ifm8"}}}]); \ No newline at end of file diff --git a/portal_build/out/_next/static/chunks/pages/index-8da26dc3ba2af71eb1da.js b/portal_build/out/_next/static/chunks/pages/index-8da26dc3ba2af71eb1da.js new file mode 100644 index 00000000..066eefc1 --- /dev/null +++ b/portal_build/out/_next/static/chunks/pages/index-8da26dc3ba2af71eb1da.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[405],{526:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return ne}});var a=n(5579),r=n(809),o=n.n(r),s=n(2447),i=n(4047),l=n(2700),c=n(4706),d=n(8127),u=n(4102),h=n(775),f=n(7294),p=n.n(f),m=n(9008),g=n(5152),v=n(451),F=n(5509),b=n(6265),C=n(1163),D=n(9669),A=n.n(D),y=n(2875);function S(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function w(e){for(var t=1;tt?"".concat(e.substring(0,t-1),".."):e})),a.state={registeredModelList:{},currentModel:void 0,chosenModel:void 0,waitForRuntime:!0,isConfirmLoad:!1,isConfirmUnload:!1,isConfirmDelete:!1,isAPIcalled:!1,isUnloadModelAPI:!1,isLoadModelAPI:!1,isGetTagAPI:!1,isOpenDrawer:!1,isOpenRegistraionForm:!1,generalIcon:void 0,projectTags:{},formData:{type:"local",modelType:"autodetect",name:"",description:"",directory:"",modelKey:"",projectKey:"",projectSecret:"",modelURL:""},drawerTabId:"details",registrationTabId:"local"},a.createMenuItems=a.createMenuItems.bind((0,c.Z)(a)),a.handleRegisterModel=a.handleRegisterModel.bind((0,c.Z)(a)),a.handleElectronFileDialog=a.handleElectronFileDialog.bind((0,c.Z)(a)),a.handleUnloadAndLoadModel=a.handleUnloadAndLoadModel.bind((0,c.Z)(a)),a.handleDeleteModel=a.handleDeleteModel.bind((0,c.Z)(a)),a.formatLongStringName=a.formatLongStringName.bind((0,c.Z)(a)),a}return(0,l.Z)(n,[{key:"componentDidMount",value:function(){var e=(0,s.Z)(o().mark((function e(){var t,n=this;return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:O()()&&(t=window.require("electron"),t.ipcRenderer.on("select-model-reply",this.handleElectronChangeDirListener));case 1:if(!this.state.waitForRuntime){e.next=8;break}return e.next=4,(0,N.kE)().then(function(){var e=(0,s.Z)(o().mark((function e(t){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(200!==t.status){e.next=6;break}if(n.setState({registeredModelList:n.generateRegisteredModelList(t.data)}),n.state.registeredModelList==={}){e.next=5;break}return e.next=5,n.handleGetLoadedModel();case 5:n.setState({waitForRuntime:!1});case 6:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()).catch((function(){}));case 4:return e.next=6,new Promise((function(e){return setTimeout(e,25e3)}));case 6:e.next=1;break;case 8:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"componentWillUnmount",value:function(){O()()&&window.require("electron").ipcRenderer.removeListener("select-model-reply",this.handleElectronChangeDirListener)}},{key:"render",value:function(){var e,t,n,a,r,o,s,i,l,c,d,u,h,f,m,g=this,F=G(P.zx,{text:"Browse",icon:"folder-new",intent:"success",loading:!1,onClick:function(){g.handleElectronFileDialog()}}),b=G(P.u,{content:G(p().Fragment,null,G("p",null,"Type the path of the folder that contains the model and label_map.pbtxt"),G("b",null,"Example"),G("p",null,G("pre",null,"/user/example/folder"))),position:T.Ly.TOP},G(P.JO,{icon:"help",className:B().HintIcon})),C=G(P.v2,{className:B().PopOverMenu},0===Object.keys(this.state.registeredModelList).length?G("div",{className:B().NonIdealPopOver},G("div",{className:"bp3-non-ideal-state"},G("div",{className:"bp3-non-ideal-state-visual"},G(P.JO,{icon:"folder-open",iconSize:P.Jh.LARGE})),G("h5",{className:"bp3-heading bp3-text-muted"},"Press the + sign to add new models"))):this.createMenuItems()),D={autodetect:"Auto Detect",tensorflow:"TensorFlow 2.x",darknet:"DarkNet (YOLO v3, YOLO v4)"},A=G("div",{className:B().RegistrationForm},"local"===this.state.registrationTabId?G(p().Fragment,null,G(P.cw,{label:"Model Type",labelFor:"label-input"},G(P.J2,{minimal:!0,content:G(P.v2,null,G(P.v2.Item,{shouldDismissPopover:!1,text:D.autodetect,onClick:function(){g.handleChangeForm({target:{name:"modelType",value:"autodetect"}})}}),G(P.v2.Item,{shouldDismissPopover:!1,text:D.tensorflow,onClick:function(){g.handleChangeForm({target:{name:"modelType",value:"tensorflow"}})}}),G(P.v2.Item,{shouldDismissPopover:!1,text:D.darknet,onClick:function(){g.handleChangeForm({target:{name:"modelType",value:"darknet"}})}})),placement:"bottom-start"},G(P.zx,{text:""!==this.state.formData.modelType?D[this.state.formData.modelType]:"None selected",rightIcon:"double-caret-vertical"})))):null,G(P.cw,{label:"Name",labelFor:"label-input"},G(P.BZ,{id:"name",name:"name",value:this.state.formData.name,placeholder:"Enter name of the model...",onChange:this.handleChangeForm})),this.renderTabSettings(this.state.registrationTabId,F,b),G(P.zx,{type:"submit",text:"Register",disabled:this.state.isAPIcalled,onClick:this.handleRegisterModel}),G("div",{className:B().Right},this.state.isAPIcalled?G(P.$j,{size:14}):void 0!==this.state.generalIcon?G(P.JO,{icon:null===(e=this.state.generalIcon)||void 0===e?void 0:e.name,intent:null===(t=this.state.generalIcon)||void 0===t?void 0:t.intent,iconSize:14}):null)),y=G("div",{className:B().Panel},G("div",{className:["bp3-elevation-2",B().Section].join(" ")},G("h6",{className:"bp3-heading"},"Directory"),G("p",{className:"bp3-running-text"},null===(n=this.state.chosenModel)||void 0===n?void 0:n.directory)),G("div",{className:["bp3-elevation-2",B().Section].join(" ")},G("h6",{className:"bp3-heading"},"Tag Map"),G("div",{className:B().TagsList},G(P.cw,null,this.state.isGetTagAPI?G(P.$j,{className:B().Spin}):Object.keys(this.state.projectTags).map((function(e){return G(P.Vp,{key:g.state.projectTags[e],interactive:!0,className:B().TagLabel},G(P.JO,{icon:"symbol-circle",color:g.handleGetTagHashColour(g.state.projectTags[e])})," ",e)})))))),S=G(P.dy,{className:this.props.useDarkTheme?"bp3-dark":"bp3-light",size:"360px",onClose:this.handleCloseDrawer,canEscapeKeyClose:!0,canOutsideClickClose:!0,isOpen:this.state.isOpenDrawer,position:T.Ly.RIGHT,usePortal:!0},G("div",{className:"bp3-drawer-header"},G(P.JO,{className:"bp3-icon",icon:"dot",iconSize:14,intent:(null===(a=this.state.chosenModel)||void 0===a?void 0:a.hash)===(null===(r=this.state.currentModel)||void 0===r?void 0:r.hash)?M.S.SUCCESS:M.S.DANGER}),G("h4",{className:"bp3-heading"},null===(o=this.state.chosenModel)||void 0===o?void 0:o.name),G(P.zx,{className:"bp3-dialog-close-button",minimal:!0,icon:"arrow-right",onClick:this.handleCloseDrawer})),G(P.wp,{className:B().DrawerNavbar},G(P.fT,{align:x.v.LEFT,className:B().DrawerNavbar},G(P.mQ,{id:"DrawerTabs",large:!0,onChange:this.handleDrawerTabChange,selectedTabId:this.state.drawerTabId,renderActiveTabPanelOnly:!0},G(P.OK,{id:"details",title:"Details"}),G(P.mQ.Expander,null)))),G("div",{className:v.$fE},G("div",null,"details"===this.state.drawerTabId?y:null)),G("div",{className:[v.e$L,v.bDx].join(" ")},G(P.zx,{type:"button",text:"Unload",disabled:(null===(s=this.state.chosenModel)||void 0===s?void 0:s.hash)!==(null===(i=this.state.currentModel)||void 0===i?void 0:i.hash)||this.state.isUnloadModelAPI,onClick:function(){g.setState({isConfirmUnload:!0})}}),G(P.J2,{interactionKind:P.V3.HOVER,content:G("div",{className:B().Section},"Delete")},G(P.zx,{type:"button",intent:M.S.DANGER,disabled:this.state.isAPIcalled,icon:"trash",onClick:function(){g.setState({isConfirmDelete:!0})}}))));return G(p().Fragment,null,G("div",{style:{maxWidth:"140px",minWidth:"140px"}},this.state.isLoadModelAPI?G(P.ko,null):G(P.J2,{className:B().PopOver,content:C,placement:"bottom",isOpen:!this.state.isOpenDrawer&&void 0,disabled:this.state.waitForRuntime&&!this.props.isConnected},G(P.u,{content:"Select a Model to Load",disabled:0===Object.keys(this.state.registeredModelList).length||!!this.state.currentModel,isOpen:!this.state.isOpenRegistraionForm&&!this.state.isOpenDrawer&&!this.state.currentModel&&Object.keys(this.state.registeredModelList).length>0||void 0},G(P.zx,{disabled:this.state.waitForRuntime&&!this.props.isConnected,className:this.state.waitForRuntime&&!this.props.isConnected?"bp3-skeleton":"",style:{minWidth:"140px",alignContent:"left"},alignText:x.v.LEFT,minimal:!0,rightIcon:"caret-down",text:void 0!==this.state.currentModel?this.formatLongStringName(this.state.currentModel.name,15):"Load Model.."})))),G(P.J2,{content:G(p().Fragment,null,G(P.wp,{className:B().DrawerNavbar},G(P.fT,{align:x.v.LEFT,className:B().DrawerNavbar},G(P.mQ,{id:"RegisterationTabs",large:!1,onChange:this.handleRegistrationTabChange,selectedTabId:this.state.registrationTabId,renderActiveTabPanelOnly:!0},G(P.OK,{id:"local",title:"Local"}),G(P.OK,{id:"hub",title:"Datature Hub"}),G(P.OK,{id:"endpoint",title:"Datature API",disabled:!1}),G(P.mQ.Expander,null)))," "),G("div",{className:v.$fE},A)),placement:"left-end",onOpening:function(){return g.setState({isOpenRegistraionForm:!0})},onClosed:function(){g.setState({generalIcon:void 0,formData:{type:"local",modelType:"autodetect",name:"",description:"",directory:"",modelKey:"",projectKey:"",projectSecret:"",modelURL:""},registrationTabId:"local",isOpenRegistraionForm:!1})}},G(P.u,{disabled:Object.keys(this.state.registeredModelList).length>0,content:"Add a Model Here",isOpen:0===Object.keys(this.state.registeredModelList).length},G(P.zx,{minimal:!0,icon:"plus"}))),S,G(P.bZ,{isOpen:this.state.isConfirmLoad,intent:M.S.WARNING,icon:"warning-sign",loading:this.state.isLoadModelAPI,onCancel:function(){return g.setState({isConfirmLoad:!1})},onConfirm:this.handleUnloadAndLoadModel,cancelButtonText:"Cancel",confirmButtonText:"I Understand",className:this.props.useDarkTheme?"bp3-dark":""},this.state.currentModel?G("div",null,"We will unload ",this.state.currentModel.name," and load"," ",null===(l=this.state.chosenModel)||void 0===l?void 0:l.name,". Are you sure you want to continue?"):G("div",null,"Confirm that you want to load ",null===(c=this.state.chosenModel)||void 0===c?void 0:c.name,".")),G(P.bZ,{isOpen:this.state.isConfirmUnload,intent:M.S.WARNING,icon:"warning-sign",loading:this.state.isUnloadModelAPI,onCancel:function(){return g.setState({isConfirmUnload:!1})},onConfirm:this.handleUnloadModel,cancelButtonText:"Cancel",confirmButtonText:"I Understand",className:this.props.useDarkTheme?"bp3-dark":""},G("div",null,"We will unload ",null===(d=this.state.currentModel)||void 0===d?void 0:d.name,". Are you sure you want to continue?")),G(P.bZ,{isOpen:this.state.isConfirmDelete,intent:M.S.WARNING,icon:"warning-sign",loading:this.state.isAPIcalled,onCancel:function(){return g.setState({isConfirmDelete:!1})},onConfirm:this.handleDeleteModel,cancelButtonText:"Cancel",confirmButtonText:"I Understand",className:this.props.useDarkTheme?"bp3-dark":""},(null===(u=this.state.currentModel)||void 0===u?void 0:u.hash)===(null===(h=this.state.chosenModel)||void 0===h?void 0:h.hash)?G("div",null,"This model is loaded. We will unload and delete"," ",null===(f=this.state.currentModel)||void 0===f?void 0:f.name,". Are you sure you want to continue?"):G("div",null,"Confirm that you want to delete ",null===(m=this.state.chosenModel)||void 0===m?void 0:m.name,".")))}}]),n}(p().Component),J=p().createElement;function U(e){var t,n=(0,f.useState)(!1),a=n[0],r=n[1],o=0,s=!1,i=e.isConnected,l=function(){var n;(n=O()(),A().get(y.JA+y.MV,{params:{isElectron:n}})).then((function(n){var l=n.data.hasCache&&!n.data.isCacheCalled;e.callbacks.HandleHasCache(l),i||(e.callbacks.HandleIsConnected(!0),i=!0,e.callbacks.HandleElectronGPUListener()),t&&(0,Z.wA)(t),s||(s=!0),o=0,a&&r(!1)})).catch((function(){if(s&&!O()()){t&&(0,Z.wA)(t),(0,Z.JJ)("Portal runtime is unresponsive. Restart server.",M.S.WARNING,25e3,"outdated")}else if(s||0!==o){if((o>=1&&!s||s)&&O()()){var n={onClick:function(){r(!0),(0,Z.M4)(),window.require("electron").ipcRenderer.send("restart-server")},text:"Restart?"};t&&(0,Z.wA)(t),(0,Z.JJ)("Portal runtime is unresponsive.",M.S.WARNING,25e3,"outdated",n)}}else{var a=J(p().Fragment,null,J(P.$j,{size:15,className:"bp3-icon"}));t=(0,Z.JJ)("Waiting for runtime to load",M.S.PRIMARY,0,a)}o+=1,e.isConnected&&(e.callbacks.HandleIsConnected(!1),i=!1)}))};return(0,f.useEffect)((function(){l();var e=setInterval(l,3e4);return function(){return clearInterval(e)}}),[a]),J(p().Fragment,null)}var W=f.createElement;function K(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var r=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return(0,u.Z)(this,n)}}var H=function(e){(0,d.Z)(n,e);var t=K(n);function n(e){return(0,i.Z)(this,n),t.call(this,e)}return(0,l.Z)(n,[{key:"render",value:function(){var e=this;return W(f.Fragment,null,W(P.cw,{label:W("b",null,"Interface")},W(P.rs,{label:"Dark Mode",defaultChecked:this.props.GlobalSetting.useDarkTheme,onChange:function(t){e.props.GlobalSettingCallback.setTheme(t.target.checked)}})),W(P.cw,{label:W("b",null,"Proccessor")},W(P.u,{disabled:O()(),content:this.props.GlobalSetting.isGPU?"Exclude the --gpu flag to run in cpu mode":"Add the --gpu flag to run the server on GPU",position:T.Ly.BOTTOM},W(P.rs,{disabled:!O()(),label:"Run on GPU",checked:this.props.GlobalSetting.isGPU,onChange:function(t){e.props.callbacks.OpenProcessorAlert(t.target.checked)}}))),W(P.cw,{label:W("b",null,"Autosave")},W(P.rs,{label:"Autosave Progress",checked:this.props.GlobalSetting.isAutosave,onChange:function(t){e.props.GlobalSettingCallback.setAutosave(t.target.checked)}})))}}]),n}(f.Component),z=f.createElement;function V(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var r=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return(0,u.Z)(this,n)}}var q=function(e){(0,d.Z)(n,e);var t=V(n);function n(e){var a;return(0,i.Z)(this,n),a=t.call(this,e),(0,b.Z)((0,c.Z)(a),"componentDidMount",(function(){O()()&&window.require("electron").ipcRenderer.on("restart-server-reply",a.handleElectronGPUListener)})),(0,b.Z)((0,c.Z)(a),"componentWillUnmount",(function(){O()()&&window.require("electron").ipcRenderer.removeListener("restart-server-reply",a.handleElectronGPUListener)})),(0,b.Z)((0,c.Z)(a),"handleElectronGPUListener",(0,s.Z)(o().mark((function e(){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,k().then((function(e){0===e.data?a.props.GlobalSettingCallback.setGPU(!0):a.props.GlobalSettingCallback.setGPU(!1)}));case 2:a.setState({isChangingProcessor:!1,changeProcessor:!1});case 3:case"end":return e.stop()}}),e)})))),(0,b.Z)((0,c.Z)(a),"openProcessorAlert",(function(){a.setState({changeProcessor:!0})})),(0,b.Z)((0,c.Z)(a),"handleChangeProcessor",(0,s.Z)(o().mark((function e(){var t;return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(a.setState({isChangingProcessor:!0}),!a.props.GlobalSetting.isGPU){e.next=6;break}return e.next=4,A().post(y.JA+y.QV).catch((function(e){var t="Failed to clear gpu";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 4:e.next=8;break;case 6:return e.next=8,A().post(y.JA+y.Gz).catch((function(e){var t="Failed to set gpu";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 8:return e.next=10,n=void 0,A().get(y.JA+y.ZW,{params:w({},n?{deleteCache:n}:{})});case 10:t=window.require("electron"),t.ipcRenderer.send("restart-server");case 12:case"end":return e.stop()}var n}),e)})))),(0,b.Z)((0,c.Z)(a),"handleLoadCache",(0,s.Z)(o().mark((function e(){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a.setState({isAPICalled:!0}),e.next=3,A().post(y.JA+y.xy).then((function(){a.setState({hasCache:!1}),window.location.reload(!1)})).catch((function(e){var t="Failed to load cache.";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 3:a.setState({isAPICalled:!1});case 4:case"end":return e.stop()}}),e)})))),(0,b.Z)((0,c.Z)(a),"handleRejectCache",(0,s.Z)(o().mark((function e(){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a.setState({isAPICalled:!0}),e.next=3,A().put(y.JA+y.xy).then((function(){a.setState({hasCache:!1})})).catch((function(e){var t="Failed to reject cache.";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 3:a.setState({isAPICalled:!1});case 4:case"end":return e.stop()}}),e)})))),(0,b.Z)((0,c.Z)(a),"isProjectBoard",(function(){return"project"===a.state.urlPath.split("/")[1]})),a.state={isChangingProcessor:!1,changeProcessor:!1,urlPath:"",hasCache:!1,isAPICalled:!1},a}return(0,l.Z)(n,[{key:"render",value:function(){var e=this;return z(f.Fragment,null,z(P.wp,null,z(P.fT,{align:x.v.LEFT},z(P.AN,{icon:z($,null),minimal:!0,onClick:function(){C.default.push({pathname:"/"})}}),z("span",{className:"bp3-navbar-divider"})),z(P.fT,{align:x.v.RIGHT},z("span",{className:"bp3-navbar-divider"}),z(_,(0,a.Z)({},this.props.GlobalSetting,{callbacks:{HandleModelChange:this.props.GlobalSettingCallback.handleModelChange}})),z("span",{className:"bp3-navbar-divider"}),z(P.zx,{style:{userSelect:"none",minWidth:"max-content"},className:"bp3-button bp3-minimal",onClick:function(){window.location="https://joindatature.slack.com/join/shared_invite/zt-hv9xv84h-WYDFnU1clNM0eGW4SfQGGg#/"}},"Community Slack"),z("span",{className:"bp3-navbar-divider"}),z(P.J2,{popoverClassName:v.lik,forceFocus:!1,position:"bottom-right",content:z(H,(0,a.Z)({},this.props,{callbacks:{OpenProcessorAlert:this.openProcessorAlert}}))},z(P.zx,{icon:"cog",className:"bp3-button bp3-minimal"})),z(P.zx,{icon:"help",className:"bp3-button bp3-minimal",onClick:function(){window.open("https://docs.datature.io/portal")}}))),z(U,{isConnected:this.props.GlobalSetting.isConnected,callbacks:{HandleHasCache:function(t){e.setState({hasCache:t})},HandleIsConnected:this.props.GlobalSettingCallback.handleIsConnected,HandleElectronGPUListener:this.handleElectronGPUListener}}),z(P.bZ,{isOpen:this.state.changeProcessor,intent:M.S.PRIMARY,icon:"warning-sign",loading:this.state.isChangingProcessor,onCancel:function(){return e.setState({changeProcessor:!1})},onConfirm:this.handleChangeProcessor,cancelButtonText:"No",confirmButtonText:"Yes",className:this.props.GlobalSetting.useDarkTheme?"bp3-dark":""},z("div",null,"To change the processor to"," ",this.props.GlobalSetting.isGPU?"CPU":"GPU",". The server has to restart. Do you wish to continue?")),z(P.bZ,{isOpen:this.state.hasCache,intent:M.S.PRIMARY,icon:"history",loading:this.state.isAPICalled,onCancel:this.handleRejectCache,onConfirm:this.handleLoadCache,cancelButtonText:"No",confirmButtonText:"Yes",className:this.props.GlobalSetting.useDarkTheme?"bp3-dark":""},z("div",null,"Unsaved session found. Would you like to resume from the previous session?")))}}]),n}(f.Component),$=function(){return z("svg",{width:"30",height:"30",viewBox:"0 0 512 512",className:"NexusLogo"},z("rect",{style:{fill:"#fff"},x:"94",y:"181",width:"80",height:"80"}),z("rect",{id:"Rectangle_1_copy_3","data-name":"Rectangle 1 copy 3",style:{fill:"#fff"},x:"94",y:"354",width:"80",height:"80"}),z("rect",{id:"Rectangle_1_copy","data-name":"Rectangle 1 copy",style:{fill:"#fff"},x:"173",y:"100",width:"244",height:"80"}),z("rect",{id:"Rectangle_1_copy-2","data-name":"Rectangle 1 copy",style:{fill:"#fff"},x:"94",y:"283",width:"252",height:"71"}),z("rect",{id:"Rectangle_1_copy-3","data-name":"Rectangle 1 copy",style:{fill:"#fff"},x:"346",y:"100",width:"71",height:"183"}))},Q=p().createElement;function Y(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var r=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return(0,u.Z)(this,n)}}var X="nexus-theme",ee=(0,g.default)((function(){return Promise.all([n.e(662),n.e(269),n.e(3),n.e(607)]).then(n.bind(n,4607))}),{ssr:!1,loadableGenerated:{webpack:function(){return[4607]},modules:["index.js -> ../src/components/annotations/annotator.tsx"]}}),te=function(e){(0,d.Z)(n,e);var t=Y(n);function n(e){var a;return(0,i.Z)(this,n),(a=t.call(this,e)).state={isGPU:!1,useDarkTheme:!0,loadedModel:void 0,isConnected:!1,isAutosave:!1},(0,F.Dg)({gutterWidth:12}),a.setTheme=a.setTheme.bind((0,c.Z)(a)),a.setGPU=a.setGPU.bind((0,c.Z)(a)),a.setAutosave=a.setAutosave.bind((0,c.Z)(a)),a}return(0,l.Z)(n,[{key:"componentDidMount",value:function(){var e=this,t=localStorage.getItem(X);this.setState({useDarkTheme:null==t||"true"===t}),k().then((function(t){0===t.data&&e.setState({isGPU:!0})})),A().get(y.JA+y.MK).then((function(t){1===t.data&&e.setState({isAutosave:!0})}))}},{key:"setTheme",value:function(e){localStorage.setItem(X,e),this.setState({useDarkTheme:e})}},{key:"setGPU",value:function(){var e=(0,s.Z)(o().mark((function e(t){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:this.setState({isGPU:t});case 1:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"setAutosave",value:function(){var e=(0,s.Z)(o().mark((function e(t){var n=this;return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:E(t).then((function(e){200===e.status&&n.setState({isAutosave:t})}));case 1:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()},{key:"render",value:function(){var e=this;return Q(p().Fragment,null,Q(m.default,null,Q("title",null,"Portal"),Q("link",{rel:"icon",type:"image/x-icon",href:"./portal-ico-dark.png",media:"(prefers-color-scheme:dark)"}),Q("link",{rel:"icon",type:"image/x-icon",href:"./portal-ico-light.png",media:"(prefers-color-scheme:light)"}),Q("link",{rel:"stylesheet",href:"https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"}),Q("link",{rel:"stylesheet",href:"https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.3/leaflet.draw.css"}),Q("link",{href:"./static/style/annotation.css",rel:"stylesheet"}),Q("link",{href:this.state.useDarkTheme?"./static/style/global-dark.css":"./static/style/global-light.css",rel:"stylesheet"})),Q("div",{className:this.state.useDarkTheme?v.Pyr:""},Q(q,{active:"Annotations",GlobalSetting:this.state,GlobalSettingCallback:{setTheme:this.setTheme,setGPU:this.setGPU,setAutosave:this.setAutosave,handleIsConnected:function(t){e.setState({isConnected:t})},handleModelChange:function(t){e.setState({loadedModel:t})}}}),Q(ee,(0,a.Z)({project:this.props.projectID},this.props,this.state))))}}]),n}(p().Component),ne=function(e){return Q(te,(0,a.Z)({projectID:"906969446527476eefc2d2062897f92d"},e))}},7316:function(e,t,n){"use strict";n.d(t,{lp:function(){return c},_q:function(){return d},nW:function(){return u},Ng:function(){return h},T:function(){return f},Q3:function(){return p},kE:function(){return m},Ge:function(){return g},kV:function(){return v},Z8:function(){return F},Ey:function(){return b},G$:function(){return C},yl:function(){return D},PF:function(){return A},ym:function(){return y},hu:function(){return S},Ig:function(){return w},pF:function(){return E}});var a=n(6265),r=n(9669),o=n.n(r),s=n(2875);function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;tt?"".concat(e.substring(0,t-1),".."):e})),a.state={registeredModelList:{},currentModel:void 0,chosenModel:void 0,waitForRuntime:!0,isConfirmLoad:!1,isConfirmUnload:!1,isConfirmDelete:!1,isAPIcalled:!1,isUnloadModelAPI:!1,isLoadModelAPI:!1,isGetTagAPI:!1,isOpenDrawer:!1,isOpenRegistraionForm:!1,generalIcon:void 0,projectTags:{},formData:{type:"local",modelType:"autodetect",name:"",description:"",directory:"",modelKey:"",projectSecret:"",modelURL:""},drawerTabId:"details",registrationTabId:"local"},a.createMenuItems=a.createMenuItems.bind((0,c.Z)(a)),a.handleRegisterModel=a.handleRegisterModel.bind((0,c.Z)(a)),a.handleElectronFileDialog=a.handleElectronFileDialog.bind((0,c.Z)(a)),a.handleUnloadAndLoadModel=a.handleUnloadAndLoadModel.bind((0,c.Z)(a)),a.handleDeleteModel=a.handleDeleteModel.bind((0,c.Z)(a)),a.formatLongStringName=a.formatLongStringName.bind((0,c.Z)(a)),a}return(0,l.Z)(n,[{key:"componentDidMount",value:function(){var e=(0,s.Z)(o().mark((function e(){var t,n=this;return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:O()()&&(t=window.require("electron"),t.ipcRenderer.on("select-model-reply",this.handleElectronChangeDirListener));case 1:if(!this.state.waitForRuntime){e.next=8;break}return e.next=4,(0,R.kE)().then(function(){var e=(0,s.Z)(o().mark((function e(t){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(200!==t.status){e.next=6;break}if(n.setState({registeredModelList:n.generateRegisteredModelList(t.data)}),n.state.registeredModelList==={}){e.next=5;break}return e.next=5,n.handleGetLoadedModel();case 5:n.setState({waitForRuntime:!1});case 6:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()).catch((function(){}));case 4:return e.next=6,new Promise((function(e){return setTimeout(e,25e3)}));case 6:e.next=1;break;case 8:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"componentWillUnmount",value:function(){O()()&&window.require("electron").ipcRenderer.removeListener("select-model-reply",this.handleElectronChangeDirListener)}},{key:"render",value:function(){var e,t,n,a,r,o,s,i,l,c,d,u,h,f,m,g=this,F=G(P.zx,{text:"Browse",icon:"folder-new",intent:"success",loading:!1,onClick:function(){g.handleElectronFileDialog()}}),b=G(P.u,{content:G(p().Fragment,null,G("p",null,"Type the path of the folder that contains the model and label_map.pbtxt"),G("b",null,"Example"),G("p",null,G("pre",null,"/user/example/folder"))),position:T.Ly.TOP},G(P.JO,{icon:"help",className:B().HintIcon})),C=G(P.v2,{className:B().PopOverMenu},0===Object.keys(this.state.registeredModelList).length?G("div",{className:B().NonIdealPopOver},G("div",{className:"bp3-non-ideal-state"},G("div",{className:"bp3-non-ideal-state-visual"},G(P.JO,{icon:"folder-open",iconSize:P.Jh.LARGE})),G("h5",{className:"bp3-heading bp3-text-muted"},"Press the + sign to add new models"))):this.createMenuItems()),D={autodetect:"Auto Detect",tensorflow:"TensorFlow 2.x",darknet:"DarkNet (YOLO v3, YOLO v4)"},A=G("div",{className:B().RegistrationForm},"local"===this.state.registrationTabId?G(p().Fragment,null,G(P.cw,{label:"Model Type",labelFor:"label-input"},G(P.J2,{minimal:!0,content:G(P.v2,null,G(P.v2.Item,{shouldDismissPopover:!1,text:D.autodetect,onClick:function(){g.handleChangeForm({target:{name:"modelType",value:"autodetect"}})}}),G(P.v2.Item,{shouldDismissPopover:!1,text:D.tensorflow,onClick:function(){g.handleChangeForm({target:{name:"modelType",value:"tensorflow"}})}}),G(P.v2.Item,{shouldDismissPopover:!1,text:D.darknet,onClick:function(){g.handleChangeForm({target:{name:"modelType",value:"darknet"}})}})),placement:"bottom-start"},G(P.zx,{text:""!==this.state.formData.modelType?D[this.state.formData.modelType]:"None selected",rightIcon:"double-caret-vertical"})))):null,G(P.cw,{label:"Name",labelFor:"label-input"},G(P.BZ,{id:"name",name:"name",value:this.state.formData.name,placeholder:"Enter name of the model...",onChange:this.handleChangeForm})),this.renderTabSettings(this.state.registrationTabId,F,b),G(P.zx,{type:"submit",text:"Register",disabled:this.state.isAPIcalled,onClick:this.handleRegisterModel}),G("div",{className:B().Right},this.state.isAPIcalled?G(P.$j,{size:14}):void 0!==this.state.generalIcon?G(P.JO,{icon:null===(e=this.state.generalIcon)||void 0===e?void 0:e.name,intent:null===(t=this.state.generalIcon)||void 0===t?void 0:t.intent,iconSize:14}):null)),y=G("div",{className:B().Panel},G("div",{className:["bp3-elevation-2",B().Section].join(" ")},G("h6",{className:"bp3-heading"},"Directory"),G("p",{className:"bp3-running-text"},null===(n=this.state.chosenModel)||void 0===n?void 0:n.directory)),G("div",{className:["bp3-elevation-2",B().Section].join(" ")},G("h6",{className:"bp3-heading"},"Tag Map"),G("div",{className:B().TagsList},G(P.cw,null,this.state.isGetTagAPI?G(P.$j,{className:B().Spin}):Object.keys(this.state.projectTags).map((function(e){return G(P.Vp,{key:g.state.projectTags[e],interactive:!0,className:B().TagLabel},G(P.JO,{icon:"symbol-circle",color:g.handleGetTagHashColour(g.state.projectTags[e])})," ",e)})))))),S=G(P.dy,{className:this.props.useDarkTheme?"bp3-dark":"bp3-light",size:"360px",onClose:this.handleCloseDrawer,canEscapeKeyClose:!0,canOutsideClickClose:!0,isOpen:this.state.isOpenDrawer,position:T.Ly.RIGHT,usePortal:!0},G("div",{className:"bp3-drawer-header"},G(P.JO,{className:"bp3-icon",icon:"dot",iconSize:14,intent:(null===(a=this.state.chosenModel)||void 0===a?void 0:a.hash)===(null===(r=this.state.currentModel)||void 0===r?void 0:r.hash)?M.S.SUCCESS:M.S.DANGER}),G("h4",{className:"bp3-heading"},null===(o=this.state.chosenModel)||void 0===o?void 0:o.name),G(P.zx,{className:"bp3-dialog-close-button",minimal:!0,icon:"arrow-right",onClick:this.handleCloseDrawer})),G(P.wp,{className:B().DrawerNavbar},G(P.fT,{align:x.v.LEFT,className:B().DrawerNavbar},G(P.mQ,{id:"DrawerTabs",large:!0,onChange:this.handleDrawerTabChange,selectedTabId:this.state.drawerTabId,renderActiveTabPanelOnly:!0},G(P.OK,{id:"details",title:"Details"}),G(P.mQ.Expander,null)))),G("div",{className:v.$fE},G("div",null,"details"===this.state.drawerTabId?y:null)),G("div",{className:[v.e$L,v.bDx].join(" ")},G(P.zx,{type:"button",text:"Unload",disabled:(null===(s=this.state.chosenModel)||void 0===s?void 0:s.hash)!==(null===(i=this.state.currentModel)||void 0===i?void 0:i.hash)||this.state.isUnloadModelAPI,onClick:function(){g.setState({isConfirmUnload:!0})}}),G(P.J2,{interactionKind:P.V3.HOVER,content:G("div",{className:B().Section},"Delete")},G(P.zx,{type:"button",intent:M.S.DANGER,disabled:this.state.isAPIcalled,icon:"trash",onClick:function(){g.setState({isConfirmDelete:!0})}}))));return G(p().Fragment,null,G("div",{style:{maxWidth:"140px",minWidth:"140px"}},this.state.isLoadModelAPI?G(P.ko,null):G(P.J2,{className:B().PopOver,content:C,placement:"bottom",isOpen:!this.state.isOpenDrawer&&void 0,disabled:this.state.waitForRuntime&&!this.props.isConnected},G(P.u,{content:"Select a Model to Load",disabled:0===Object.keys(this.state.registeredModelList).length||!!this.state.currentModel,isOpen:!this.state.isOpenRegistraionForm&&!this.state.isOpenDrawer&&!this.state.currentModel&&Object.keys(this.state.registeredModelList).length>0||void 0},G(P.zx,{disabled:this.state.waitForRuntime&&!this.props.isConnected,className:this.state.waitForRuntime&&!this.props.isConnected?"bp3-skeleton":"",style:{minWidth:"140px",alignContent:"left"},alignText:x.v.LEFT,minimal:!0,rightIcon:"caret-down",text:void 0!==this.state.currentModel?this.formatLongStringName(this.state.currentModel.name,15):"Load Model.."})))),G(P.J2,{content:G(p().Fragment,null,G(P.wp,{className:B().DrawerNavbar},G(P.fT,{align:x.v.LEFT,className:B().DrawerNavbar},G(P.mQ,{id:"RegisterationTabs",large:!1,onChange:this.handleRegistrationTabChange,selectedTabId:this.state.registrationTabId,renderActiveTabPanelOnly:!0},G(P.OK,{id:"local",title:"Local"}),G(P.OK,{id:"hub",title:"Datature Hub"}),G(P.OK,{id:"endpoint",title:"Datature API (Coming Soon)",disabled:!0}),G(P.mQ.Expander,null)))," "),G("div",{className:v.$fE},A)),placement:"left-end",onOpening:function(){return g.setState({isOpenRegistraionForm:!0})},onClosed:function(){g.setState({generalIcon:void 0,formData:{type:"local",modelType:"autodetect",name:"",description:"",directory:"",modelKey:"",projectSecret:"",modelURL:""},registrationTabId:"local",isOpenRegistraionForm:!1})}},G(P.u,{disabled:Object.keys(this.state.registeredModelList).length>0,content:"Add a Model Here",isOpen:0===Object.keys(this.state.registeredModelList).length},G(P.zx,{minimal:!0,icon:"plus"}))),S,G(P.bZ,{isOpen:this.state.isConfirmLoad,intent:M.S.WARNING,icon:"warning-sign",loading:this.state.isLoadModelAPI,onCancel:function(){return g.setState({isConfirmLoad:!1})},onConfirm:this.handleUnloadAndLoadModel,cancelButtonText:"Cancel",confirmButtonText:"I Understand",className:this.props.useDarkTheme?"bp3-dark":""},this.state.currentModel?G("div",null,"We will unload ",this.state.currentModel.name," and load"," ",null===(l=this.state.chosenModel)||void 0===l?void 0:l.name,". Are you sure you want to continue?"):G("div",null,"Confirm that you want to load ",null===(c=this.state.chosenModel)||void 0===c?void 0:c.name,".")),G(P.bZ,{isOpen:this.state.isConfirmUnload,intent:M.S.WARNING,icon:"warning-sign",loading:this.state.isUnloadModelAPI,onCancel:function(){return g.setState({isConfirmUnload:!1})},onConfirm:this.handleUnloadModel,cancelButtonText:"Cancel",confirmButtonText:"I Understand",className:this.props.useDarkTheme?"bp3-dark":""},G("div",null,"We will unload ",null===(d=this.state.currentModel)||void 0===d?void 0:d.name,". Are you sure you want to continue?")),G(P.bZ,{isOpen:this.state.isConfirmDelete,intent:M.S.WARNING,icon:"warning-sign",loading:this.state.isAPIcalled,onCancel:function(){return g.setState({isConfirmDelete:!1})},onConfirm:this.handleDeleteModel,cancelButtonText:"Cancel",confirmButtonText:"I Understand",className:this.props.useDarkTheme?"bp3-dark":""},(null===(u=this.state.currentModel)||void 0===u?void 0:u.hash)===(null===(h=this.state.chosenModel)||void 0===h?void 0:h.hash)?G("div",null,"This model is loaded. We will unload and delete"," ",null===(f=this.state.currentModel)||void 0===f?void 0:f.name,". Are you sure you want to continue?"):G("div",null,"Confirm that you want to delete ",null===(m=this.state.chosenModel)||void 0===m?void 0:m.name,".")))}}]),n}(p().Component),J=p().createElement;function U(e){var t,n=(0,f.useState)(!1),a=n[0],r=n[1],o=0,s=!1,i=e.isConnected,l=function(){var n;(n=O()(),A().get(y.JA+y.MV,{params:{isElectron:n}})).then((function(n){var l=n.data.hasCache&&!n.data.isCacheCalled;e.callbacks.HandleHasCache(l),i||(e.callbacks.HandleIsConnected(!0),i=!0,e.callbacks.HandleElectronGPUListener()),t&&(0,Z.wA)(t),s||(s=!0),o=0,a&&r(!1)})).catch((function(){if(s&&!O()()){t&&(0,Z.wA)(t),(0,Z.JJ)("Portal runtime is unresponsive. Restart server.",M.S.WARNING,25e3,"outdated")}else if(s||0!==o){if((o>=1&&!s||s)&&O()()){var n={onClick:function(){r(!0),(0,Z.M4)(),window.require("electron").ipcRenderer.send("restart-server")},text:"Restart?"};t&&(0,Z.wA)(t),(0,Z.JJ)("Portal runtime is unresponsive.",M.S.WARNING,25e3,"outdated",n)}}else{var a=J(p().Fragment,null,J(P.$j,{size:15,className:"bp3-icon"}));t=(0,Z.JJ)("Waiting for runtime to load",M.S.PRIMARY,0,a)}o+=1,e.isConnected&&(e.callbacks.HandleIsConnected(!1),i=!1)}))};return(0,f.useEffect)((function(){l();var e=setInterval(l,3e4);return function(){return clearInterval(e)}}),[a]),J(p().Fragment,null)}var W=f.createElement;function H(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var r=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return(0,u.Z)(this,n)}}var z=function(e){(0,d.Z)(n,e);var t=H(n);function n(e){return(0,i.Z)(this,n),t.call(this,e)}return(0,l.Z)(n,[{key:"render",value:function(){var e=this;return W(f.Fragment,null,W(P.cw,{label:W("b",null,"Interface")},W(P.rs,{label:"Dark Mode",defaultChecked:this.props.GlobalSetting.useDarkTheme,onChange:function(t){e.props.GlobalSettingCallback.setTheme(t.target.checked)}})),W(P.cw,{label:W("b",null,"Proccessor")},W(P.u,{disabled:O()(),content:this.props.GlobalSetting.isGPU?"Exclude the --gpu flag to run in cpu mode":"Add the --gpu flag to run the server on GPU",position:T.Ly.BOTTOM},W(P.rs,{disabled:!O()(),label:"Run on GPU",checked:this.props.GlobalSetting.isGPU,onChange:function(t){e.props.callbacks.OpenProcessorAlert(t.target.checked)}}))),W(P.cw,{label:W("b",null,"Autosave")},W(P.rs,{label:"Autosave Progress",checked:this.props.GlobalSetting.isAutosave,onChange:function(t){e.props.GlobalSettingCallback.setAutosave(t.target.checked)}})))}}]),n}(f.Component),K=f.createElement;function V(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var r=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return(0,u.Z)(this,n)}}var q=function(e){(0,d.Z)(n,e);var t=V(n);function n(e){var a;return(0,i.Z)(this,n),a=t.call(this,e),(0,b.Z)((0,c.Z)(a),"componentDidMount",(function(){O()()&&window.require("electron").ipcRenderer.on("restart-server-reply",a.handleElectronGPUListener)})),(0,b.Z)((0,c.Z)(a),"componentWillUnmount",(function(){O()()&&window.require("electron").ipcRenderer.removeListener("restart-server-reply",a.handleElectronGPUListener)})),(0,b.Z)((0,c.Z)(a),"handleElectronGPUListener",(0,s.Z)(o().mark((function e(){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,k().then((function(e){0===e.data?a.props.GlobalSettingCallback.setGPU(!0):a.props.GlobalSettingCallback.setGPU(!1)}));case 2:a.setState({isChangingProcessor:!1,changeProcessor:!1});case 3:case"end":return e.stop()}}),e)})))),(0,b.Z)((0,c.Z)(a),"openProcessorAlert",(function(){a.setState({changeProcessor:!0})})),(0,b.Z)((0,c.Z)(a),"handleChangeProcessor",(0,s.Z)(o().mark((function e(){var t;return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(a.setState({isChangingProcessor:!0}),!a.props.GlobalSetting.isGPU){e.next=6;break}return e.next=4,A().post(y.JA+y.QV).catch((function(e){var t="Failed to clear gpu";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 4:e.next=8;break;case 6:return e.next=8,A().post(y.JA+y.Gz).catch((function(e){var t="Failed to set gpu";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 8:return e.next=10,n=void 0,A().get(y.JA+y.ZW,{params:w({},n?{deleteCache:n}:{})});case 10:t=window.require("electron"),t.ipcRenderer.send("restart-server");case 12:case"end":return e.stop()}var n}),e)})))),(0,b.Z)((0,c.Z)(a),"handleLoadCache",(0,s.Z)(o().mark((function e(){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a.setState({isAPICalled:!0}),e.next=3,A().post(y.JA+y.xy).then((function(){a.setState({hasCache:!1}),window.location.reload(!1)})).catch((function(e){var t="Failed to load cache.";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 3:a.setState({isAPICalled:!1});case 4:case"end":return e.stop()}}),e)})))),(0,b.Z)((0,c.Z)(a),"handleRejectCache",(0,s.Z)(o().mark((function e(){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a.setState({isAPICalled:!0}),e.next=3,A().put(y.JA+y.xy).then((function(){a.setState({hasCache:!1})})).catch((function(e){var t="Failed to reject cache.";e.response&&(t="".concat(e.response.data.message)),(0,Z.JJ)(t,M.S.DANGER,3e3)}));case 3:a.setState({isAPICalled:!1});case 4:case"end":return e.stop()}}),e)})))),(0,b.Z)((0,c.Z)(a),"isProjectBoard",(function(){return"project"===a.state.urlPath.split("/")[1]})),a.state={isChangingProcessor:!1,changeProcessor:!1,urlPath:"",hasCache:!1,isAPICalled:!1},a}return(0,l.Z)(n,[{key:"render",value:function(){var e=this;return K(f.Fragment,null,K(P.wp,null,K(P.fT,{align:x.v.LEFT},K(P.AN,{icon:K($,null),minimal:!0,onClick:function(){C.default.push({pathname:"/"})}}),K("span",{className:"bp3-navbar-divider"})),K(P.fT,{align:x.v.RIGHT},K("span",{className:"bp3-navbar-divider"}),K(j,(0,a.Z)({},this.props.GlobalSetting,{callbacks:{HandleModelChange:this.props.GlobalSettingCallback.handleModelChange}})),K("span",{className:"bp3-navbar-divider"}),K(P.zx,{style:{userSelect:"none",minWidth:"max-content"},className:"bp3-button bp3-minimal",onClick:function(){window.location="https://joindatature.slack.com/join/shared_invite/zt-hv9xv84h-WYDFnU1clNM0eGW4SfQGGg#/"}},"Community Slack"),K("span",{className:"bp3-navbar-divider"}),K(P.J2,{popoverClassName:v.lik,forceFocus:!1,position:"bottom-right",content:K(z,(0,a.Z)({},this.props,{callbacks:{OpenProcessorAlert:this.openProcessorAlert}}))},K(P.zx,{icon:"cog",className:"bp3-button bp3-minimal"})),K(P.zx,{icon:"help",className:"bp3-button bp3-minimal",onClick:function(){window.open("https://docs.datature.io/portal")}}))),K(U,{isConnected:this.props.GlobalSetting.isConnected,callbacks:{HandleHasCache:function(t){e.setState({hasCache:t})},HandleIsConnected:this.props.GlobalSettingCallback.handleIsConnected,HandleElectronGPUListener:this.handleElectronGPUListener}}),K(P.bZ,{isOpen:this.state.changeProcessor,intent:M.S.PRIMARY,icon:"warning-sign",loading:this.state.isChangingProcessor,onCancel:function(){return e.setState({changeProcessor:!1})},onConfirm:this.handleChangeProcessor,cancelButtonText:"No",confirmButtonText:"Yes",className:this.props.GlobalSetting.useDarkTheme?"bp3-dark":""},K("div",null,"To change the processor to"," ",this.props.GlobalSetting.isGPU?"CPU":"GPU",". The server has to restart. Do you wish to continue?")),K(P.bZ,{isOpen:this.state.hasCache,intent:M.S.PRIMARY,icon:"history",loading:this.state.isAPICalled,onCancel:this.handleRejectCache,onConfirm:this.handleLoadCache,cancelButtonText:"No",confirmButtonText:"Yes",className:this.props.GlobalSetting.useDarkTheme?"bp3-dark":""},K("div",null,"Unsaved session found. Would you like to resume from the previous session?")))}}]),n}(f.Component),$=function(){return K("svg",{width:"30",height:"30",viewBox:"0 0 512 512",className:"NexusLogo"},K("rect",{style:{fill:"#fff"},x:"94",y:"181",width:"80",height:"80"}),K("rect",{id:"Rectangle_1_copy_3","data-name":"Rectangle 1 copy 3",style:{fill:"#fff"},x:"94",y:"354",width:"80",height:"80"}),K("rect",{id:"Rectangle_1_copy","data-name":"Rectangle 1 copy",style:{fill:"#fff"},x:"173",y:"100",width:"244",height:"80"}),K("rect",{id:"Rectangle_1_copy-2","data-name":"Rectangle 1 copy",style:{fill:"#fff"},x:"94",y:"283",width:"252",height:"71"}),K("rect",{id:"Rectangle_1_copy-3","data-name":"Rectangle 1 copy",style:{fill:"#fff"},x:"346",y:"100",width:"71",height:"183"}))},Q=p().createElement;function Y(e){var t=function(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,a=(0,h.Z)(e);if(t){var r=(0,h.Z)(this).constructor;n=Reflect.construct(a,arguments,r)}else n=a.apply(this,arguments);return(0,u.Z)(this,n)}}var X="nexus-theme",ee=(0,g.default)((function(){return Promise.all([n.e(662),n.e(269),n.e(3),n.e(607)]).then(n.bind(n,4607))}),{ssr:!1,loadableGenerated:{webpack:function(){return[4607]},modules:["index.js -> ../src/components/annotations/annotator.tsx"]}}),te=function(e){(0,d.Z)(n,e);var t=Y(n);function n(e){var a;return(0,i.Z)(this,n),(a=t.call(this,e)).state={isGPU:!1,useDarkTheme:!0,loadedModel:void 0,isConnected:!1,isAutosave:!1},(0,F.Dg)({gutterWidth:12}),a.setTheme=a.setTheme.bind((0,c.Z)(a)),a.setGPU=a.setGPU.bind((0,c.Z)(a)),a.setAutosave=a.setAutosave.bind((0,c.Z)(a)),a}return(0,l.Z)(n,[{key:"componentDidMount",value:function(){var e=this,t=localStorage.getItem(X);this.setState({useDarkTheme:null==t||"true"===t}),k().then((function(t){0===t.data&&e.setState({isGPU:!0})})),A().get(y.JA+y.MK).then((function(t){1===t.data&&e.setState({isAutosave:!0})}))}},{key:"setTheme",value:function(e){localStorage.setItem(X,e),this.setState({useDarkTheme:e})}},{key:"setGPU",value:function(){var e=(0,s.Z)(o().mark((function e(t){return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:this.setState({isGPU:t});case 1:case"end":return e.stop()}}),e,this)})));return function(t){return e.apply(this,arguments)}}()},{key:"setAutosave",value:function(){var e=(0,s.Z)(o().mark((function e(t){var n=this;return o().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:E(t).then((function(e){200===e.status&&n.setState({isAutosave:t})}));case 1:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()},{key:"render",value:function(){var e=this;return Q(p().Fragment,null,Q(m.default,null,Q("title",null,"Portal"),Q("link",{rel:"icon",type:"image/x-icon",href:"./portal-ico-dark.png",media:"(prefers-color-scheme:dark)"}),Q("link",{rel:"icon",type:"image/x-icon",href:"./portal-ico-light.png",media:"(prefers-color-scheme:light)"}),Q("link",{rel:"stylesheet",href:"https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"}),Q("link",{rel:"stylesheet",href:"https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.3/leaflet.draw.css"}),Q("link",{href:"./static/style/annotation.css",rel:"stylesheet"}),Q("link",{href:this.state.useDarkTheme?"./static/style/global-dark.css":"./static/style/global-light.css",rel:"stylesheet"})),Q("div",{className:this.state.useDarkTheme?v.Pyr:""},Q(q,{active:"Annotations",GlobalSetting:this.state,GlobalSettingCallback:{setTheme:this.setTheme,setGPU:this.setGPU,setAutosave:this.setAutosave,handleIsConnected:function(t){e.setState({isConnected:t})},handleModelChange:function(t){e.setState({loadedModel:t})}}}),Q(ee,(0,a.Z)({project:this.props.projectID},this.props,this.state))))}}]),n}(p().Component),ne=function(e){return Q(te,(0,a.Z)({projectID:"906969446527476eefc2d2062897f92d"},e))}},7316:function(e,t,n){"use strict";n.d(t,{lp:function(){return c},_q:function(){return d},nW:function(){return u},Ng:function(){return h},T:function(){return f},Q3:function(){return p},kE:function(){return m},Ge:function(){return g},kV:function(){return v},Z8:function(){return F},Ey:function(){return b},G$:function(){return C},yl:function(){return D},PF:function(){return A},ym:function(){return y},hu:function(){return S},Ig:function(){return w},pF:function(){return E}});var a=n(6265),r=n(9669),o=n.n(r),s=n(2875);function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=i)&&Object.keys(n.O).every((function(e){return n.O[e](r[c])}))?r.splice(c--,1):(a=!1,i0&&e[f-1][2]>i;f--)e[f]=e[f-1];e[f]=[r,o,i]}}(),n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.f={},n.e=function(e){return Promise.all(Object.keys(n.f).reduce((function(t,r){return n.f[r](e,t),t}),[]))},n.u=function(e){return"static/chunks/"+({269:"0b7b90cd",662:"29107295"}[e]||e)+"."+{3:"dac82d28ef46f0b163d8",269:"92b8a6d99817c87d21b6",607:"576e9e84426511ff810c",662:"2648cb5e919f7c78c7cc"}[e]+".js"},n.miniCssF=function(e){return"static/css/"+{405:"5441740d7d3b11650f51",607:"ea6ce45697ea9055b31d",888:"ca4d9efbce0c6147795e"}[e]+".css"},n.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}(),n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e={},t="_N_E:";n.l=function(r,o,i,u){if(e[r])e[r].push(o);else{var a,c;if(void 0!==i)for(var f=document.getElementsByTagName("script"),l=0;l=i)&&Object.keys(n.O).every((function(e){return n.O[e](r[c])}))?r.splice(c--,1):(a=!1,i0&&e[f-1][2]>i;f--)e[f]=e[f-1];e[f]=[r,o,i]}}(),n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.f={},n.e=function(e){return Promise.all(Object.keys(n.f).reduce((function(t,r){return n.f[r](e,t),t}),[]))},n.u=function(e){return"static/chunks/"+({269:"0b7b90cd",662:"29107295"}[e]||e)+"."+{3:"dac82d28ef46f0b163d8",269:"92b8a6d99817c87d21b6",607:"9f07b963d28c2ca7e4ae",662:"2648cb5e919f7c78c7cc"}[e]+".js"},n.miniCssF=function(e){return"static/css/"+{405:"5441740d7d3b11650f51",607:"ea6ce45697ea9055b31d",888:"ca4d9efbce0c6147795e"}[e]+".css"},n.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}(),n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){var e={},t="_N_E:";n.l=function(r,o,i,u){if(e[r])e[r].push(o);else{var a,c;if(void 0!==i)for(var f=document.getElementsByTagName("script"),l=0;lヽ(ಠ_ಠ)ノ: Something broke. Click <a href="/">here</a> to try again

ヽ(ಠ_ಠ)ノ

Something broke. Click here to try again.

\ No newline at end of file +ヽ(ಠ_ಠ)ノ: Something broke. Click <a href="/">here</a> to try again

ヽ(ಠ_ಠ)ノ

Something broke. Click here to try again.

\ No newline at end of file diff --git a/portal_build/out/index.html b/portal_build/out/index.html index c8a48b37..0f3df54b 100644 --- a/portal_build/out/index.html +++ b/portal_build/out/index.html @@ -1 +1 @@ -Portal
\ No newline at end of file +Portal
\ No newline at end of file diff --git a/portal_build/out/loading.html b/portal_build/out/loading.html index 7e3736c5..be6d4a15 100644 --- a/portal_build/out/loading.html +++ b/portal_build/out/loading.html @@ -51,4 +51,4 @@ box-shadow: 0 0 0 35px rgba(0, 0, 0, 0); } } -
> Initializing Portal Engine ..
\ No newline at end of file +
> Initializing Portal Engine ..
\ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 5f13cd38..484e02da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,6 @@ Flask-Cors==3.0.10 Flask-RESTful==0.3.9 Flask-SocketIO==5.1.0 jsonpickle==2.0.0 -numpy==1.21.6 opencv-python==4.7.0.72 Pillow==9.5.0 scandir==1.10.0 diff --git a/setup-virtualenv.sh b/setup-virtualenv.sh index fc7ee92a..aa68b78a 100755 --- a/setup-virtualenv.sh +++ b/setup-virtualenv.sh @@ -37,13 +37,8 @@ cp ./Pipfile ./portal_build cd ./portal_build echo "Installing Python Environment in portal_build..." echo "$OSTYPE" -if [[ "$OSTYPE" == "msys" ]]; then - python -m pip install --upgrade pip - python -m pip install pipenv -else - python3 -m pip install --upgrade pip - python3 -m pip install pipenv -fi +python3 -m pip install --upgrade pip +python3 -m pip install pipenv PIPENV_VENV_IN_PROJECT=1 PIPENV_DEFAULT_PYTHON_VERSION=3.9 pipenv sync -d cd .. diff --git a/src/app/package-lock.json b/src/app/package-lock.json index 909b8dd5..e4b03c3a 100644 --- a/src/app/package-lock.json +++ b/src/app/package-lock.json @@ -1,12 +1,12 @@ { "name": "portal", - "version": "0.5.8", + "version": "0.5.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "portal", - "version": "0.5.8", + "version": "0.5.9", "dependencies": { "@babel/plugin-proposal-optional-chaining": "^7.12.7", "@blueprintjs/core": "^3.44.2", diff --git a/src/app/package.json b/src/app/package.json index 2580b4fe..2cffa899 100644 --- a/src/app/package.json +++ b/src/app/package.json @@ -1,6 +1,6 @@ { "name": "portal", - "version": "0.5.8", + "version": "0.5.9", "author": "Datature", "private": true, "main": "main.js", diff --git a/src/engine/run.py b/src/engine/run.py index 4b396df4..9fb30d77 100644 --- a/src/engine/run.py +++ b/src/engine/run.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,18 +8,19 @@ @File : run.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Main file to run the flask app. -''' +""" + +import os # Ignore due to Pyshell # pylint: disable=E0401, E0611 import sys -import os - import webbrowser + from flask import send_from_directory from flask_cors import cross_origin @@ -81,7 +82,7 @@ os.environ["USE_CACHE_DIR"] = use_cache_dir # pylint: disable=wrong-import-position -from server import server, app, global_store # noqa: E402 +from server import app, global_store, server # noqa: E402 if os.getenv("COMMAND_LINE"): diff --git a/src/engine/server/__init__.py b/src/engine/server/__init__.py index bb48dfa7..888f021f 100644 --- a/src/engine/server/__init__.py +++ b/src/engine/server/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : __init__.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module to set up the Flask app and import the routes. -''' +""" import os import threading import time @@ -31,11 +31,14 @@ IDLE_MINUTES = 60 * 5 CACHE_OPTION = os.environ["USE_CACHE"] == "1" try: - DEBUG_MODE = (int(os.environ["PORTAL_LOGGING"]) - if "PORTAL_LOGGING" in os.environ else None) + DEBUG_MODE = ( + int(os.environ["PORTAL_LOGGING"]) if "PORTAL_LOGGING" in os.environ else None + ) except ValueError as e: - raise ValueError("invalid literal for PORTAL_LOGGING variable.\n" - "Only 1, 2, 3, 4, 5 are accepted.") from e + raise ValueError( + "invalid literal for PORTAL_LOGGING variable.\n" + "Only 1, 2, 3, 4, 5 are accepted." + ) from e if DEBUG_MODE is not None: # pylint: disable=wrong-import-position import logging @@ -50,8 +53,10 @@ logging.basicConfig(level=DEBUG_MODE * 10) logger = logging.getLogger(__name__) except ValueError as e: - raise ValueError("invalid literal for PORTAL_LOGGING variable.\n" - "Only 1, 2, 3, 4, 5 are accepted.") from e + raise ValueError( + "invalid literal for PORTAL_LOGGING variable.\n" + "Only 1, 2, 3, 4, 5 are accepted." + ) from e else: logger = None @@ -81,9 +86,7 @@ def run(self): # pylint: disable=invalid-name app = Flask(__name__) server = ServerThread(app) -global_store = GlobalStore(MODEL_LOAD_LIMIT, - IDLE_MINUTES, - caching_system=CACHE_OPTION) +global_store = GlobalStore(MODEL_LOAD_LIMIT, IDLE_MINUTES, caching_system=CACHE_OPTION) def wait_for_process() -> None: diff --git a/src/engine/server/models/abstract/BaseModel.py b/src/engine/server/models/abstract/BaseModel.py index 7945b3e7..27bf7d9e 100644 --- a/src/engine/server/models/abstract/BaseModel.py +++ b/src/engine/server/models/abstract/BaseModel.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : BaseModel.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the BaseModel Implementation -''' +""" from server.services.errors import Errors, PortalError @@ -87,7 +87,8 @@ def _load_label_map_(self): """ raise NotImplementedError( "Using the BaseModel implementation of _load_label_map_." - "Please also implement this in your custom model class.") + "Please also implement this in your custom model class." + ) @classmethod def register(self): @@ -105,7 +106,8 @@ def register(self): """ raise NotImplementedError( "Using the BaseModel implementation of register." - "Please also implement this in your custom model class.") + "Please also implement this in your custom model class." + ) @classmethod def load(self): @@ -117,7 +119,8 @@ def load(self): """ raise NotImplementedError( "Using the BaseModel implementation of load." - "Please also implement this in your custom model class.") + "Please also implement this in your custom model class." + ) @classmethod def predict(self, image_array): @@ -141,4 +144,5 @@ def predict(self, image_array): """ raise NotImplementedError( "Using the BaseModel implementation of predict." - "Please also implement this in your custom model class.") + "Please also implement this in your custom model class." + ) diff --git a/src/engine/server/models/abstract/Model.py b/src/engine/server/models/abstract/Model.py index 0f01a8e8..96c36446 100644 --- a/src/engine/server/models/abstract/Model.py +++ b/src/engine/server/models/abstract/Model.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,20 +8,19 @@ @File : Model.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the factory function -''' +""" -from server.models.tensorflow_model import TensorflowModel +from server.models.autodetect_model import AutoDetectModel from server.models.darknet_model import DarknetModel from server.models.endpoint_model import EndpointModel -from server.models.autodetect_model import AutoDetectModel +from server.models.tensorflow_model import TensorflowModel -def Model(model_type: str, directory: str, name: str, description: str, - **kwargs): +def Model(model_type: str, directory: str, name: str, description: str, **kwargs): """Factory function that routes the model to the specific class.""" args = [model_type, directory, name, description] diff --git a/src/engine/server/models/autodetect_model.py b/src/engine/server/models/autodetect_model.py index 619d7735..e0aad231 100644 --- a/src/engine/server/models/autodetect_model.py +++ b/src/engine/server/models/autodetect_model.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : autodetect_model.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the AutoDetect Model class. -''' +""" import os import sys @@ -108,16 +108,14 @@ class AutoDetectModel(BaseModel): def _load_label_map_(self): """Overloaded from Parent Class.""" self._label_map_ = {} - label_file = ("label.txt" - if self._model_type_ == "tflite" else "label_map.pbtxt") - with open(os.path.join(self._directory_, label_file), - "r", - encoding="utf-8") as label_file: + label_file = "label.txt" if self._model_type_ == "tflite" else "label_map.pbtxt" + with open( + os.path.join(self._directory_, label_file), "r", encoding="utf-8" + ) as label_file: for line in label_file: if "id" in line: label_index = int(line.split(":")[-1]) - label_name = ( - next(label_file).split(":")[-1].strip().strip("'")) + label_name = next(label_file).split(":")[-1].strip().strip("'") self._label_map_[str(label_index)] = { "id": label_index, "name": label_name, @@ -128,13 +126,14 @@ def register(self): folder_contents = os.listdir(self._directory_) try: self._model_type_, self._model_path_ = infer_model_type_and_path( - self._directory_, folder_contents) + self._directory_, folder_contents + ) except Exception as e: raise PortalError(Errors.INVALIDTYPE, str(e)) from e self._height_, self._width_, info_line = infer_input_details( - os.path.join(self._directory_, "predict.py")) - self._model_format_ = next( - (x for x in MODEL_FORMATS if x in info_line), None) + os.path.join(self._directory_, "predict.py") + ) + self._model_format_ = next((x for x in MODEL_FORMATS if x in info_line), None) self._load_label_map_() self._key_ = get_hash(self._directory_) return self._key_, self @@ -144,9 +143,11 @@ def load(self): sys.path.append(self._directory_) if self._model_type_ == "pytorch": import torch + self._model_ = torch.load(self._model_path_) elif self._model_type_ == "onnx": import onnxruntime as ort + self._model_ = ort.InferenceSession(self._model_path_) if self._model_format_ == "instance": self._input_name = self._model_.get_inputs()[0].name @@ -164,34 +165,40 @@ def load(self): self._output_name = list(self._model_.structured_outputs.keys())[0] elif self._model_type_ == "yolov8": from ultralytics import YOLO + self._model_ = YOLO(self._model_path_) def predict(self, image_array): """Overloaded from Parent Class.""" try: if self._model_type_ == "yolov8": - return yolov8_predict(self._model_, image_array, - (self._height_, self._width_)) + return yolov8_predict( + self._model_, image_array, (self._height_, self._width_) + ) image_array = np.expand_dims( np.array( - Image.fromarray(image_array).resize( - (self._width_, self._height_))).astype(np.float32), 0) + Image.fromarray(image_array).resize((self._width_, self._height_)) + ).astype(np.float32), + 0, + ) if self._model_type_ == "onnx": - detections_output = onnx_predict(self._model_, - self._model_format_, - self._input_name, - self._output_name, - image_array) + detections_output = onnx_predict( + self._model_, + self._model_format_, + self._input_name, + self._output_name, + image_array, + ) elif self._model_type_ == "tflite": - detections_output = tflite_predict(self._model_, - self._model_format_, - image_array) + detections_output = tflite_predict( + self._model_, self._model_format_, image_array + ) elif self._model_type_ == "pytorch": detections_output = torch_predict(self._model_, image_array) elif self._model_type_ == "tensorflow": - detections_output = tf_predict(self._model_, - self._model_format_, - self._output_name, image_array) + detections_output = tf_predict( + self._model_, self._model_format_, self._output_name, image_array + ) return self.postprocess(detections_output) except Exception as e: raise PortalError(Errors.FAILEDPREDICTION, str(e)) from e @@ -214,7 +221,8 @@ def postprocess(self, detections_output): elif self._model_format_ == "semantic": mask_list, bbox_list, class_list, scores_list = get_polygons( - detections_output) + detections_output + ) bboxes = np.array(bbox_list) classes = np.array(class_list) masks = np.array(mask_list) @@ -228,8 +236,8 @@ def postprocess(self, detections_output): bboxes = bboxes[0] masks = masks[0] image_masks = reframe_box_masks_to_image_masks( - tf.convert_to_tensor(masks), bboxes, self._height_, - self._width_) + tf.convert_to_tensor(masks), bboxes, self._height_, self._width_ + ) image_masks = tf.cast(image_masks > 0.5, tf.uint8).numpy() detections["detection_masks"] = image_masks diff --git a/src/engine/server/models/darknet_model.py b/src/engine/server/models/darknet_model.py index 4b57301c..0043a3da 100644 --- a/src/engine/server/models/darknet_model.py +++ b/src/engine/server/models/darknet_model.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,34 +8,33 @@ @File : darknet_model.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the Darknet Model class. -''' +""" import os import cv2 import numpy as np - +from server.models.abstract.BaseModel import BaseModel from server.services.errors import Errors, PortalError from server.services.hashing import get_hash -from server.models.abstract.BaseModel import BaseModel - class DarknetModel(BaseModel): """Implementation of the Darknet Model.""" def _load_label_map_(self): """Overloaded from Parent Class.""" - labels = (open(os.path.join( - self._directory_, self._labelsname_)).read().strip().split("\n")) + labels = ( + open(os.path.join(self._directory_, self._labelsname_)) + .read() + .strip() + .split("\n") + ) self._label_map_ = { - str(label_index): { - "id": label_index, - "name": label_name - } + str(label_index): {"id": label_index, "name": label_name} for label_index, label_name in enumerate(labels) } @@ -60,24 +59,21 @@ def register(self): "class label file .names is not found in given directory.", ) if labels > 1: - raise PortalError(Errors.OVERLOADED, - "multiple class label files found.") + raise PortalError(Errors.OVERLOADED, "multiple class label files found.") if self._weightsname_ == "": raise PortalError( Errors.INVALIDFILEPATH, "weights file .weights is not found in given directory", ) if weights > 1: - raise PortalError(Errors.OVERLOADED, - "multiple weights label files found.") + raise PortalError(Errors.OVERLOADED, "multiple weights label files found.") if self._configname_ == "": raise PortalError( Errors.INVALIDFILEPATH, "config file .cfg is not found in given directory.", ) if configs > 1: - raise PortalError(Errors.OVERLOADED, - "multiple config files found.") + raise PortalError(Errors.OVERLOADED, "multiple config files found.") with open(self._configname_, "r") as conf: heightcheck = False widthcheck = False @@ -86,11 +82,13 @@ def register(self): break if "height" in line: self._height_ = int( - line.replace("=", "").replace("height", "").strip()) + line.replace("=", "").replace("height", "").strip() + ) heightcheck = True if "width" in line: self._width_ = int( - line.replace("=", "").replace("width", "").strip()) + line.replace("=", "").replace("width", "").strip() + ) widthcheck = True self._load_label_map_() self._key_ = get_hash(self._directory_) @@ -98,8 +96,7 @@ def register(self): def load(self): """Overloaded from Parent Class.""" - loaded_model = cv2.dnn.readNetFromDarknet(self._configname_, - self._weightsname_) + loaded_model = cv2.dnn.readNetFromDarknet(self._configname_, self._weightsname_) self._model_ = loaded_model def predict(self, image_array): diff --git a/src/engine/server/models/endpoint_model.py b/src/engine/server/models/endpoint_model.py index 900edaad..e7587d95 100644 --- a/src/engine/server/models/endpoint_model.py +++ b/src/engine/server/models/endpoint_model.py @@ -8,7 +8,7 @@ @File : endpoint_model.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the Endpoint Model class. diff --git a/src/engine/server/models/model_utils/__init__.py b/src/engine/server/models/model_utils/__init__.py index 9f2dd961..ef052a77 100644 --- a/src/engine/server/models/model_utils/__init__.py +++ b/src/engine/server/models/model_utils/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,15 +8,22 @@ @File : __init__.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Model utilities init file. -''' +""" from .predict import ( # noqa: F401 - onnx_predict, tf_predict, tflite_predict, torch_predict, yolov8_predict, + onnx_predict, + tf_predict, + tflite_predict, + torch_predict, + yolov8_predict, ) from .utils import ( # noqa: F401 - MODEL_FORMATS, get_polygons, infer_input_details, - infer_model_type_and_path, reframe_box_masks_to_image_masks, + MODEL_FORMATS, + get_polygons, + infer_input_details, + infer_model_type_and_path, + reframe_box_masks_to_image_masks, ) diff --git a/src/engine/server/models/model_utils/utils.py b/src/engine/server/models/model_utils/utils.py index e0d6e5a3..05444507 100644 --- a/src/engine/server/models/model_utils/utils.py +++ b/src/engine/server/models/model_utils/utils.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : utils.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing utilities for models. -''' +""" import ast import os from typing import List, Tuple @@ -20,7 +20,7 @@ import cv2 import numpy as np import tensorflow as tf -from server.services.global_store import Errors, PortalError +from server.services.errors import Errors, PortalError MODEL_TYPES = { "yolov8": "yolov8", @@ -49,8 +49,7 @@ def infer_model_type_and_path(directory, folder_contents): model_path = os.path.join(directory, item) return val, model_path - raise PortalError(Errors.INVALIDTYPE, - "Detected Model Output Format Not Supported.") + raise PortalError(Errors.INVALIDTYPE, "Detected Model Output Format Not Supported.") def infer_input_details(prediction_script): @@ -74,16 +73,16 @@ def infer_input_details(prediction_script): lines = predictor_file.readlines() info_line = list(filter(lambda x: "@Desc" in x, lines))[0] height, width = ast.literal_eval( - list(filter(lambda x: "HEIGHT, WIDTH" in x, - lines))[0].replace("HEIGHT, WIDTH = ", "")) + list(filter(lambda x: "HEIGHT, WIDTH" in x, lines))[0].replace( + "HEIGHT, WIDTH = ", "" + ) + ) return height, width, info_line -def reframe_box_masks_to_image_masks(box_masks, - boxes, - image_height, - image_width, - resize_method="bilinear"): +def reframe_box_masks_to_image_masks( + box_masks, boxes, image_height, image_width, resize_method="bilinear" +): """Transforms the box masks back to full image masks. Embeds masks in bounding boxes of larger masks whose shapes correspond to image shape. @@ -121,9 +120,7 @@ def transform_boxes_relative_to_boxes(boxes, reference_boxes): box_masks_expanded = tf.expand_dims(box_masks, axis=3) num_boxes = tf.shape(box_masks_expanded)[0] - unit_boxes = tf.concat( - [tf.zeros([num_boxes, 2]), - tf.ones([num_boxes, 2])], 1) + unit_boxes = tf.concat([tf.zeros([num_boxes, 2]), tf.ones([num_boxes, 2])], 1) reverse_boxes = transform_boxes_relative_to_boxes(unit_boxes, boxes) resized_crops = tf.image.crop_and_resize( @@ -145,19 +142,19 @@ def transform_boxes_relative_to_boxes(boxes, reference_boxes): def get_polygons( - mask: np.ndarray -) -> (Tuple[List[np.ndarray], List[List[float]], List[int], List[float]]): + mask: np.ndarray, +) -> Tuple[List[np.ndarray], List[List[float]], List[int], List[float]]: """Convert AutoDetect Model semantic segmentation output to polygons. - Arguments: - mask: Probability map with shape [num_classes, height, width]. + Arguments: + mask: Probability map with shape [num_classes, height, width]. - Return: - Tuple containing polygon masks and their respective bounding boxes, - labels and confidences. + Return: + Tuple containing polygon masks and their respective bounding boxes, + labels and confidences. - NOTE: num_classes includes the background class indexed at 0. - This will be filtered out within this function. + NOTE: num_classes includes the background class indexed at 0. + This will be filtered out within this function. """ height = mask.shape[1] width = mask.shape[2] @@ -168,7 +165,8 @@ def get_polygons( # Step 2: for each class mask, convert to polygons normalized_mask = (mask - np.min(mask)) / (np.max(mask) - np.min(mask)) for class_id, (class_mask, normalized_class_mask) in enumerate( - zip(mask, normalized_mask)): + zip(mask, normalized_mask) + ): if class_id > 0: background_class = np.zeros_like(class_mask, np.uint8) @@ -185,10 +183,13 @@ def get_polygons( cv2.drawContours(instance, contours, cnt_id, 1, -1) total_area = np.count_nonzero(instance) total_score = np.sum( - normalized_class_mask[np.where(instance > 0)]) + normalized_class_mask[np.where(instance > 0)] + ) average_score = total_score / total_area - contour = tuple((cnt[0][1] / width, cnt[0][0] / height) - for cnt in contour.tolist()) + contour = tuple( + (cnt[0][1] / width, cnt[0][0] / height) + for cnt in contour.tolist() + ) y_coordinates, x_coordinates = zip(*contour) xmin = min(x_coordinates) ymin = min(y_coordinates) diff --git a/src/engine/server/models/tensorflow_model.py b/src/engine/server/models/tensorflow_model.py index ecca87cb..d60fad42 100644 --- a/src/engine/server/models/tensorflow_model.py +++ b/src/engine/server/models/tensorflow_model.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,24 +8,23 @@ @File : tensorflow_model.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the TensorFlow Model class. -''' +""" import os import cv2 import numpy as np import tensorflow as tf +from server.models.abstract.BaseModel import BaseModel +from server.models.model_utils import reframe_box_masks_to_image_masks # pylint: disable=E0401, E0611 from server.services.errors import Errors, PortalError from server.services.hashing import get_hash -from server.models.abstract.BaseModel import BaseModel -from server.models.model_utils import reframe_box_masks_to_image_masks - class TensorflowModel(BaseModel): """Implementation of the TensorFlow Model.""" @@ -34,14 +33,13 @@ def _load_label_map_(self): """Overloaded from Parent Class.""" self._label_map_ = {} with open( - os.path.join(self._directory_, "label_map.pbtxt"), - "r", + os.path.join(self._directory_, "label_map.pbtxt"), + "r", ) as label_file: for line in label_file: if "id" in line: label_index = int(line.split(":")[-1]) - label_name = ( - next(label_file).split(":")[-1].strip().strip("'")) + label_name = next(label_file).split(":")[-1].strip().strip("'") self._label_map_[str(label_index)] = { "id": label_index, "name": label_name, @@ -49,17 +47,19 @@ def _load_label_map_(self): def register(self): """Overloaded from Parent Class.""" - if not os.path.isfile(os.path.join(self._directory_, - "label_map.pbtxt")): + if not os.path.isfile(os.path.join(self._directory_, "label_map.pbtxt")): raise PortalError( Errors.INVALIDFILEPATH, "label_map.pbtxt is not found in given directory.", ) - if not (os.path.isfile( - os.path.join(self._directory_, "saved_model", - "saved_model.pbtxt")) or os.path.isfile( - os.path.join(self._directory_, "saved_model", - "saved_model.pb"))): + if not ( + os.path.isfile( + os.path.join(self._directory_, "saved_model", "saved_model.pbtxt") + ) + or os.path.isfile( + os.path.join(self._directory_, "saved_model", "saved_model.pb") + ) + ): raise PortalError( Errors.INVALIDFILEPATH, "saved_model/{saved_model.pb|saved_model.pbtxt} " @@ -75,7 +75,8 @@ def register(self): def load(self): """Overloaded from Parent Class.""" loaded_model = tf.saved_model.load( - os.path.join(self._directory_, "saved_model")) + os.path.join(self._directory_, "saved_model") + ) self._model_ = loaded_model def predict(self, image_array): @@ -88,7 +89,8 @@ def predict(self, image_array): cv2.resize( image_array, (self._height_, self._width_), - ))[tf.newaxis, ...] + ) + )[tf.newaxis, ...] try: detections = model(image_tensor) for key, value in detections.items(): @@ -97,7 +99,8 @@ def predict(self, image_array): box_masks = detections["detection_masks"] boxes = detections["detection_boxes"] image_masks = reframe_box_masks_to_image_masks( - tf.convert_to_tensor(box_masks), boxes, height, width) + tf.convert_to_tensor(box_masks), boxes, height, width + ) image_masks = tf.cast(image_masks > 0.5, tf.uint8).numpy() detections["detection_masks"] = image_masks return detections diff --git a/src/engine/server/routes/__init__.py b/src/engine/server/routes/__init__.py index 7b81172b..0f797a4b 100644 --- a/src/engine/server/routes/__init__.py +++ b/src/engine/server/routes/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,8 +8,8 @@ @File : __init__.py @Author : Marcus Neo and Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Init file for routes. -''' +""" diff --git a/src/engine/server/routes/routes.py b/src/engine/server/routes/routes.py index 5705644b..919f5f5c 100644 --- a/src/engine/server/routes/routes.py +++ b/src/engine/server/routes/routes.py @@ -8,7 +8,7 @@ @File : routes.py @Author : Marcus Neo and Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing all API routes. diff --git a/src/engine/server/services/__init__.py b/src/engine/server/services/__init__.py index 41404562..5f98d0c3 100644 --- a/src/engine/server/services/__init__.py +++ b/src/engine/server/services/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : .py @Author : Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the file encoder and decoder. -''' +""" from urllib.parse import quote, unquote ENCODING = "utf-8" diff --git a/src/engine/server/services/errors.py b/src/engine/server/services/errors.py index 7a2bc295..20b3ce60 100644 --- a/src/engine/server/services/errors.py +++ b/src/engine/server/services/errors.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,14 +8,14 @@ @File : errors.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : A service to deal with errors and exceptions -''' +""" import logging -from enum import Enum import traceback +from enum import Enum from flask import jsonify @@ -65,10 +65,7 @@ class PortalError(Exception): """Error class to handle the errors and exceptions thrown.""" # pylint: disable=super-init-not-called - def __init__(self, - error: Errors, - message: str, - fail_location: str = None) -> None: + def __init__(self, error: Errors, message: str, fail_location: str = None) -> None: """Initialize the PortalError class. :param error: An enum member of the Errors class. @@ -98,11 +95,13 @@ def output(self) -> tuple: print(traceback.format_exc()) logging.error(self._error_) return ( - jsonify({ - "error": self._error_, - "fail_location": self._fail_location_, - "message": self._message_, - "error_code": self._error_code_, - }), + jsonify( + { + "error": self._error_, + "fail_location": self._fail_location_, + "message": self._message_, + "error_code": self._error_code_, + } + ), self._status_, ) diff --git a/src/engine/server/services/filesystem/__init__.py b/src/engine/server/services/filesystem/__init__.py index 87e08094..89c678da 100644 --- a/src/engine/server/services/filesystem/__init__.py +++ b/src/engine/server/services/filesystem/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,8 +8,8 @@ @File : __init__.py @Author : Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Init script for filesystem services. -''' +""" diff --git a/src/engine/server/services/filesystem/file.py b/src/engine/server/services/filesystem/file.py index 105275f7..21029c1c 100644 --- a/src/engine/server/services/filesystem/file.py +++ b/src/engine/server/services/filesystem/file.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,13 +8,15 @@ @File : file.py @Author : Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Service to deal with file related functions. -''' +""" from io import BytesIO + import cv2 + # pylint: disable=E0401, E0611 from server.services.errors import Errors, PortalError @@ -56,8 +58,7 @@ def allowed_file(filename): :param filename: a string that is the name of the file :return: boolean (TRUE: Allowed; FALSE: Not Allowed) """ - return "." in filename and filename.rsplit( - ".", 1)[1].lower() in ALLOWED_EXTENSIONS + return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS def allowed_image(filename): @@ -67,8 +68,10 @@ def allowed_image(filename): :param filename: a string that is the name of the file :return: boolean (TRUE: Allowed; FALSE: Not Allowed) """ - return ("." in filename - and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS_IMAGE) + return ( + "." in filename + and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS_IMAGE + ) def allowed_video(filename): @@ -78,8 +81,10 @@ def allowed_video(filename): :param filename: a string that is the name of the file :return: boolean (TRUE: Allowed; FALSE: Not Allowed) """ - return ("." in filename - and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS_VIDEO) + return ( + "." in filename + and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS_VIDEO + ) def generate_thumbnail(path, filename): @@ -104,8 +109,7 @@ def generate_thumbnail(path, filename): res, image_ar = vcap.read() while image_ar.mean() < threshold and res: res, image_ar = vcap.read() - image_ar = cv2.resize(image_ar, (width, height), 0, 0, - cv2.INTER_LINEAR) + image_ar = cv2.resize(image_ar, (width, height), 0, 0, cv2.INTER_LINEAR) res, image_buf = cv2.imencode(".jpeg", image_ar) thumb_bytes = image_buf.tobytes() diff --git a/src/engine/server/services/filesystem/folder.py b/src/engine/server/services/filesystem/folder.py index 08801eec..27946191 100644 --- a/src/engine/server/services/filesystem/folder.py +++ b/src/engine/server/services/filesystem/folder.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : folder.py @Author : Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Service to deal with folder related class and functions -''' +""" import datetime import os @@ -57,8 +57,9 @@ def get_folders(self): def get_tree(self): """Create a list of filepaths within this folder.""" - return self._create_tree_(self._name_, self._path_, self._files_, - self._folders_) + return self._create_tree_( + self._name_, self._path_, self._files_, self._folders_ + ) def get_last_updated_time(self): """Obtained the last updated time of the folder.""" @@ -88,7 +89,8 @@ def update_folder(self, path, time): folder = item if path.startswith(folder.get_path()): self._folders_[index] = folder.update_folder( - path, datetime.datetime.utcnow()) + path, datetime.datetime.utcnow() + ) return self def remove_folder(self, delete_path, parent_folders): @@ -116,8 +118,9 @@ def _create_tree_(self, name, path, files, folders): for i in files: images.append(i.get_name()) for f in folders: - tree = self._create_tree_(f.get_name(), f.get_path(), - f.get_files(), f.get_folders()) + tree = self._create_tree_( + f.get_name(), f.get_path(), f.get_files(), f.get_folders() + ) child_nodes.append(tree) return { @@ -141,19 +144,18 @@ def _crawl_for_allowed_files_(self): try: # pylint: disable=unused-variable for file in os.listdir(decoded_path): - folder_path = os.path.normpath(os.path.join( - decoded_path, file)) + folder_path = os.path.normpath(os.path.join(decoded_path, file)) if os.path.isdir(folder_path): self._folders_.append( Folder( encode(folder_path), file, datetime.datetime.utcnow(), - )) + ) + ) else: if allowed_file(file): - file_path = os.path.normpath( - os.path.join(decoded_path, file)) + file_path = os.path.normpath(os.path.join(decoded_path, file)) self._files_.append(File(encode(file_path), file)) except OSError as error: diff --git a/src/engine/server/services/filesystem/folder_target.py b/src/engine/server/services/filesystem/folder_target.py index 69ba9de2..babc1261 100644 --- a/src/engine/server/services/filesystem/folder_target.py +++ b/src/engine/server/services/filesystem/folder_target.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,18 +8,18 @@ @File : folder_target.py @Author : Beatrice Leong -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Service to deal with the targeted folder (folder selected by user) -''' +""" import datetime import os # Ignore import-error and no-name-in-module due to Pyshell # pylint: disable=E0401, E0611 from server.services import decode, encode -from server.services.errors import PortalError, Errors +from server.services.errors import Errors, PortalError from server.services.filesystem.folder import Folder @@ -56,7 +56,8 @@ def update_all_folders(self): self._folders_.pop(index) else: self._folders_[index] = folder.update_folder( - folder.get_path(), datetime.datetime.utcnow()) + folder.get_path(), datetime.datetime.utcnow() + ) def update_folder(self, path): """Scan one folder to check for new updates.""" @@ -66,8 +67,7 @@ def update_folder(self, path): self.delete_folder(path) raise PortalError( Errors.INVALIDFILETYPE, - f"{decoded_path} is no longer a directory." - "Deleted it from assets", + f"{decoded_path} is no longer a directory." "Deleted it from assets", ) path = encode(decoded_path) @@ -75,7 +75,8 @@ def update_folder(self, path): folder = item if path.startswith(folder.get_path()): self._folders_[index] = folder.update_folder( - folder.get_path(), datetime.datetime.utcnow()) + folder.get_path(), datetime.datetime.utcnow() + ) break def delete_folder(self, path): @@ -96,8 +97,9 @@ def add_folders(self, path): decoded_path = os.path.normpath(decode(path)) # Makes sure path is a folder if not os.path.isdir(decoded_path): - raise PortalError(Errors.INVALIDFILETYPE, - f"{decoded_path} is not a directory") + raise PortalError( + Errors.INVALIDFILETYPE, f"{decoded_path} is not a directory" + ) # Ensure all encoded path are encoded with the same format path = encode(decoded_path) # pylint: disable=unused-variable @@ -108,11 +110,11 @@ def add_folders(self, path): if path.startswith(folder.get_path()): is_exist = True self._folders_[index] = folder.update_folder( - path, datetime.datetime.utcnow()) + path, datetime.datetime.utcnow() + ) break if not is_exist: - self._folders_.append( - Folder(path, tail, datetime.datetime.utcnow())) + self._folders_.append(Folder(path, tail, datetime.datetime.utcnow())) def _flatten_assets_(self, arr, folders): """ diff --git a/src/engine/server/services/global_store.py b/src/engine/server/services/global_store.py index a68c5ba5..88944f59 100644 --- a/src/engine/server/services/global_store.py +++ b/src/engine/server/services/global_store.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,22 +8,24 @@ @File : global_store.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the GlobalStore class. -''' -import gc -import os +""" import atexit +import gc import json +import os import time -from typing import Union, Optional -import jsonpickle +from typing import Optional, Union -from flask import Response +import jsonpickle from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.interval import IntervalTrigger +from flask import Response +from server.models.abstract.BaseModel import BaseModel +from server.models.abstract.Model import Model # Ignore import-error and no-name-in-module due to Pyshell # pylint: disable=E0401, E0611 @@ -32,9 +34,6 @@ # pylint: disable=cyclic-import from server.services.filesystem.folder_target import FolderTargets -from server.models.abstract.BaseModel import BaseModel -from server.models.abstract.Model import Model - def _delete_store_(): if os.path.isfile(os.getenv("CACHE_DIR")): @@ -102,8 +101,9 @@ def set_start_scheduler(self): """Start the scheduler""" if self._scheduler_ is None: self._scheduler_ = BackgroundScheduler(daemon=True) - self._scheduler_.add_job(self._schedule_shutdown_, - IntervalTrigger(minutes=1)) + self._scheduler_.add_job( + self._schedule_shutdown_, IntervalTrigger(minutes=1) + ) self._scheduler_.start() # Shut down the scheduler when exiting the app @@ -126,9 +126,9 @@ def turn_on_autosave(self): """Enable caching during runtime.""" self.caching_system = True with open( - os.environ["USE_CACHE_DIR"], - "w", - encoding="utf-8", + os.environ["USE_CACHE_DIR"], + "w", + encoding="utf-8", ) as cache_flag: cache_flag.write("1") self._save_store_() @@ -136,9 +136,9 @@ def turn_on_autosave(self): def turn_off_autosave(self): """Disable caching during runtime.""" with open( - os.environ["USE_CACHE_DIR"], - "w", - encoding="utf-8", + os.environ["USE_CACHE_DIR"], + "w", + encoding="utf-8", ) as cache_flag: cache_flag.write("0") _delete_store_() @@ -158,12 +158,12 @@ def load_cache(self): with open(os.getenv("CACHE_DIR"), "r", encoding="utf-8") as cache: self._store_ = json.load(cache) self._targeted_folders_ = jsonpickle.decode( - self._store_["targeted_folders"]) + self._store_["targeted_folders"] + ) store_registry = self._store_["registry"] # pylint: disable=R1721 deepcopy_store_registry = { - key: value - for key, value in store_registry.items() + key: value for key, value in store_registry.items() } for _, value in deepcopy_store_registry.items(): reg_model = Model( @@ -193,8 +193,9 @@ def _save_store_(self): updated_registry = { registry_key: { key: value - for key, value in self._store_["registry"] - [registry_key].items() if key in [ + for key, value in self._store_["registry"][registry_key].items() + if key + in [ "model_type", "model_dir", "model_name", @@ -232,7 +233,7 @@ def cache_is_called(self): # This function is called instead. def delete_cache(self) -> None: """Sync all persistent dicitionaries. - To be done before entire system closes. + To be done before entire system closes. """ if self.caching_system: _delete_store_() @@ -267,8 +268,9 @@ def set_status(self, status: str) -> bool: return False if self._op_status_["status"] == status: return True - raise PortalError(Errors.ATOMICERROR, - "Another atomic process is already running.") + raise PortalError( + Errors.ATOMICERROR, "Another atomic process is already running." + ) def get_status(self) -> None: """Acquire the status of the atomic function.""" @@ -279,8 +281,9 @@ def clear_status(self) -> None: self._op_status_["status"] = None self._op_atomic_ = False - def set_caught_response(self, response_name: str, - response: Union[Response, tuple]) -> None: + def set_caught_response( + self, response_name: str, response: Union[Response, tuple] + ) -> None: """Store the return of a function. :param response_name: The string signifying the origin of the response. @@ -299,10 +302,7 @@ def get_caught_response(self, origin: str) -> Union[Response, tuple]: # MODEL (DE)REGISTRATION AND INFORMATION def get_registered_model_list(self) -> dict: """Retrieve the list of models.""" - return { - key: dic["directory"] - for key, dic in self._store_["registry"].items() - } + return {key: dic["directory"] for key, dic in self._store_["registry"].items()} def add_registered_model( self, @@ -428,8 +428,9 @@ def add_predictions(self, key: tuple, value: str) -> None: def check_prediction_cache(self, key: tuple) -> bool: """Check if a prediction key is in the prediction cache.""" - return key[2] in list(self._store_["predictions"].get(key[0], {}).get( - key[1], {}).keys()) + return key[2] in list( + self._store_["predictions"].get(key[0], {}).get(key[1], {}).keys() + ) def get_predicted_images(self, model_id: str) -> list: """Return a list of all successfully predicted images.""" @@ -447,9 +448,9 @@ def get_predictions(self, key: tuple) -> Union[list, dict]: :param key: The prediction key. :return: The predictions. """ - return (self._store_["predictions"].get(key[0], - {}).get(key[1], - {}).get(key[2], {})) + return ( + self._store_["predictions"].get(key[0], {}).get(key[1], {}).get(key[2], {}) + ) def get_prediction_progress(self) -> dict: """Retrieve the _prediction_progress_ attribute.""" diff --git a/src/engine/server/services/hashing.py b/src/engine/server/services/hashing.py index dbe11e00..450f78b0 100644 --- a/src/engine/server/services/hashing.py +++ b/src/engine/server/services/hashing.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,12 +8,13 @@ @File : hashing.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : A service responsible for hashing. -''' +""" import hashlib + from dirhash import dirhash @@ -24,7 +25,6 @@ def get_hash(path_to_directory: str) -> str: :return: Hash string. """ directory_contents_hash = dirhash(path_to_directory, "md5") - double_hash = hashlib.md5( - (directory_contents_hash + path_to_directory).encode()) + double_hash = hashlib.md5((directory_contents_hash + path_to_directory).encode()) return double_hash.hexdigest() diff --git a/src/engine/server/services/model_loader.py b/src/engine/server/services/model_loader.py index e4a8b65e..f4e4d3a2 100644 --- a/src/engine/server/services/model_loader.py +++ b/src/engine/server/services/model_loader.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,18 +8,17 @@ @File : model_loader.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the loading functions. -''' +""" from flask import Response # pylint: disable=E0401, E0611 from server import global_store -from server.services.errors import Errors, PortalError - from server.models.abstract.BaseModel import BaseModel +from server.services.errors import Errors, PortalError def model_loader(model_id: str) -> Response: @@ -37,8 +36,7 @@ def model_loader(model_id: str) -> Response: if model_id in list(global_store.get_loaded_model_keys()): return Response(status=200) try: - registered_model: BaseModel = global_store.get_registered_model( - model_id) + registered_model: BaseModel = global_store.get_registered_model(model_id) registered_model.load() global_store.load_model(model_id, registered_model) return Response(status=200) @@ -48,7 +46,6 @@ def model_loader(model_id: str) -> Response: model_id + " is not found in registered model list.", ) from e except TypeError as e: - raise PortalError(Errors.UNINITIALIZED, - "No models are registered.") from e + raise PortalError(Errors.UNINITIALIZED, "No models are registered.") from e except FileNotFoundError as e: raise PortalError(Errors.INVALIDFILEPATH, str(e)) from e diff --git a/src/engine/server/services/model_register.py b/src/engine/server/services/model_register.py index 01868ac4..e117b441 100644 --- a/src/engine/server/services/model_register.py +++ b/src/engine/server/services/model_register.py @@ -8,7 +8,7 @@ @File : model_register.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the register functions. diff --git a/src/engine/server/services/predictions.py b/src/engine/server/services/predictions.py index dd4b8e0f..dd45135f 100644 --- a/src/engine/server/services/predictions.py +++ b/src/engine/server/services/predictions.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,29 +8,28 @@ @File : predictions.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the prediction function. -''' +""" import os from typing import Optional import cv2 import numpy as np +from server import global_store +from server.models.abstract.BaseModel import BaseModel +from server.services.errors import Errors, PortalError # pylint: disable=E0401, E0611 from server.utils.prediction_utilities import ( - get_suppressed_output, back_to_array, get_detection_json, - visualize, + get_suppressed_output, save_to_bytes, + visualize, ) -from server.models.abstract.BaseModel import BaseModel - -from server.services.errors import PortalError, Errors -from server import global_store # pylint: disable=R0913 @@ -51,7 +50,9 @@ def _predict_single_image( :return: The predictions in the format requested by format_arg. """ image_array = cv2.cvtColor(image_array, cv2.COLOR_BGRA2RGB) - detections = model_class.predict(image_array=image_array, ) + detections = model_class.predict( + image_array=image_array, + ) suppressed_output = get_suppressed_output( detections=detections, filter_id=None, @@ -127,8 +128,7 @@ def predict_video( cap.release() cv2.destroyAllWindows() global_store.clear_stop() - raise PortalError(Errors.STOPPEDPROCESS, - "video prediction killed.") + raise PortalError(Errors.STOPPEDPROCESS, "video prediction killed.") # Capture frame-by-frame ret, frame = cap.read() if ret: diff --git a/src/engine/server/utils/__init__.py b/src/engine/server/utils/__init__.py index 0d88203a..45767b7a 100644 --- a/src/engine/server/utils/__init__.py +++ b/src/engine/server/utils/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,8 +8,8 @@ @File : __init__.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Init file for server utilitites. -''' +""" diff --git a/src/engine/server/utils/color_switch.py b/src/engine/server/utils/color_switch.py index 415eb6ec..70dafd0d 100644 --- a/src/engine/server/utils/color_switch.py +++ b/src/engine/server/utils/color_switch.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,11 +8,11 @@ @File : color_switch.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Utility function color_switch. -''' +""" def color_switch(number: int) -> list: diff --git a/src/engine/server/utils/prediction_utilities.py b/src/engine/server/utils/prediction_utilities.py index 5ad0473f..10b999ab 100644 --- a/src/engine/server/utils/prediction_utilities.py +++ b/src/engine/server/utils/prediction_utilities.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*-coding:utf-8 -*- -''' +""" ████ ██ ██ Datature ██ ██ Powering Breakthrough AI @@ -8,23 +8,23 @@ @File : prediction_utilities.py @Author : Marcus Neo -@Version : 0.5.8 +@Version : 0.5.9 @Contact : hello@datature.io @License : Apache License 2.0 @Desc : Module containing the utilities needed for predictions. -''' +""" from base64 import encodebytes from typing import Union -import numpy as np import cv2 -from shapely.geometry import Polygon, MultiPolygon -from shapely.ops import unary_union +import numpy as np +from server import EPSILON_MULTIPLIER +from server.services.global_store import Errors, PortalError # pylint: disable=E0401, E0611 from server.utils.color_switch import color_switch -from server import EPSILON_MULTIPLIER -from server.services.global_store import PortalError, Errors +from shapely.geometry import MultiPolygon, Polygon +from shapely.ops import unary_union def corrected_predict_query(*args, request) -> dict: @@ -70,8 +70,9 @@ def corrected_predict_query(*args, request) -> dict: try: confidence = float(request.args.get("confidence", 0.001)) except TypeError as e: - raise PortalError(Errors.INVALIDQUERY, - "Confidence Query is not a float.") from e + raise PortalError( + Errors.INVALIDQUERY, "Confidence Query is not a float." + ) from e reanalyse_string = request.args.get("reanalyse", "false") if reanalyse_string not in ["true", "false"]: @@ -104,13 +105,12 @@ def _filter_class_and_zero_scores( """ if filter_class is not None: filter_idx = [ - idx for idx, (score, class_id) in enumerate(zip(scores, classes)) + idx + for idx, (score, class_id) in enumerate(zip(scores, classes)) if (score >= confidence and class_id == filter_class) ] else: - filter_idx = [ - idx for idx, score in enumerate(scores) if score >= confidence - ] + filter_idx = [idx for idx, score in enumerate(scores) if score >= confidence] return filter_idx @@ -166,18 +166,22 @@ def _non_max_suppress_bbox( # intersect = width * height intersect = np.maximum(0.0, xx2 - xx1) * np.maximum(0.0, yy2 - yy1) - overlap = intersect / (areas[score] + areas[sorted_scores[1:]] - - intersect) - sorted_scores = sorted_scores[np.union1d( - np.where(overlap <= 1 - iou)[0], - np.where(class_others != class_largest), - ) + 1] + overlap = intersect / (areas[score] + areas[sorted_scores[1:]] - intersect) + sorted_scores = sorted_scores[ + np.union1d( + np.where(overlap <= 1 - iou)[0], + np.where(class_others != class_largest), + ) + + 1 + ] detection_boxes = list(map(tuple, bbox_filter[keep])) detection_scores = list(scores_filter[keep]) detection_classes = list(classes_filter[keep]) - detection_boxes = [(float(item[0]), float(item[1]), float(item[2]), - float(item[3])) for item in detection_boxes] + detection_boxes = [ + (float(item[0]), float(item[1]), float(item[2]), float(item[3])) + for item in detection_boxes + ] detection_scores = [float(item) for item in detection_scores] detection_classes = [int(item) for item in detection_classes] return ( @@ -236,21 +240,25 @@ def _non_max_suppress_mask( intersect = np.empty_like(sorted_scores[1:]) for index, others in enumerate(masks_filter[sorted_scores[1:]]): intersect[index] = np.count_nonzero( - np.logical_and(masks_filter[score], others)) - - overlap = intersect / (areas[score] + areas[sorted_scores[1:]] - - intersect) - sorted_scores = sorted_scores[np.union1d( - np.where(overlap <= 1 - iou)[0], - np.where( - classes_filter[sorted_scores[1:]] != classes_filter[score]), - ) + 1] + np.logical_and(masks_filter[score], others) + ) + + overlap = intersect / (areas[score] + areas[sorted_scores[1:]] - intersect) + sorted_scores = sorted_scores[ + np.union1d( + np.where(overlap <= 1 - iou)[0], + np.where(classes_filter[sorted_scores[1:]] != classes_filter[score]), + ) + + 1 + ] detection_boxes = list(map(tuple, bbox_filter[keep])) detection_scores = list(scores_filter[keep]) detection_classes = list(classes_filter[keep]) detection_masks = list(masks_filter[keep]) - detection_boxes = [(float(item[0]), float(item[1]), float(item[2]), - float(item[3])) for item in detection_boxes] + detection_boxes = [ + (float(item[0]), float(item[1]), float(item[2]), float(item[3])) + for item in detection_boxes + ] detection_scores = [float(item) for item in detection_scores] detection_classes = [int(item) for item in detection_classes] return ( @@ -293,27 +301,32 @@ def get_suppressed_output( :param confidence: The confidence threshold. :returns: tuple of suppressed (bbox, scores and classes). """ - detection_masks = (detections["detection_masks"] - if "detection_masks" in detections else None) + detection_masks = ( + detections["detection_masks"] if "detection_masks" in detections else None + ) detection_boxes = detections["detection_boxes"] detection_scores = detections["detection_scores"] detection_classes = detections["detection_classes"] - return (_non_max_suppress_bbox( - bbox=detection_boxes, - scores=detection_scores, - classes=detection_classes, - filter_class=filter_id, - iou=iou, - confidence=confidence, - ) if detection_masks is None else _non_max_suppress_mask( - bbox=detection_boxes, - scores=detection_scores, - classes=detection_classes, - masks=detection_masks, - filter_class=filter_id, - iou=iou, - confidence=confidence, - )) + return ( + _non_max_suppress_bbox( + bbox=detection_boxes, + scores=detection_scores, + classes=detection_classes, + filter_class=filter_id, + iou=iou, + confidence=confidence, + ) + if detection_masks is None + else _non_max_suppress_mask( + bbox=detection_boxes, + scores=detection_scores, + classes=detection_classes, + masks=detection_masks, + filter_class=filter_id, + iou=iou, + confidence=confidence, + ) + ) def back_to_array(suppressed_output: tuple) -> dict: @@ -323,23 +336,20 @@ def back_to_array(suppressed_output: tuple) -> dict: :returns: Dictionary containing the suppressed outputs in array form. """ tensor_dict = { - "num_detections": - np.array( + "num_detections": np.array( [ float(len(suppressed_output[2])), ], dtype=np.float32, ), - "detection_boxes": - np.array([suppressed_output[0]], dtype=np.float32), - "detection_scores": - np.array([suppressed_output[1]], dtype=np.float32), - "detection_classes": - np.array([suppressed_output[2]], dtype=np.float32), + "detection_boxes": np.array([suppressed_output[0]], dtype=np.float32), + "detection_scores": np.array([suppressed_output[1]], dtype=np.float32), + "detection_classes": np.array([suppressed_output[2]], dtype=np.float32), } if suppressed_output[3] is not None: - tensor_dict["detection_masks"] = np.array([suppressed_output[3]], - dtype=np.uint8) + tensor_dict["detection_masks"] = np.array( + [suppressed_output[3]], dtype=np.uint8 + ) return tensor_dict @@ -372,12 +382,10 @@ def _convert_mask_to_contours(reframed_masks: np.array) -> list: polygons = [] for single_contour in inner_contour: # 2. Simplfy the contour to get an approximation - epsilon = EPSILON_MULTIPLIER * cv2.arcLength( - single_contour, True) + epsilon = EPSILON_MULTIPLIER * cv2.arcLength(single_contour, True) approx = cv2.approxPolyDP(single_contour, epsilon, True) # 3. Normalize the approximation - approx = [[item[0][0] / width, item[0][1] / height] - for item in approx] + approx = [[item[0][0] / width, item[0][1] / height] for item in approx] # Min 3 points is needed for polygon to be created if len(approx) >= 3: @@ -401,8 +409,7 @@ def _convert_mask_to_contours(reframed_masks: np.array) -> list: if isinstance(union_polygon, MultiPolygon): # pylint: disable=E1101 polygon_list = list(union_polygon.geoms) - largest_poly_idx = np.argmax( - [item.area for item in polygon_list]) + largest_poly_idx = np.argmax([item.area for item in polygon_list]) final_polygon = polygon_list[largest_poly_idx] # 6. No change for single polygon @@ -422,8 +429,7 @@ def get_detection_json(detections_output: dict, category_map: tuple) -> list: """ num_detections = int(detections_output.pop("num_detections")) detections = { - key: value[0, :num_detections] - for key, value in detections_output.items() + key: value[0, :num_detections] for key, value in detections_output.items() } # Extract predictions bboxes = detections["detection_boxes"] @@ -439,21 +445,16 @@ def get_detection_json(detections_output: dict, category_map: tuple) -> list: output = [] for each_class, _ in enumerate(classes): - if contours is None or (contours is not None - and bool(contours[each_class])): + if contours is None or (contours is not None and bool(contours[each_class])): tag = category_map[str(classes[each_class])] item = {} item["confidence"] = float(scores[each_class]) item["tag"] = tag item["bound"] = [ - [float(bboxes[each_class][1]), - float(bboxes[each_class][0])], - [float(bboxes[each_class][1]), - float(bboxes[each_class][2])], - [float(bboxes[each_class][3]), - float(bboxes[each_class][2])], - [float(bboxes[each_class][3]), - float(bboxes[each_class][0])], + [float(bboxes[each_class][1]), float(bboxes[each_class][0])], + [float(bboxes[each_class][1]), float(bboxes[each_class][2])], + [float(bboxes[each_class][3]), float(bboxes[each_class][2])], + [float(bboxes[each_class][3]), float(bboxes[each_class][0])], ] if contours is not None: item["boundType"] = "masks"