{"version":3,"sources":["viewer/utils/PolygonUtil.jsx","common/components/Spinloader.jsx","common/utils/Backend.jsx","aiViewer/components/AIModel2ProjectTypeMapping.jsx","viewer/contexts/PersistentStorageContext.jsx","common/utils/RandomColorGenerator.jsx","home/dialogs/FindFilesDialog.jsx","common/components/AITrainingInformation.jsx","common/components/AITrainingDataContainer.jsx","viewer/contexts/ProjectContext.jsx","viewer/contexts/TilesContext.jsx","spectraViewer/contexts/SpectraViewerContext.jsx","viewer/contexts/ResultTabContext.jsx","scanViewer/contexts/ScanViewerContext.jsx","globalComponents/CustomSvgIcon.jsx","aiViewer/AIContext.jsx","common/services/authentication.service.js","proteomViewer/components/ProteomSettings.jsx","home/dialogs/CreateProjectdialogComponents/ProjectTypeList.jsx","common/components/LazyRender.jsx","viewer/contexts/ProjectHistoryContext.jsx","home/dialogs/CreateProjectdialogComponents/EmptySlideCreation.jsx","home/dialogs/CreateProjectdialogComponents/StepFileSelection.jsx","common/utils/Utils.jsx","common/components/RoiTypes.jsx","common/components/PrivateRoute.jsx","common/components/CustomDialog.jsx","home/dialogs/CreateProjectdialogComponents/StepMetaData.jsx","home/dialogs/CreateProjectdialogComponents/StepProjectModuleSelection.jsx","home/dialogs/CreateProjectDialog.jsx","home/components/PreviewImage.jsx","home/components/ProjectsTableRow.jsx","home/dialogs/CreateConfirmationDialog.jsx","home/components/ProjectsTable.jsx","home/HomePage.jsx","common/components/NavigationBar.jsx","App.jsx","registerServiceWorker.js","index.js","common/components/Structure.jsx","common/components/AITrainingSettings.jsx","common/utils/Localization.jsx","common/components/InstantAnalysisModule.jsx","common/utils/auth-header.js","common/utils/handle-response.js","common/utils/history.js","common/utils/role.js","viewer/utils/ROI.jsx","common/components/IAMConfig.jsx","viewer/utils/StructuresUtils.jsx"],"names":["lineArrayBuffer","lineArray","radius","vw","vh","undefined","length","feature","turf","buffered","buffer","viewRect","result","console","log","distance","p1","p2","deltaX","x","deltaY","y","Math","sqrt","pointsToCirclePolygon","numberOfSegments","n","center","dist","coordinates","w","h","i","point","cos","PI","sin","max","min","push","regions","inverted","simplifyRegions","tolerance","poly","simplifiedPoly","highQuality","e","geometry","calcBoundingBox","region","left","top","right","bottom","rect","p","calcBoundingBoxFullObject","roiCoords","_roiCoords$","Error","pointInsideRegion","turfPoint","turfPoly","pointInside","regionRoi","hasIntersection","regionRoi1","regionRoi2","poly1","poly2","intersects","isInside","getIntersections","regionRois1","regionRois2","regions1","map","roi","regions2","findIndexById","structures","id","findIndex","structure","findSameLayer","selectedLayer","defaultParentIndex","parentLayerId","parentId","classificationSubtype","parentIndex","findSiblingRoiLayers","roiLayers","overlapRoiLayers","visible","layer","regionRois","checkIfStructureHidden","isSubtype","name","color","label","window","showWarningSnackbar","idx","findClickedRoi","includeBaseROI","inversed","overlapTreeItems","tree","search","minX","parseInt","minY","maxX","maxY","treeItem","getExterior","drawRegion","filter","a","arr","el","getIndexOf","drawRegionGeoJson","PolyBool","polygonToGeoJSON","drawRegionWithoutHoles","type","updateDrawLayer","clear","subtype","bufferSize","drawRegionRois","RegionROI","color1","multiLayerRegions","multiDrawRegions","transformResult","coordArray","roiToAdd","createRegionRoi","area","fullyLoaded","structureId","isObject","arguments","updateLayer","positionInRoiLayer","overlap","parentLayer","clickedOnRoi","historyItem","histId","parentRegionRois","reducedLayerRegionRois","forEach","r","uuid","getTreeItemsFromRois","multiParentRegions","intersection","turfPolyToRegionRois","openErrorDialog","overlapRoiLayer","overlapItems","drawRoi","drawPoly","isIntersecting","comment","remove","add","copy","transformResultInfo","differenceRegionsInfo","segDiff","idxRoi","segGeoJSON","idxRegionsInfo","subtypeName","differenceRegionsAndInfo","debug","firstRoiToAdd","insert","all","fromIndex","item","toIndex","element","splice","arraymove","projectHistory","findRoi","resultRoi","targetLayerIndex","validateAndCorrectRois","rois","fallbackStructureIndex","suggestedStructure","find","realStructureByNameAndColor","suggestedStructChildren","generateChildrenList","s","realStructureByParentAndColor","realStructureByParentAndLabel","newlyAssignedStructure","fallbackStructure","epsilon","SpinloaderContext","React","createContext","withSpinloader","Component","WrappedComponent","props","_jsx","Consumer","children","context","spinloader","displayName","concat","SpinloaderProvider","constructor","super","showWithProgress","progressObject","this","start_time","performance","now","progress","setState","show","messagePresent","message","isNaN","indefinite","clearTimeout","timeout","showWithAutoProgress","seconds","currentSecond","predictedSeconds","setTimeout","updateAutoProgress","state","showWithMessage","measureTime","executionTime","minutes","logMessage","rightWidth","showWithTimeout","scenesLeft","timeoutSeconds","waitTime","timeoutHide","resetTimer","hide","hideTimeDelayed","delay","load","func","setRightWidth","width","render","classes","_jsxs","Provider","value","numberScenes","progObject","numberRestScenes","callback","className","greyedOutBackground","onContextMenu","preventDefault","style","progressContainer","Dialog","dialog","open","hideBackdrop","DialogTitle","CircularProgress","LinearProgress","linearProgress","height","variant","size","withStyles","styles","position","zIndex","margin","textAlign","pointerEvents","display","marginLeft","background","PYTHON_SERVER_URL","jobProgressConnection","HubConnectionBuilder","withUrl","configureLogging","LogLevel","Warning","build","fetch_auth","url","config","currentUser","authenticationService","currentUserValue","token","headers","Authorization","fetch","logout","Promise","reject","validateResponse","response","permissionString","status","showErrorSnackbar","success","json","showHandledProblems","errorMessage","permissionDenied","handleJsonResponse","res","error","serverTimeoutInMilliseconds","keepAliveIntervalInMilliseconds","Backend","static","ok","statusText","io","then","text","catch","user","method","body","JSON","stringify","group","userId","userGroups","validateResponseJSON","appsettings","data","date","dateFormated","toISOString","dateDay","convertDateToDayString","blob","URL","createObjectURL","document","createElement","href","download","appendChild","click","actionName","customErrorPrint","redirect","responseData","resolve","caseId","path","params","errorCallback","progressCallback","jobId","random","toString","substr","connection","on","line","start","invoke","err","page","lv","fileId","projectId","zRange","showPointCloud","toLowerCase","queryOptions","async","projectIds","roiType","Object","values","RoiType","includes","TypeError","timeInSeconds","time","searchOptions","_res","roisNotLoaded","ImageRoi","incomingRoi","fromObject","AudioRoi","filePath","requestUrl","encodeURIComponent","errMsg","ex","exportName","file","time1","FormData","append","info","updatedName","model","formData","projectActionMode","projectCount","projects","names","output_name","projectJson","img","folderPath","fileName","fileMappings","projectType","projectNames","evalOnly","remoteUuid","Structure","tmpStructures","tmpstruct","toolSettings","openConfirmationDialog","modificationStatus","ModificationStatus","Saved","roiUpdate","reassignedIds","failedToAdd","failedToDelete","roisToAdd","Added","roiIdsToDelete","Deleted","Blob","warning","forceReload","availabeProjectTypes","modules","module","tools","tool","InstantAnalysisModule","waitForElement","getVersion","ptKey","version","projectTypes","parse","localStorage","getItem","loadAvailableProjectTypes","projectTypesList","annotations","description","isUserModule","order","setItem","isRelative","dir","task","str","image_path","obj","convertDateToShortIsoString","Date","location","origin","req","XMLHttpRequest","setRequestHeader","responseType","onload","Uint8Array","onerror","send","successCallback","modelType","isVdlModel","parameters","advancedSettings","comDLArchitecture","off","trainingProgress","updateTrainingData","project","myJson","tileExportProgress","model_path","online","details","unlistedModels","modelErrs","shortErr","models","newModels","new_model","m","AITrainingDataContainer","AIModel2ProjectTypeMapping","modelName","projectTypeMapping","jsonString","aiModel","payload","validateInstance","AITrainingSettings","optionalParams","showSuccessSnackbar","verifiedAIModel","selectedAIModel","isJsonString","jsonLine","k","replace","keys","files","annotation","geoJSON","serializedGeoJSON","stdout","iamConfig","galleryTrainingProgress","alModel","graphRequestSettings","startsWith","slice","uuidv4","Accept","iamName","iam","errorStr","statusMessage","closeProject","loadTensorboardScalarData","getTrainingEpochProgress","targetDataFormat","structureMappings","inferenceParameters","outerStructureId","isActive","validateType","ValidationType","String","validateInEnum","TargetDataFormat","Array","structureMapping","StructureMapping","InferenceParameters","Int","Bool","convertPascalCaseKeysToCamelCase","convertSnakeCaseKeysToCamelCase","Image","ImageInferenceParameters","Audio","AudioInferenceParameters","oldId","newId","PersistentStorageContext","withPersistentStorage","persistentStorage","PersistentStorageProvider","_isMounted","loadedProjectState","projectState","projectTypeState","save","key","v","stateObject","saveProjectTypeValue","loadProjectTypeValue","loadAll","entries","presetColors","getRandomColor","colorIdx","RangeError","floor","getUnusedColor","UNSAFE_checkStructureType","counter","some","ProjectActionMode","freeze","Import","Update","Query","_dialogContent","title","FindFilesDialog","_this","_props$formData","_props$onSuccess","setMountedState","handleClose","dialogIsOpen","openAccordion","isValidating","handleRefresh","checkUnique","checkFileMappings","allUniquelyMapped","openWarningDialog","handleSubmit","onSuccess","Boolean","generateFileList","LazyRender","maxContainerHeight","elementHeight","f","marginBottom","TextField","sourcePath","InputProps","endAdornment","duplicatePath","InputAdornment","Tooltip","disableInteractive","ContentCopyIcon","sx","found","CheckIcon","ErrorIcon","disabled","fullWidth","newPath","onChange","target","forceUpdate","uniqueFiles","mapping","index","array","sort","b","localeCompare","filesFound","missing","duplicates","split","pop","onClose","maxWidth","IconButton","float","onClick","RefreshIcon","DialogContent","dialogContent","DialogContentText","Accordion","expanded","_","AccordionSummary","Typography","AccordionDetails","DialogActions","Button","root","paddingTop","minWidth","SystemInformation","os","cpu","gpu","ram","_obj$os","_obj$cpu","_obj$gpu","_obj$ram","Os","Cpu","Gpu","Ram","AITrainingInformation","creationDate","completionDate","systemInformation","trainingStatus","settings","information","ProjectContext","withProject","projectContext","ProjectProvider","initAIData","readAIModel2ProjectModuleMapping","mappingData","aiModel2ProjectModuleMappings","wasSavedByUser","projectObject","viewerConfig","filteredMappingData","mappingItem","structureIdx","toolIdx","t","toolParam","toolParams","ui","default","minSize","maxSize","minIntensity","maxIntensity","confidence","dependingStructure","initModel2ProjectTypeMapping","initProject","projectStructures","stuct","toolsInProject","AICockpit","initForeignHistory","socket","componentDidUpdate","structuresStateList","isUnfolded","showSubtypes","updateProjectStructures","cleanUsersData","timeNow","usersData","updateTime","receiveSocketMessage","syncStructures","receive","fileRoiLayers","newRoiLayers","tempRoiLayer","roiLayer","RBush","initSocket","getAnnotationSocket","onmessage","ev","getCurrentUser","fullName","intervalId","setInterval","readyState","getMousePositionInImage","objectToSend","clearInterval","init","viewer","updateProject","selStructureId","anno","newRegionRois","createRoisFromAnno","setChangingFile","changingFile","setActiveTab","tab","activeTab","getActiveTab","getRegionById","c","getNumberOfChilds","parentStructure","importStructures","layerId","sendStructures","addStructure","grid","newLayerId","reduce","newStructure","dynamic","allToolNames","dynamicStructure","classFrequencies","class_0","class_1","class_2","class_3","class_4","class_5","class_6","avgClassFrequnecy","subtypeLevel","defaultSelected","alterStructure","newRoilayer","addSubStructure","parent","fromHistoModule","subStructure","parentColor","subtypeColor","hasChild","numberChilds","roiIndex","addSubtypeText","addSubType","findChilds","subType","deleteStructure","childs","toplevelParentId","getParentIndexLayer","structureIndex","roiIdx","struct","subtypesRemoved","parentStruct","updateStructures","newSelectedLayer","duplicateStructure","pureLabel","copiesCount","assign","duplicateChildren","findChildren","oldParent","newParent","canMoveStructure","selectedStructure","direction","structuresSameLevel","moveStructure","strt","ed","allElements_1","lastStructure","idxSwapStructure","otherParent","sceneGUID","roi_layer_a","roi_layer_b","getProjectStringInfos","join","today","dd","getDate","padStart","mm","getMonth","yyyy","getFullYear","setStateNow","newState","getUserData","setPersistentStorage","commentLayers","ome","isLoadingAnnotations","galleryImageSize","userPermissions","canImportModels","canExportModels","groupPermissions","canAnnotate","canTrainModel","canRunJob","canComment","canEditStructures","canAccessAITab","canEditModel","annotationsReduced","totalRoiCount","shortCutButtonIdList","allAiModels","opacity","getModelMetadata","aiModels","componentDidMount","componentWillUnmount","getUsersData","getFileRoiLayers","TilesContext","withTiles","tiles","TilesProvider","getIndex","strAnnoCount","getIndexObj","strSubtypesPages","resetStPg","visibleImage","visibleImageUpdatedAt","coloredImages","coloredImagesUpdatedAt","imgWidth","imgHeight","pageIndex","histogramConfig","selectedLayerColor","selcetedLayerIndex","annotationCount","firstIteration","accPoints","pointCount","galleryVisible","isMousedown","isOnImage","IsInOtherImage","onPageInput","structureBefore","graphAcc","roiProps","pos","histoClassificationStarted","zLevel","chainLeaderId","transformationMatrix","transformationFactor","transformationOffset","setVisibleImage","clearTiles","pushVisibleImage","tileId","getTime","sorted","src","resetVisibleImages","getVisibleImages","getVisibleImage","setColoredImages","pushColoredImages","resetColoredImages","getColoredImages","getColoredImage","setImgWidth","getImgWidth","setImgHeight","getImgHeight","setPageIndex","getPageIndex","setHistogramConfig","getHistogramConfig","setSelectedLayerColor","getSelectedLayerColor","setSelectedLayerIndex","selectedLayerIndex","getSelectedLayerIndex","addAnnotationCount","setAnnotationCount","getAnnotationCount","setFirstIteration","getFirstIteration","pushAccPoint","getAccPoints","setGalleryVisible","getGalleryVisible","setIsMousedown","getIsMousedown","setIsOnImage","getIsOnImage","setIsInOtherImage","isInOtherImage","getIsInOtherImage","setRoiProps","getRoiProps","setPositionRoi","setOnPageInput","getOnPageInput","pushStrAnnoCount","pushDynamicStructureAC","setStrAnnoCount","setParentAnnoCount","getStrAnnoCountElement","getStrAnnoCount","setAnnoCount","changeAnnoCount","idx_a","idx_b","pushSubtypesPages","tilePage","subtypes","pushDynamicStructureSP","getSubtypesPages","setSubtypesPages","setPage","getPage","setTilePage","getTilePage","setSubtypes","setSingleSubtype","getSubtypes","resetSubtypesPages","setStructure","getStructure","getStructureBefore","setGraphAcc","pushGraphAcc","getGraphAcc","setHistoClassificationStarted","getHistoClassificationStarted","setFileId","getFileId","setZLevel","getZLevel","setTransformationMatnFactnOff","fact","Off","getTransformationMatrix","getTransformationFactor","getTransformationOffset","removeTransformationMatrix","resetAllTransformationMatnFact","getAllTransformationMatrices","getAllTransformationFactors","getAllTransformationOffsets","SpectraViewerContext","withSpectraViewer","spectraViewer","SpectraViewerProvider","setContextState","object","updateAreas","areas","refs","createRef","toggleSavedCalcs","useSavedCalcs","setMaxScores","availableSamples","rawSpectra","checked","maxScores","sortPCAs","valueToSortBy","temp_pcas","pcas","reverse","pcaOrder","selectedSpectrum","operationSets","rawSpectraLoaded","selectedPca","selectedPcaId","focusedPca","scores","approximations","analysisResults","analysisResultsLoaded","selectedPcaScore","selectedProcessedSpectrum","currentlyShownData","ratedSpectra","selectedModelIdx","selectedModelName","passingCriteria","passingCriteria_idx","passingCriteria_min","passingCriteria_max","spectraPredictionSettings","ResultTabContext","withResultTab","_ref","propsWithoutClasses","resultTab","ResultTabProvider","getPosition","rendererCtx","getTransform","getScale","selectedRoi","selectedChildIndex","changeFile","hundredTiles","rendererInitialized","rendererCanvas","zoomLevelFixed","gridExists","resetPressed","selSampleSet","fileChange","getSelectedRoi","setSelectedRoi","getSelectedChildIndex","setSelectedChildIndex","getSelectedStructure","setSelectedStructure","getChangeFile","setChangeFile","getHundredTiles","setHundredTiles","getRendererInitialized","setRendererInitialized","getRendererCanvas","setRendererCanvas","getRendererCtx","setRendererCtx","getZoomLevelFixed","toggleZoomLevelFixed","setZoomLevelFixed","getGridExists","setGridExists","getResetPressed","setResetPressed","getSelSampleSet","setSelSampleSet","getFileChange","setFileChange","ScanViewerContext","withScanViewerContext","scanViewerContext","ScanViewerProvider","setLenseType","lenseType","setAdapterType","adapterType","changeScanState","scanState","changeTab","slideScanning","commentCount","channels","_this$io","connected","emit","setScanRendererSize","changeMicroscopeParams","paramJson","changeImportParams","param","importFilePath","moveCenter","dx","dy","sendMinimapClickPosition","sendFilePath","tabIdx","exportWIP","importWIP","filepath","createWSI","setWhiteBalanceState","setVignetteState","setFeaturePointsState","numFeaturePoints","toggleCamera","cameraVisible","toggleMinimap","mapVisible","toggleGrid","gridVisible","toggleDebugData","debugDataVisible","toggleComments","commentsVisible","toggleFluorescence","sideBarContent","updateFluorescenceParams","toggleAutomation","automationVisible","toggleFocusPeaking","focusPeakingOn","deleteScanArea","deleteArea","x1","centeredX","y1","centeredY","x2","y2","zoomIn","zoomOut","zoomReset","exitScanner","disconnect","useAutomatedMicroscope","command","automatedMicroscopeStatus","streamReady","fluorescenceChannels","selectedChannel","cameraMinFramerate","cameraMaxFramerate","cameraMinExposureTime","cameraMaxExposureTime","cameraMinGain","cameraMaxGain","cameraMinGamma","cameraMaxGamma","cameraMinBlackValue","cameraMaxBlackValue","pixelSizeCamera","cameraColorMin","cameraColorMax","getPythonServerSocket","message_content","openResponseDialog","history","paused","addEventListener","cameraVisibleValue","mapVisibleValue","gridVisibleValue","debugDataVisibleValue","commentsVisibleValue","automationVisibleValue","focusPeakingOnValue","sideBarContentValue","removeEventListener","withRouter","CustomSvgIcon","stroke","vertAlign","xmlns","viewBox","isolation","verticalAlign","d","fillRule","fill","mask","vectorEffect","strokeWidth","strokeLinejoin","strokeLinecap","strokeMiterlimit","cx","cy","transform","focusable","role","AIContext","AIContextProvider","hasChanges","setHasChanges","useState","initError","setInitError","initializing","setInitializing","modelFilterValue","setModelFilterValue","setProjectTypes","projectTypeSettingList","setProjectTypeSettingList","projectTypeStructures","setProjectTypeStructures","selectedModel","setSelectedModel","setSelectedModelName","selectedProjectType","setSelectedProjectType","selectedStructuresMappingIdx","setSelectedStructuresMappingIdx","selectedTab","setSelectedTab","structuresMapping","setStructuresMapping","trainedModels","setTrainedModels","useEffect","initialize","loadViewerConfig","newProjectTypeStructures","updateSelectedProjectType","readProjectTypeMappingForAIModel","metaData","mappingArray","initMapping","AIModels","nTrainedModels","trainingParameters","epochs","AIModelDataContainer","newStructureMapping","mappingObject","modelStructure","modelStructureMapping","handleSelectProjectTypeIdx","selectedMapping","addMapping","newMapping","removeMapping","newItems","saveCurrentModelSettings","writeProjectTypeMappingForAIModel","updateStructuresMappingWithIdx","newStructuresMapping","updateModels","currentUserSubject","BehaviorSubject","login","email","password","requestOptions","handleResponse","next","isLoggedIn","removeItem","reload","asObservable","_currentUserSubject$v","ProteomSettings","projectStringProperties","onChangeMetaData","paddingContainer","FormControl","formItem","select","Channel","MenuItem","Proteome","component","hidden","FormLabel","RadioGroup","row","defaultValue","FormControlLabel","control","Checkbox","currentTarget","Continues","Discontinues","EpitopeLengthMax","EpitopeLengthMin","numberInput","inputProps","step","MinScore","padding","marginRight","applyButton","useStyles","makeStyles","projectTilesList","maxHeight","projectTile","cursor","overflow","border","projectTileSelected","expiredMarker","expiringMarker","lineHeight","ProjectTypeList","onProjectType","availableTypes","searchText","ImageList","rowHeight","spacing","cols","searchContent","projectProperties","Hidden","toSearch","availableType","ImageListItem","classNames","WIP","isValid","expirationDate","expiresInDays","image","alt","tileImage","ImageListItemBar","titleBar","forwardRef","ref","offsetElements","containerRef","useRef","scrollPositionTop","setScrollPositionTop","containerHeight","setContainerHeight","current","clientHeight","handleScroll","scrollTop","scrollBottom","scrollHeight","scrollTo","useImperativeHandle","isInView","ProjectHistoryContext","withProjectHistory","ProjectHistoryProvider","collecting","collection","past","future","stepType","items","toSend","itm","input","inputItems","roiStructure","processItem","updateState","undoItem","redoItem","shownSaveHintNum","showActionSnackbar","onSaveClick","action","parentLayerIdx","parentRoiLayer","isSame","sameBoundsWith","undo","redo","canUndo","canRedo","getHistoryLength","sizeLimitReached","mergePastItems","newItem","startCollection","addCollection","mergedItems","EmptySlideCreation","allowed_formats","checkFormat","valid_regex","format","test","emptyFile_name","ref_regex","Grid","container","overflowY","alignItems","xs","pattern","allowed_format","inputRef","onKeyDown","addFile","ref_button","event","non_utf8_capable_filetypes","StepFileSelection","getLastDir","pathEnding","lastSeperator","lastIndexOf","fromCharCode","getFilesFromPath","currentPath","filterText","addAll","supportedFileFormats","foldersToExclude","directoryEntries","walkDir","filteredDirFiles","subfolderFiles","entry","shouldBeAdded","lastDir","subfiles","addFileCount","addManyFilesConfirmed","pathParts","extension","updateFolderList","dirfiles","char","charCodeAt","lastFileName","dirFilePaths","shiftKey","lastFileIdx","indexOf","fileIdx","firstIdx","lastIdx","fileNameToAdd","onChangeFiles","toggleAllFiles","removeFolder","addFolder","clickEvent","filePaths","filteredFiles","filesToAdd","stopPropagation","resultFiles","isDisabled","relativePath","imageFiles","Set","toggleSortMenu","sortMenuOpen","setSortBy","sortBy","sortReverse","creationTime","switchFolderWithCases","showFolders","handleItemClick","selCase","onChangeCaseId","pathArray","getFilePathsFromCaseList","caseFiles","walkCaseFiles","addCaseFile","dirFilesCase","foundCase","caseList","cases","Id","image_error","caseItems","listCases","case_acc","onChangeFilter","gridTemplateRows","Box","justifyContent","fontSize","selButton","node","anchorEl","MoreVertIcon","Menu","keepMounted","ArrowUpward","ArrowDownward","SearchIcon","marginTop","autoFocus","List","dense","fileList","ListItem","ListItemIcon","substring","ListItemText","primary","ListItemButton","objectFit","imageThumbnail","onError","CheckBox","fileSize","textOverflow","loaded","Folder","ListItemSecondaryAction","AddToPhotos","selItem","selectionTarget","freeHistoParameters","minHeight","backgroundColor","borderBottom","isUuid","inputString","acceptNil","uuid_w_nil","isHexColor","isInt","Number","Function","Undefined","variableName","isArray","instanceType","enumType","roundToDecimal","num","decimals","round","EPSILON","pow","rgbToHex","g","toHex","toUpperCase","rgbaToHex","rgbaString","alpha","parts","parseFloat","alphaHex","rgbHex","o","newO","origKey","newKey","prototype","hasOwnProperty","call","charAt","countDecimals","_x$toString$split$1$l","shortenString","maxLength","startIdx","endIdx","ceil","viewerType","downloadJsonObjectAsFile","jsonObject","downloadName","dataStr","dlAnchorElem","setAttribute","downloadArrayAsFile","arrayIn","requestFileInput","acceptedFileTypes","inputElem","onchange","debounce","fn","timeoutId","_len","args","_key","isColorLight","rgba","hex","exec","hexToRgba","ImageAnnotationType","Area","Comments","AnnotationAction","Save","Export","DeleteAll","saveAnnotations","annotationType","polyRep","saveAnnotationsToDb","oldIds","newIds","idTuple","exportAnnotations","username","timestamp","isStructure","msg","importAnnotations","existingAnnotations","unsaved","fr","FileReader","importedAnnotations","isAiAnnotated","z","startTime","endTime","minFreq","maxFreq","errmsg","readAsText","deleteAllAnnotations","forceDelete","Roi","getTreeItem","bboxPolygon","box","bbox","PrivateRoute","roles","rest","Route","Redirect","to","pathname","from","CustomDialog","handleConfirmOpen","responseFunction","content","dialogState","awaitUserConfirmation","contentList","confirmed","handleErrorOpen","handleWarningOpen","handleInformationOpen","downloadError","removeChild","openInformationDialog","Fragment","multiline","StepMetaData","FormHelperText","metaField","StepProjectModuleSelection","imageListItemRefs","onChangeName","isHistoModule","sm","TextValidator","errorMessages","validators","onFocus","tileBar","whiteSpace","CreateProjectDialog","handleKeyPress","handleNext","prevProps","promises","imageFileIds","getFileInfo","submitted","activeStep","origFiles","newdefaultname","nextStep","filesRemoved","oF","filesRemovedInfo","fileAnnoCount","annotationsToLoose","acc","name_array","createProject","loadProject","projectModel","readableId","job","saveProject","handleActiveTabChange","setProjectsPending","editCaseProjects","handleBack","prevStep","ProjectStringProperties","pt","field","groups","getLicensingInfo","license","activeModules","licenseStatus","activeModule","isExpired","firstValidProjectType","getCurrentUserGroups","Divider","divider","ValidatorForm","onSubmit","onSaveName","MobileStepper","steps","nextButton","KeyboardArrowRight","backButton","KeyboardArrowLeft","PreviewImage","setFileName","renderThumbnail","ProjectsTableRow","isSelected","handleClick","handleSelectOneClick","onEditProject","onProjectStateClick","loadProjectMessage","jsonResponse","onSetTimedClick","setProjectsTimed","TableRow","tableRow","canOpen","hover","tabIndex","selected","TableCell","align","scope","canEdit","EditIcon","ownerName","labelFromProjectType","resultObject","labelFromState","progressBarContainer","bar","creatingJobBar","progressBar","toFixed","onProjectErrorStateClick","convertDate","creationDateTime","toLocaleString","canAccessResults","duplicateProjects","FileCopyIcon","cancelJob","StopIcon","canRun","TimerIcon","onRunRowClick","PlayArrowIcon","CreateConfirmationDialog","setOpen","setPending","setEvalOnly","runJob","Radio","desc","orderBy","rows","numeric","disablePadding","EnhancedTableHead","createSortHandler","property","onRequestSort","onSelectAllClick","numSelected","TableHead","sortDirection","placement","enterDelay","TableSortLabel","active","EnhancedTableToolbar","_user$group","_user$group2","onCreateTimeLineChartClick","onDeleteClick","onDuplicateSelectedClick","onExportClick","onImportClick","onMergeResultsClick","onMergeSelectedClick","onRunSelectedClick","onTimedRunSelectedClick","fileUploader","timeLineButtonDisabled","timeLineButtonTooltip","initTimelineButton","selectedProjects","projectTypeEqual","projectTypeSupported","allProjectsFinished","notSupportedMethod","supportedProjectTypes","mergeResultButtonDisabled","mergeResultButtonTooltip","initMergeButton","mergeResultsButtonTooltip","mergeResultsButtonDisabled","every","Toolbar","highlight","searchIcon","searchField","spacer","actions","FontAwesomeIcon","icon","faObjectGroup","TimelineIcon","canOpenProject","CloudDownload","Merge","FileCopy","DeleteIcon","canImportProjects","CloudUpload","accept","theme","paddingRight","gridTemplateColumns","palette","mode","secondary","main","lighten","light","dark","flex","ProjectsTable","tableContainerRef","projectTypesNames","topScrollPos","bottomScrollPos","handleRequestSort","handleSelectAllClick","isJobVisible","selectedObject","selectedIndex","serverIsRunning","handleContextmenu","openConfDialog","clickedProjId","importProjects","ImportProjectsDialog","exportProjects","deleteProjects","deleteGalleryExport","projectTypesEqual","selectedProjectId","selectedProject","mergeProjects","droppedRoisMessages","handleChange","idxTop","showJob","openCreateTimeLineDialog","createTimeLineChartDialogIsOpen","mergeProjectResults","projectsDirId","closeCreateTimeLineDialog","countFinished","countOther","cur","sortedProjects","cmp","stabilizedThis","stableSort","getSorting","Paper","FindMissingFiles","Tabs","indicatorColor","textColor","Tab","TableContainer","tableWrapper","Table","stickyHeader","table","tableLayout","rowCount","TableBody","overflowX","darken","incrementDefaultName","newDefaultName","maxProjNum","proj","match","projNum","newMaxProjNum","pad","HomePage","checkPythonServer","isLocalServerReady","handleClickOpen","editableProject","handleEditOpen","refreshProjects","activeTabIndex","refreshProjectsInterval","refreshInterval","listProjects","Fab","fab","AddIcon","serverSpinLoader","NavigationBar","checkProjectButton","isResultsButtonVisible","dir_path","walkProjectDirFiles","reportExists","endsWith","resultsPath","extraButtonState","projectPath","updateUserGroups","canAccessLicensingPage","canAccessAdminPage","canAccessCases","canAccessScan","canAccessFileView","setNavigationbarTitle","headline","showDevButtons","scannerState","expirationMessage","setPageHeadline","listen","subscribe","scannerData","expirationDays","handleMenu","contains","titleMap","pathFragment","fullVersion","AppBar","menuButton","grow","ping","getAbout","logFiles","newestLogFile","decodeURIComponent","headerButton","WorkIcon","BarChartIcon","PermMediaIcon","FolderCopyIcon","ScannerIcon","warningColor","SvgIcon","toggleClassRoomChat","ScreenShareIcon","Person","ArrowDropDown","Popper","transition","disablePortal","TransitionProps","Grow","menu","square","ClickAwayListener","onClickAway","MenuList","CoPresent","menuIcon","Build","History","Info","ExitToApp","flexGrow","appbarPlaceholder","mixins","toolbar","textTransform","borderRadius","transformOrigin","errorColor","AboutPage","lazy","AdminPage","AudioViewer","AIViewer","CasesPage","FileViewer","PredictionPage","ProteomViewer","Report","ScanViewer","SpectraViewer","Viewer","LoginPage","LicensingPage","SettingsPage","UserHistoryPage","SuspenseFallback","flexDirection","App","enqueueSnackbar","action_msg","hide_msg","closeSnackbar","sbId","_Fragment","persist","Suspense","fallback","_ref2","_ref3","ScanProvider","_ref4","historyDepth","_ref5","_ref6","Role","Admin","exact","withSnackbar","hostname","baseUrl","getElementsByTagName","getAttribute","rootElement","getElementById","createTheme","inactive","typography","useNextVariants","ReactDOM","BrowserRouter","basename","StyledEngineProvider","injectFirst","ThemeProvider","SnackbarProvider","maxSnack","navigator","serviceWorker","ready","registration","unregister","isDynamic","sameLevelRank","isInversed","annotationsAreVisible","hasChildren","nestingDepth","totalObjectCount","canBeChosen","isChosen","maxId","__setMaxId","newStructureId","highestIdInStructures","abs","structureCanMove","siblings","sameLevelIndex","parentStructures","parentStructs","childStructures","childStructs","getSameLevelRank","sortStructures","child","newSameLevelRank","sibsToModify","prevRanks","insertStructure","deleteAnnotations","firstNewId","newStructs","parentIdx","cs","shift","exportStructures","_project$name","newStructures","newStruct","val","DatasetApproach","ImageFileBased","ImageObjectBased","ImageSlidingWindow","AudioFileBased","AudioSlidingWindow","DatasetApproachNames","DatasetApproachShort","DatasetType","ImageClassification","ImageObjectDetection","ImageSegmentation","ImageInstanceSegmentation","AudioClassification","AudioSequenceDetection","AudioSequenceSegmentation","AudioSequenceInstanceSegmentation","DatasetTypeNames","DatasetTypeShort","ImageDatasetTypes","AudioDatasetTypes","_targetDataFormatbyModuleName","AudioAnnotator","targetDataFormatbyModuleName","_targetDataFormatbyMo","Metrics","Accuracy","MetricsNames","LossFunction","CrossEntropy","Dice","CrossEntropyDice","LossFunctionNames","Optimizer","Adam","AdamW","SGD","OptimizerNames","_DefaultDatasetTypeMappings","DefaultDatasetType","_DefaultDatasetTypeMa","_DefaultDatasetApproachMappings","DefaultDatasetApproach","_DefaultDatasetApproa","TrainingParameters","earlyStopping","batchSize","metrics","lossFunctions","optimizer","learningRate","metric","lossFunction","ModelMetaData","isNewModel","DatasetParameters","datasetApproach","datasetType","datasetOnly","useExistingDataset","removeBackground","removeBorderThreshold","DatasetMeta","ImageDatasetMeta","inputChannels","spatialDims","imageWidth","imageHeight","numberOfClasses","pyramidLevel","pixelSize","fluorescenceChannel","AudioDatasetMeta","sequenceLengthSeconds","sequenceOverlapSeconds","_ModelParameterMappping","getModelParameters","_ModelParameterMapppi","datasetParameters","modelParameters","padTo2Digits","jsonDate","getHours","getMinutes","getSeconds","UIComponent","optional","hiddenStructures","options","_obj$hiddenStructures","Parameter","tooltip","preview","shared","parameter","authHeader","createBrowserHistory","User","BaseROI","strokeColor","fillColor","CommentROI","commentValue","computedValue","fontScaleFactor","updateBounds","bounds","containsPoint","inputObj","convertToImageROI","aiAnnotated","roiCopy","isAnnotated","isLabeled","isSelObj","getBoundsColorId","ai","setRegions","borderColor","annotated","labeled","isSel","isSaved","saved","tileName","selectedWithKey","frequencyClass","isStartData","aiIdx","galleryIndex","firstTimeGallery","getPointOnPoly","pointOnPolygon","converted","removeDuplicates","inputRegions","resultRegions","getRectRegions","getSimplifiedRectRegions","getDynamicRegions","comp","numObjects","intRegions","simplifyedRegions","boundsAreaCompare","pArea","newRegionRoi","RectROI","ctx","drawingMode","resizePoint","summary","handleMouseDown","cornerRadius","dragStart","handleMouseMove","canvas","hovered","handleMouseUp","drag","resize","draw","strokeStyle","lineWidth","beginPath","closePath","cornerDiameter","fillStyle","getFirstValidatedIndexValue","getOnlyValidatedSimpleIndexValue","frequencyCl","confidenceThreshold","minObjectSize","maxObjectSize","minimumObjectSize","maximumObjectSize","minTimeSeconds","maxTimeSeconds","minFrequencyHz","maxFrequencyHz","SearchArea","IAMConfig","fileIds","structureIds","previewOnly","searchArea","generateParentList","parentList","continueSearch","currentStruct","getParentIndex","childrenList","generateAListOfAllChildrenRecursively","allChildren","getContainedRegionRois","decendantIds","toplevelParentIndex","fullChildrenList","currentChildren","convertLegacyStructures","convertedStructures","getNumberOfAnnotations"],"mappings":"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","file":"static/js/main.88975205.chunk.js","sourcesContent":["// Copyright HS Analysis GmbH, 2019\r\n// Author: Viktor Eberhardt, Lukas Buess, Timo Koch, Valentin Haas\r\n\r\n// External imports\r\nimport PolyBool from \"polybooljs\";\r\nimport * as turf from \"@turf/turf\";\r\n//import { booleanIntersects, difference, simplify } from \"@turf/turf\";\r\n// use old turf library, since new turf lib breaks GeoJSON coordinates when buffering\r\nimport { buffer } from \"turf\";\r\n\r\n// HSA imports\r\nimport { RegionROI } from \"./ROI\";\r\nimport { generateChildrenList } from \"./StructuresUtils\";\r\n\r\n//default: 0.0000000001\r\nPolyBool.epsilon(0.0000000001);\r\n\r\nexport function lineArrayBuffer(lineArray, radius, vw, vh) {\r\n if (lineArray === undefined || lineArray.length === 0) return;\r\n if (lineArray.length === 1) {\r\n lineArray = [lineArray[0], lineArray[0]];\r\n }\r\n let feature =\r\n lineArray.length > 1 ? turf.lineString(lineArray) : turf.point(lineArray);\r\n let buffered = buffer(feature, radius * 110);\r\n let viewRect = turf.bboxPolygon([0, 0, vw, vh]);\r\n let result = null;\r\n try {\r\n result = turf.intersect(buffered, viewRect);\r\n } catch {\r\n console.log(\"pen tool error:\", buffered, viewRect);\r\n return null;\r\n }\r\n return result;\r\n}\r\n\r\nexport function circleToPolygon(center, radius, numberOfSegments) {\r\n let n = numberOfSegments ? numberOfSegments : 32;\r\n let coordinates = [];\r\n\r\n for (let i = 0; i < n; ++i) {\r\n coordinates.push([\r\n center[0] + radius * Math.cos((2 * Math.PI * i) / n),\r\n center[1] + radius * Math.sin((2 * Math.PI * i) / n),\r\n ]);\r\n }\r\n\r\n return {\r\n regions: [coordinates],\r\n inverted: false,\r\n };\r\n}\r\n\r\nexport function distance(p1, p2) {\r\n let deltaX = p1.x - p2.x;\r\n let deltaY = p1.y - p2.y;\r\n return Math.sqrt(deltaX * deltaX + deltaY * deltaY);\r\n}\r\n\r\nexport function pointsToCirclePolygon(p1, p2, numberOfSegments, vw, vh) {\r\n let n = numberOfSegments ? numberOfSegments : 32;\r\n let center = {\r\n x: (p1.x + p2.x) / 2,\r\n y: (p1.y + p2.y) / 2,\r\n };\r\n let dist = distance(p1, center);\r\n let coordinates = [];\r\n let x = center.x - dist;\r\n let y = center.y - dist;\r\n let w = 2 * dist;\r\n let h = 2 * dist;\r\n\r\n for (let i = 0; i < n; ++i) {\r\n let point = [\r\n x + w / 2 + (w / 2) * Math.cos((2 * Math.PI * i) / n),\r\n y + h / 2 + (h / 2) * Math.sin((2 * Math.PI * i) / n),\r\n ];\r\n point[0] = Math.max(0, point[0]);\r\n point[1] = Math.max(0, point[1]);\r\n point[0] = Math.min(vw, point[0]);\r\n point[1] = Math.min(vh, point[1]);\r\n coordinates.push(point);\r\n }\r\n\r\n return {\r\n regions: [coordinates],\r\n inverted: false,\r\n };\r\n}\r\n\r\nexport function rectangleToEllipyePolygon(x, y, w, h, numberOfSegments) {\r\n let n = numberOfSegments ? numberOfSegments : 32;\r\n let coordinates = [];\r\n\r\n for (let i = 0; i < n; ++i) {\r\n coordinates.push([\r\n x + w / 2 + (w / 2) * Math.cos((2 * Math.PI * i) / n),\r\n y + h / 2 + (h / 2) * Math.sin((2 * Math.PI * i) / n),\r\n ]);\r\n }\r\n\r\n return {\r\n regions: [coordinates],\r\n inverted: false,\r\n };\r\n}\r\n\r\nexport function lineToPolygon(start, stop, width) {\r\n let coordinates = [];\r\n\r\n let normalVector = [-(stop[1] - start[1]), stop[0] - start[0]];\r\n\r\n let normalVectorLength = Math.sqrt(\r\n normalVector[0] * normalVector[0] + normalVector[1] * normalVector[1]\r\n );\r\n normalVector[0] /= normalVectorLength;\r\n normalVector[1] /= normalVectorLength;\r\n\r\n coordinates.push([\r\n start[0] + (normalVector[0] * width) / 2,\r\n start[1] + (normalVector[1] * width) / 2,\r\n ]);\r\n coordinates.push([\r\n stop[0] + (normalVector[0] * width) / 2,\r\n stop[1] + (normalVector[1] * width) / 2,\r\n ]);\r\n coordinates.push([\r\n stop[0] - (normalVector[0] * width) / 2,\r\n stop[1] - (normalVector[1] * width) / 2,\r\n ]);\r\n coordinates.push([\r\n start[0] - (normalVector[0] * width) / 2,\r\n start[1] - (normalVector[1] * width) / 2,\r\n ]);\r\n\r\n return {\r\n regions: [coordinates],\r\n inverted: false,\r\n };\r\n}\r\n\r\nexport function simplifyRegions(regions, tolerance) {\r\n let poly = turf.polygon(regions);\r\n let simplifiedPoly = regions;\r\n try {\r\n simplifiedPoly = turf.simplify(poly, {\r\n tolerance: tolerance,\r\n highQuality: false,\r\n });\r\n } catch (e) {\r\n return regions;\r\n }\r\n\r\n return simplifiedPoly.geometry.coordinates;\r\n}\r\n\r\nexport function bufferSimplifyRegions(regions) {\r\n let poly = turf.polygon(regions);\r\n poly = buffer(poly, -5);\r\n if (poly.geometry.coordinates[0].length === 0) return regions;\r\n let simplifiedPoly = turf.simplify(poly, {\r\n tolerance: 0.05,\r\n highQuality: false,\r\n });\r\n return simplifiedPoly.geometry.coordinates;\r\n}\r\n\r\n/**\r\n * Calculates the bounding box around an object, not considering holes.\r\n * Holes are calculated individually.\r\n * Results in a rect object with top, botton, left, and right properties.\r\n * @param {Array[[float, float]]} region Coordinates as array of point arrays.\r\n * @returns {object} Rectangle object containing top, botton, left, and right properties.\r\n */\r\nexport function calcBoundingBox(region) {\r\n if (region.length === 0) {\r\n // region is empty\r\n return { left: 0, top: 0, right: 0, bottom: 0 };\r\n }\r\n let rect = {\r\n left: region[0][region[0].length - 1][0],\r\n top: region[0][region[0].length - 1][1],\r\n right: region[0][region[0].length - 1][0],\r\n bottom: region[0][region[0].length - 1][1],\r\n };\r\n for (let p of region[0]) {\r\n if (p[0] < rect.left) rect.left = p[0];\r\n if (p[0] > rect.right) rect.right = p[0];\r\n if (p[1] < rect.top) rect.top = p[1];\r\n if (p[1] > rect.bottom) rect.bottom = p[1];\r\n }\r\n return rect;\r\n}\r\n\r\n/**\r\n * Calculates the bounding box around an object.\r\n * Results in a rect object with top, botton, left, and right properties.\r\n * @param {Array[Array[[float, float]]]} roiCoords GeoJson coordinates as array.\r\n * @returns Rectangle object containing top, botton, left, and right properties.\r\n */\r\nexport function calcBoundingBoxFullObject(roiCoords) {\r\n // Validity checks\r\n if (!roiCoords?.length) {\r\n throw new Error(\r\n \"Invalid or empty ROI supplied, cannot calculate bounding box\"\r\n );\r\n }\r\n\r\n // Only consider first coordinate set, the rest contain holes.\r\n if (!roiCoords[0]?.length) {\r\n throw new Error(\r\n \"Invalid or empty area supplied, cannot calculate bounding box\"\r\n );\r\n }\r\n return calcBoundingBox([roiCoords[0]]);\r\n}\r\n\r\nexport function getTreeItem(regions) {\r\n let bounds = calcBoundingBox(regions);\r\n return {\r\n minX: bounds.left,\r\n minY: bounds.top,\r\n maxX: bounds.right,\r\n maxY: bounds.bottom,\r\n used: false,\r\n regions: regions[0],\r\n };\r\n}\r\n\r\nexport function calcBoundingBoxes(layer) {\r\n let rects = [];\r\n for (let roi of layer.regionRois) {\r\n let region = roi.region;\r\n if (region[region.length - 1]) {\r\n rects.push(calcBoundingBox(region));\r\n }\r\n }\r\n return rects;\r\n}\r\n\r\nexport function intersectRect(r1, r2) {\r\n return !(\r\n r2.left >= r1.right ||\r\n r2.right <= r1.left ||\r\n r2.top >= r1.bottom ||\r\n r2.bottom <= r1.top\r\n );\r\n}\r\n\r\nexport function pointInsidePoly(p, polyPoints) {\r\n let x = p.x,\r\n y = p.y;\r\n let intersections = 0;\r\n let ss = \"\";\r\n for (let i = 0, j = polyPoints.length - 1; i < polyPoints.length; j = i++) {\r\n let xi = polyPoints[i][0],\r\n yi = polyPoints[i][1];\r\n let xj = polyPoints[j][0],\r\n yj = polyPoints[j][1];\r\n if (yj === yi && yj === y && x > Math.min(xj, xi) && x < Math.max(xj, xi)) {\r\n // Check if point is on an horizontal polygon boundary\r\n return true;\r\n }\r\n\r\n if (\r\n y > Math.min(yj, yi) &&\r\n y <= Math.max(yj, yi) &&\r\n x <= Math.max(xj, xi) &&\r\n yj !== yi\r\n ) {\r\n ss = ((y - yj) * (xi - xj)) / (yi - yj) + xj;\r\n if (ss === x) {\r\n // Check if point is on the polygon boundary (other than horizontal)\r\n return true;\r\n }\r\n if (xj === xi || x <= ss) {\r\n intersections++;\r\n }\r\n }\r\n }\r\n // If the number of edges we passed through is odd, then it’s in the polygon.\r\n if (intersections % 2 !== 0) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n}\r\n\r\nexport function pointInsideRegion(p, region) {\r\n let turfPoint = turf.point([p.x, p.y]);\r\n let turfPoly = turf.polygon([region]);\r\n return !turf.booleanDisjoint(turfPoly, turfPoint);\r\n}\r\n\r\nexport function pointInside(p, regionRoi) {\r\n let turfPoint = turf.point([p.x, p.y]);\r\n let turfPoly = turf.polygon(regionRoi.regions);\r\n return !turf.booleanDisjoint(turfPoly, turfPoint);\r\n}\r\n\r\nexport function boundsInside(b, regionRoi) {\r\n let points = [\r\n { x: b.left, y: b.top },\r\n { x: b.right, y: b.top },\r\n { x: b.right, y: b.bottom },\r\n { x: b.left, y: b.bottom },\r\n ];\r\n let returnValue = true;\r\n for (let p of points) {\r\n if (!pointInside(p, regionRoi)) returnValue = false;\r\n }\r\n return returnValue;\r\n}\r\n\r\n// if one poly intersects or is inside other poly\r\nexport function hasIntersection(regionRoi1, regionRoi2) {\r\n let poly1 = turf.polygon(regionRoi1.regions);\r\n let poly2 = turf.polygon(regionRoi2.regions);\r\n return !turf.booleanDisjoint(poly1, poly2);\r\n}\r\n\r\nexport function intersects(regionRoi1, regionRoi2) {\r\n let poly1 = turf.polygon(regionRoi1.regions[0]);\r\n let poly2 = turf.polygon(regionRoi2.regions[0]);\r\n return turf.booleanIntersects(poly1, poly2);\r\n}\r\n\r\nexport function isInside(regionRoi1, regionRoi2) {\r\n let poly1 = turf.polygon(regionRoi1.regions);\r\n let poly2 = turf.polygon(regionRoi2.regions);\r\n\r\n // Return true if poly1 is completely inside poly2\r\n return turf.booleanWithin(poly1, poly2);\r\n}\r\n\r\nexport function filterInvalidRegions(layer) {\r\n let result = layer.regionRois.filter(\r\n (roi) => roi.regions[roi.regions.length - 1]\r\n );\r\n layer.regionRois = result;\r\n}\r\n\r\nexport function getIntersections(regionRois1, regionRois2) {\r\n let regions1 = regionRois1.map((roi) => roi.regions);\r\n let regions2 = regionRois2.map((roi) => roi.regions);\r\n\r\n let poly1 = turf.multiPolygon(regions1);\r\n let poly2 = turf.multiPolygon(regions2);\r\n let intersection = turf.intersect(poly1, poly2);\r\n return intersection;\r\n}\r\nfunction findIndexById(structures, id) {\r\n return structures.findIndex((structure) => structure.id === id);\r\n}\r\nexport function findSameLayer(structures, selectedLayer) {\r\n let defaultParentIndex = selectedLayer === 0 ? -1 : 0;\r\n let parentLayerId = structures[selectedLayer].parentId;\r\n while (structures[selectedLayer].classificationSubtype) {\r\n selectedLayer = findIndexById(structures, parentLayerId);\r\n parentLayerId = structures[selectedLayer].parentId;\r\n }\r\n let parentIndex = structures.findIndex(\r\n (structure) => structure.id === structures[selectedLayer].parentId\r\n );\r\n return [selectedLayer, parentIndex < 0 ? defaultParentIndex : parentIndex];\r\n}\r\n\r\nexport function findSiblingRoiLayers(structures, selectedLayer, roiLayers) {\r\n let overlapRoiLayers = [];\r\n let parentLayerId = structures[selectedLayer].parentId;\r\n for (let i = 1; i < structures.length; i++) {\r\n if (\r\n selectedLayer !== i &&\r\n structures[i].parentId === parentLayerId &&\r\n structures[i].visible\r\n ) {\r\n if (roiLayers[i].layer.regionRois.length > 0) {\r\n overlapRoiLayers.push(roiLayers[i]);\r\n }\r\n }\r\n }\r\n return overlapRoiLayers;\r\n}\r\n\r\n/**\r\n * Check if structure is hidden when starting drawing and if so unhide it\r\n * @param {*} structures reference on this.structures needed! No copy!\r\n * @param {*} selectedLayer index of selected structure\r\n * @param {*}\r\n */\r\nexport function checkIfStructureHidden(\r\n structures,\r\n selectedLayer,\r\n isSubtype,\r\n name,\r\n color\r\n) {\r\n // set baseRoi to visible\r\n structures[0].visible = true;\r\n\r\n // if subtype get correct selectedLayer\r\n if (isSubtype) {\r\n selectedLayer = structures.findIndex(\r\n (structure) => structure.label === name && structure.color === color\r\n );\r\n }\r\n if (!structures[selectedLayer].visible) {\r\n window.showWarningSnackbar(\"Unhiding drawing structure\");\r\n structures[selectedLayer].visible = true;\r\n }\r\n let parentId = structures[selectedLayer].parentId;\r\n while (parentId !== 0 && parentId !== null) {\r\n // unhide all subtypes with same parent structure\r\n for (let idx in structures) {\r\n if (structures[idx].parentId === parentId) {\r\n if (!structures[idx].visible) {\r\n structures[idx].visible = true;\r\n }\r\n }\r\n }\r\n // unhide parent structure\r\n for (let structure of structures) {\r\n if (structure.id === parentId) {\r\n if (!structure.visible) {\r\n structure.visible = true;\r\n }\r\n parentId = structure.parentId;\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Filter only relevant Regions from given rois\r\n * @param {*} tree search tree\r\n * @param {*} rois ROI used as filter using Bounding Box\r\n * @returns [largestROI, reducedLayerRegions]\r\n */\r\nexport function getTreeRegionsFromRois(tree, rois) {\r\n let reducedLayerRois = [];\r\n for (let regionRoi of rois) {\r\n tree\r\n .search(regionRoi.treeItem)\r\n .filter((treeItem) => treeItem.roi.isObject === false)\r\n .forEach((treeItem) => {\r\n const index = reducedLayerRois.findIndex(\r\n (roi) => roi.uuid === treeItem.roi.uuid\r\n );\r\n if (index === -1) {\r\n reducedLayerRois.push(treeItem.roi);\r\n }\r\n });\r\n }\r\n return [\r\n reducedLayerRois[0],\r\n reducedLayerRois.map((roi) => roi.regions),\r\n reducedLayerRois,\r\n ];\r\n}\r\n\r\n/**\r\n * find smallest region\r\n * @param {*} p mouse position\r\n * @param {*} selectedLayer this.selectedLayer\r\n * @param {*} structures this.structures\r\n * @param {*} roiLayers this.roiLayers\r\n * @param {boolean} includeBaseROI this.includeBaseROI\r\n * @returns {[]} region polygon or false if none was found\r\n */\r\nexport function findRegion(\r\n p,\r\n selectedLayer,\r\n structures,\r\n roiLayers,\r\n includeBaseROI\r\n) {\r\n if (\r\n structures[selectedLayer].visible &&\r\n (includeBaseROI || !structures[selectedLayer].inversed)\r\n ) {\r\n let smallestRoi = null;\r\n for (let roi of roiLayers[selectedLayer].layer.regionRois) {\r\n if (pointInside(p, roi)) {\r\n if (smallestRoi === null || roi.area < smallestRoi.area) {\r\n smallestRoi = roi;\r\n }\r\n }\r\n }\r\n if (smallestRoi !== null) return smallestRoi;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * find clicked on ROI\r\n * @param {*} p mouse position\r\n * @param {*} selectedLayer this.selectedLayer\r\n * @param {*} structures this.structures\r\n * @param {*} roiLayers this.roiLayers\r\n * @param {boolean} includeBaseROI this.includeBaseROI\r\n * @returns {[]} region polygon or false if none was found\r\n */\r\nexport function findClickedRoi(\r\n p,\r\n selectedLayer,\r\n structures,\r\n roiLayers,\r\n includeBaseROI\r\n) {\r\n if (\r\n structures[selectedLayer].visible &&\r\n (includeBaseROI || !structures[selectedLayer].inversed)\r\n ) {\r\n let overlapTreeItems = roiLayers[selectedLayer].tree.search({\r\n minX: parseInt(p.x, 10),\r\n minY: parseInt(p.y, 10),\r\n maxX: parseInt(p.x, 10),\r\n maxY: parseInt(p.y, 10),\r\n });\r\n for (let treeItem of overlapTreeItems) {\r\n if (pointInside(p, treeItem.roi)) {\r\n return treeItem.roi;\r\n }\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/** Find all ROIs of a layer present at a certain location.\r\n *\r\n * @param {Object} p (Mouse) position {x: , y: }\r\n * @param {Int} selectedLayer The id of the selected layer.\r\n * @param {Array} structures Structures of the project.\r\n * @param {Array} roiLayers The layers containing all ROIs.\r\n * @param {Bool} includeBaseROI Whether or not to include the Base ROI.\r\n * @returns {Object} The ROI object found.\r\n * @returns {Bool} If no ROI is found, returns false.\r\n */\r\nexport function findClickedBounds(\r\n p,\r\n selectedLayer,\r\n structures,\r\n roiLayers,\r\n includeBaseROI\r\n) {\r\n if (\r\n structures[selectedLayer].visible &&\r\n (includeBaseROI || !structures[selectedLayer].inversed)\r\n ) {\r\n let overlapTreeItems = roiLayers[selectedLayer].tree.search({\r\n minX: parseInt(p.x, 10),\r\n minY: parseInt(p.y, 10),\r\n maxX: parseInt(p.x, 10),\r\n maxY: parseInt(p.y, 10),\r\n });\r\n for (let treeItem of overlapTreeItems) {\r\n return treeItem.roi;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Check if layer.regionRoi corresponse to Roi in overlapRegionRoi\r\n * @param {*} overlapRegionRois Regions that are overlapping with draw region\r\n * @param {ROI} checkRegion ROI of object.layer to be checked if the same as overlapRegionRois\r\n * @returns {boolean} true if is Hole, false if is outside\r\n */\r\nexport function isInRegionRois(overlapRegionRois, checkRegion) {\r\n let inRegionRois = false;\r\n\r\n for (let region of overlapRegionRois.regions) {\r\n if (\r\n region.find(\r\n (point) =>\r\n point[0] === checkRegion.regions[0][0] &&\r\n point[1] === checkRegion.regions[0][1]\r\n )\r\n ) {\r\n if (\r\n region.find(\r\n (point) =>\r\n point[0] === checkRegion.regions[1][0] &&\r\n point[1] === checkRegion.regions[1][1]\r\n )\r\n ) {\r\n inRegionRois = true;\r\n return inRegionRois;\r\n }\r\n }\r\n }\r\n\r\n return inRegionRois;\r\n}\r\n\r\n/**\r\n * generate overlapRegionRois based on GeoJson logic without the region (incl holes) that was clicked on\r\n * @param {*} reducedLayerRegionsGeoJson geoJson polygon/multipolygon\r\n * @param {*} clickedOnRegion (opt.) regions of clicked on ROI\r\n * @returns [overlapPolygon, clickedOnPolygon]\r\n */\r\nexport function generateOverlapRegionRois(\r\n reducedLayerRegionsGeoJson,\r\n clickedOnRegion\r\n) {\r\n let overlapPolygon = {\r\n inverted: false,\r\n regions: [],\r\n };\r\n let clickedOnPolygon = {\r\n inverted: false,\r\n regions: [],\r\n };\r\n\r\n if (reducedLayerRegionsGeoJson.coordinates.length > 0) {\r\n if (reducedLayerRegionsGeoJson[\"type\"] === \"Polygon\") {\r\n let clickIsOnPolygon = false;\r\n if (clickedOnRegion) {\r\n if (\r\n reducedLayerRegionsGeoJson[\"coordinates\"][0].find(\r\n (point) =>\r\n point[0] === clickedOnRegion[0][0] &&\r\n point[1] === clickedOnRegion[0][1]\r\n )\r\n ) {\r\n if (\r\n reducedLayerRegionsGeoJson[\"coordinates\"][0].find(\r\n (point) =>\r\n point[0] === clickedOnRegion[1][0] &&\r\n point[1] === clickedOnRegion[1][1]\r\n )\r\n ) {\r\n clickIsOnPolygon = true;\r\n }\r\n }\r\n }\r\n let tmpPoly = {\r\n inverted: false,\r\n regions: reducedLayerRegionsGeoJson[\"coordinates\"],\r\n };\r\n if (clickIsOnPolygon) {\r\n clickedOnPolygon = tmpPoly;\r\n } else {\r\n overlapPolygon = tmpPoly;\r\n }\r\n } else {\r\n for (let polygon of reducedLayerRegionsGeoJson[\"coordinates\"]) {\r\n let clickIsOnPolygon = false;\r\n if (clickedOnRegion) {\r\n if (\r\n polygon[0].find(\r\n (point) =>\r\n point[0] === clickedOnRegion[0][0] &&\r\n point[1] === clickedOnRegion[0][1]\r\n )\r\n ) {\r\n if (\r\n polygon[0].find(\r\n (point) =>\r\n point[0] === clickedOnRegion[1][0] &&\r\n point[1] === clickedOnRegion[1][1]\r\n )\r\n ) {\r\n clickIsOnPolygon = true;\r\n }\r\n }\r\n }\r\n if (clickIsOnPolygon) {\r\n clickedOnPolygon.regions = [...clickedOnPolygon.regions, ...polygon];\r\n } else {\r\n overlapPolygon.regions = [...overlapPolygon.regions, ...polygon];\r\n }\r\n }\r\n }\r\n }\r\n return [overlapPolygon, clickedOnPolygon];\r\n}\r\n\r\n/**\r\n * generate regions that intersect with drawRegion based on GeoJson logic\r\n * @param {{ type: String, coordinates: any }} reducedLayerRegionsGeoJson geoJson polygon/multipolygon\r\n * @param {[]} drawRegion region others have to intersect with\r\n * @returns overlapRegionRois\r\n */\r\nexport function getIntersectingRegions(reducedLayerRegionsGeoJson, drawRegion) {\r\n let poly = [];\r\n if (drawRegion.length === 1) drawRegion = drawRegion[0];\r\n let poly1 = turf.polygon([drawRegion]);\r\n\r\n if (reducedLayerRegionsGeoJson[\"type\"] === \"Polygon\") {\r\n if (reducedLayerRegionsGeoJson[\"coordinates\"].length > 0) {\r\n let poly2 = turf.polygon(reducedLayerRegionsGeoJson.coordinates[0]);\r\n\r\n if (turf.booleanIntersects(poly1, poly2)) {\r\n poly.push({\r\n regions: reducedLayerRegionsGeoJson.coordinates\r\n ? reducedLayerRegionsGeoJson.coordinates\r\n : [],\r\n inverted: false,\r\n });\r\n }\r\n } else {\r\n poly.push({\r\n regions: reducedLayerRegionsGeoJson.coordinates\r\n ? reducedLayerRegionsGeoJson.coordinates\r\n : [],\r\n inverted: false,\r\n });\r\n }\r\n } else {\r\n for (let regions of reducedLayerRegionsGeoJson.coordinates) {\r\n let poly2 = {\r\n type: \"Feature\",\r\n properties: {},\r\n geometry: {\r\n type: \"Polygon\",\r\n coordinates: regions[0],\r\n },\r\n };\r\n if (turf.booleanIntersects(poly1, poly2)) {\r\n poly.push({\r\n regions: regions,\r\n inverted: false,\r\n });\r\n }\r\n }\r\n }\r\n return poly;\r\n}\r\n\r\n/**\r\n * before further analysis remove holes from drawRegion\r\n * -> uses buffer of 1\r\n * @param {*} drawRegion in GeoJson format\r\n * @returns drawRegion without holes\r\n */\r\nexport function getExterior(drawRegion) {\r\n // custom index filter to get duplicated points\r\n function getIndexOf(a, arr) {\r\n for (let i = 0; i < arr.length; i++) {\r\n let el = arr[i];\r\n if (el[0] === a[0] && el[1] === a[1]) return i;\r\n }\r\n return -1;\r\n }\r\n\r\n try {\r\n drawRegion.regions[0] = drawRegion.regions[0].filter(\r\n (a, i, arr) => getIndexOf(a, arr) === i\r\n );\r\n let drawRegionGeoJson = PolyBool.polygonToGeoJSON(drawRegion);\r\n\r\n if (drawRegionGeoJson.coordinates.length !== 0) {\r\n drawRegionGeoJson = buffer(drawRegionGeoJson, 1).geometry;\r\n let drawRegionWithoutHoles = {\r\n inverted: false,\r\n regions: [],\r\n };\r\n if (drawRegionGeoJson.type === \"Polygon\") {\r\n drawRegionWithoutHoles.regions.push(drawRegionGeoJson.coordinates[0]);\r\n } else {\r\n for (let regions of drawRegionGeoJson.coordinates) {\r\n drawRegionWithoutHoles.regions.push(regions[0]);\r\n }\r\n }\r\n drawRegion = drawRegionWithoutHoles;\r\n }\r\n } catch {\r\n console.log(\"Error in getExterior, returning empty regions instead!\");\r\n drawRegion = {\r\n regions: [],\r\n inverted: false,\r\n };\r\n }\r\n\r\n return drawRegion;\r\n}\r\n\r\n// /**\r\n// * Get all regions and Rois that overlap with drawing region and the largest included area based on the provided rTree\r\n// * @param {*} tree rTree with all relevant ROIs\r\n// * @param {*} drawRegionRois drawn region that should be used as baseline\r\n// * @returns [reducedLayerRegions, reducedLayerRegionRois] which contain all regions/ROIs that are relevant for the drawn region\r\n// */\r\n// function getOverlapRegionsAndRois(tree, drawRegionRois) {\r\n// let reducedLayerRegions = [];\r\n// let reducedLayerRegionRois = [];\r\n// if (tree) {\r\n// // get all Regions that overlap with drawRegion\r\n// let tmpResult = getTreeRegionsFromRois(tree, drawRegionRois);\r\n// reducedLayerRegions = tmpResult[1];\r\n// reducedLayerRegionRois = tmpResult[2];\r\n// }\r\n// return [reducedLayerRegions, reducedLayerRegionRois];\r\n// }\r\n\r\nfunction getTreeItemsFromRois(tree, regionRois) {\r\n let reducedLayerRegionRois = [];\r\n if (tree) {\r\n for (let roi of regionRois) {\r\n tree.search(roi.treeItem).forEach((treeItem) => {\r\n let idx = reducedLayerRegionRois.findIndex(\r\n (r) => r.uuid === treeItem.roi.uuid\r\n );\r\n if (idx < 0) reducedLayerRegionRois.push(treeItem.roi);\r\n });\r\n }\r\n }\r\n return reducedLayerRegionRois;\r\n}\r\n\r\n/**\r\n * Generates difference Regions and Informations to account for subtypes when deleting (using turf)\r\n * @param {*} overlapItems overlapping tree items\r\n * @param {*} transformResult turf.difference() result\r\n * @returns differenceRegionsInfo - corresponding Info\r\n */\r\nfunction differenceRegionsAndInfo(overlapItems, transformResult) {\r\n let differenceRegionsInfo = [];\r\n\r\n transformResult = transformResult ? transformResult : turf.multiPolygon([]);\r\n if (transformResult.geometry.type === \"Polygon\") {\r\n transformResult = turf.multiPolygon([transformResult.geometry.coordinates]);\r\n }\r\n\r\n for (let poly of transformResult.geometry.coordinates) {\r\n differenceRegionsInfo.push({\r\n name: null,\r\n color: null,\r\n subtype: null,\r\n structureId: null,\r\n });\r\n let segDiff = turf.polygon(poly);\r\n for (let idxRoi in overlapItems) {\r\n let segGeoJSON = turf.polygon(overlapItems[idxRoi].regions);\r\n if (!turf.booleanDisjoint(segDiff, segGeoJSON)) {\r\n let idxRegionsInfo = differenceRegionsInfo.length - 1;\r\n differenceRegionsInfo[idxRegionsInfo].name =\r\n overlapItems[idxRoi].subtypeName;\r\n differenceRegionsInfo[idxRegionsInfo].color =\r\n overlapItems[idxRoi].color;\r\n differenceRegionsInfo[idxRegionsInfo].subtype =\r\n overlapItems[idxRoi].isSubtype;\r\n differenceRegionsInfo[idxRegionsInfo].structureId =\r\n overlapItems[idxRoi].structureId;\r\n break;\r\n }\r\n }\r\n }\r\n return differenceRegionsInfo;\r\n}\r\n\r\n// /**\r\n// * custom GeoJSON converter to throw that sees them all as outer Polygons\r\n// * TODO: Add efficient way to detect wholes\r\n// * @param {*} reducedLayerRegions\r\n// * @returns\r\n// */\r\n// function customGeoJsonConverter(reducedLayerRegions) {\r\n// let resultGeoJSON = {\r\n// coordinates: [],\r\n// };\r\n// if (reducedLayerRegions.length === 0) {\r\n// resultGeoJSON.type = \"Polygon\";\r\n// } else if (reducedLayerRegions.length === 1) {\r\n// resultGeoJSON.type = \"Polygon\";\r\n// resultGeoJSON.coordinates = reducedLayerRegions;\r\n// } else {\r\n// resultGeoJSON.type = \"MultiPolygon\";\r\n// for (let reducedLayerRegion of reducedLayerRegions) {\r\n// resultGeoJSON.coordinates.push([reducedLayerRegion]);\r\n// }\r\n// }\r\n// return resultGeoJSON;\r\n// }\r\n\r\n// function checkIfExists(value) {\r\n// return value ? value : null;\r\n// }\r\n\r\n// /**\r\n// * checks object for needed parameters and if not exists, set to null\r\n// * @param {*} object original object to check\r\n// * @returns object with all entries\r\n// */\r\n// function checkObject(object) {\r\n// object = {\r\n// layer: checkIfExists(object.layer),\r\n// drawRegion: checkIfExists(object.drawRegion),\r\n// clear: checkIfExists(object.clear),\r\n// color: checkIfExists(object.color),\r\n// subtype: checkIfExists(object.subtype),\r\n// name: checkIfExists(object.name),\r\n// tree: checkIfExists(object.tree),\r\n// positionInRoiLayer: checkIfExists(object.positionInRoiLayer),\r\n// fullyLoaded: checkIfExists(object.fullyLoaded),\r\n// overlap: checkIfExists(object.overlap),\r\n// parentLayer: checkIfExists(object.parentLayer),\r\n// structureId: checkIfExists(object.structureId),\r\n// overlapRoiLayers: checkIfExists(object.overlapRoiLayers),\r\n// clickedOnRegion: checkIfExists(object.clickedOnRegion),\r\n// convert: checkIfExists(object.convert),\r\n// };\r\n// return object;\r\n// }\r\n\r\n/** Updates the objects currently being drawn.\r\n *\r\n * @param {Object} layer Structure being edited {regionRois: [], inverted: Bool}\r\n * @param {Object} drawRegion Objects inside the structure: {regions: [[x:, y: ], ...], inverted: Bool}\r\n * @param {Bool} clear Delete mode?\r\n * @param {String} color Color of the currently selected structure (#012DEF)\r\n * @param {Bool} subtype Whether or not the annotation is a subtype.\r\n * @param {String} name Name of the structure.\r\n */\r\nexport function updateDrawLayer(\r\n layer,\r\n drawRegion,\r\n clear,\r\n color,\r\n subtype,\r\n name,\r\n bufferSize\r\n) {\r\n // drawRegionRois -> region that was clicked on\r\n let drawRegionRois = drawRegion.regions.map((regions) => {\r\n return new RegionROI({\r\n regions: regions,\r\n color1: color,\r\n subtype: subtype,\r\n name: name,\r\n });\r\n });\r\n let multiLayerRegions = layer.regionRois.map((roi) => roi.regions);\r\n let multiDrawRegions = drawRegionRois.map((roi) => roi.regions);\r\n let transformResult = turf.union(\r\n turf.multiPolygon(multiDrawRegions),\r\n turf.multiPolygon(multiLayerRegions)\r\n );\r\n if (bufferSize && bufferSize !== 0) {\r\n transformResult = buffer(transformResult, bufferSize * 100);\r\n }\r\n\r\n layer.regionRois = [];\r\n let coordArray = [];\r\n if (transformResult === null) {\r\n coordArray = [];\r\n } else if (transformResult.geometry.type === \"Polygon\") {\r\n coordArray = [transformResult.geometry.coordinates];\r\n } else {\r\n coordArray = transformResult.geometry.coordinates;\r\n }\r\n for (let coordinates of coordArray) {\r\n let roiToAdd = createRegionRoi(\r\n coordinates,\r\n color,\r\n subtype,\r\n name,\r\n null,\r\n null\r\n );\r\n if (roiToAdd.area > 0.1) layer.regionRois.push(roiToAdd);\r\n }\r\n}\r\n\r\n/** Creates a ROI object.\r\n *\r\n * @param {Array} regions Array of coordninate arrays: [[x,y], ..., [x,y]]\r\n * @param {String} color #012DEF\r\n * @param {Bool} subtype Is the ROI a subtype or not?\r\n * @param {String} name Name of the object structure, e.g. \"Base ROI\"\r\n * @param {Bool} fullyLoaded\r\n * @param {Int} structureId Id of the objects structure.\r\n * @param {Bool} isObject Is the ROI an object for object detection? Defaults to false.\r\n * @returns\r\n */\r\nexport function createRegionRoi(\r\n regions,\r\n color,\r\n isSubtype,\r\n name,\r\n fullyLoaded,\r\n structureId,\r\n isObject = false\r\n) {\r\n return new RegionROI({\r\n regions: regions,\r\n color1: color,\r\n subtype: isSubtype,\r\n name: name,\r\n fullyLoaded: fullyLoaded,\r\n structureId: structureId,\r\n isObject: isObject,\r\n });\r\n}\r\n\r\nexport function turfPolyToRegionRois(\r\n poly,\r\n color,\r\n isSubtype,\r\n name,\r\n fullyLoaded,\r\n structureId\r\n) {\r\n let coordArray = [];\r\n if (poly === null) {\r\n coordArray = [];\r\n } else if (poly.geometry.type === \"Polygon\") {\r\n coordArray = [poly.geometry.coordinates];\r\n } else {\r\n coordArray = poly.geometry.coordinates;\r\n }\r\n return coordArray.map((coordinates) => {\r\n return createRegionRoi(\r\n coordinates,\r\n color,\r\n isSubtype,\r\n name,\r\n fullyLoaded,\r\n structureId\r\n );\r\n });\r\n}\r\n\r\n/**\r\n * Checks if a ROI is inside its parentlayer,\r\n * calculates resulting polygon for overlapping polygons.\r\n *\r\n * @param {Object} layer Structure being edited {regionRois: [], inverted: Bool}\r\n * @param {Object} drawRegion Objects inside the structure: {regions: [RegionROI, ...], inverted: Bool}\r\n * @param {Bool} clear Delete mode?\r\n * @param {String} color Color of the currently selected structure (#012DEF)\r\n * @param {Bool} isSubtype Whether or not the annotation is a subtype.\r\n * @param {String} name Name of the structure.\r\n * @param {rTree} tree R Tree containing structure information of the selected layer\r\n * @param {Bool} positionInRoiLayer Is the object inside a ROI Layer?\r\n * @param {Bool} fullyLoaded\r\n * @param {Bool} overlap\r\n * @param {Object} parentLayer The parent structure as object. Prevents annotations outside of paranet layer.\r\n * @param {Int} structureId The id of the structure.\r\n * @param {Array} overlapRoiLayers List of all ROI Layers, 1 for each struct, substruct and subtypes of the same parent. Depends on the checkboxes set in remove overlaps.\r\n * @param {Object} clickedOnRoi The ROI the user clicked on to begin with, if any.\r\n * @param {Bool} isObject Is this an object detection annotation? Defaults to false.\r\n * @param {Bool} convert (Not used). Whether or not to convert. Defaults to false.\r\n */\r\nexport function updateLayer(\r\n layer,\r\n drawRegion,\r\n clear,\r\n color,\r\n isSubtype,\r\n name,\r\n tree,\r\n positionInRoiLayer,\r\n fullyLoaded,\r\n overlap,\r\n parentLayer,\r\n structureId,\r\n overlapRoiLayers,\r\n clickedOnRoi,\r\n isObject = false\r\n) {\r\n let historyItem = [];\r\n let histId = structureId;\r\n // drawRegionRois -> region that was clicked on\r\n // Creates a Region ROI for the freshly created ROI\r\n let drawRegionRois = [];\r\n for (let regionRoi of drawRegion.regions) {\r\n drawRegionRois.push(regionRoi);\r\n }\r\n\r\n // Extract the regions of the freshly created ROI\r\n let multiDrawRegions = drawRegionRois.map((roi) => roi.regions);\r\n\r\n // Filter with Base ROI and Parent Annotations\r\n if (parentLayer && parentLayer.tree && !clear) {\r\n let parentRegionRois = getTreeItemsFromRois(\r\n parentLayer.tree,\r\n drawRegionRois\r\n );\r\n // Extract the regions of parent regions\r\n let multiParentRegions = parentRegionRois.map((roi) => roi.regions);\r\n // Check if in parent region\r\n try {\r\n let poly1 = turf.multiPolygon(multiDrawRegions);\r\n poly1 = turf.simplify(poly1, {\r\n tolerance: 0.05,\r\n highQuality: false,\r\n });\r\n let poly2 = turf.multiPolygon(multiParentRegions);\r\n let intersection = turf.intersect(poly1, poly2);\r\n\r\n if (intersection) {\r\n multiDrawRegions = turfPolyToRegionRois(\r\n intersection,\r\n color,\r\n isSubtype,\r\n name,\r\n fullyLoaded,\r\n structureId\r\n ).map((roi) => roi.regions);\r\n } else {\r\n multiDrawRegions = [];\r\n window.showWarningSnackbar(\"Can only be drawn inside parent regions.\");\r\n return;\r\n }\r\n } catch (e) {\r\n window.openErrorDialog(e);\r\n return;\r\n }\r\n }\r\n\r\n // Remove Overlaps, if checkbox is active\r\n if (!clear && overlapRoiLayers && overlapRoiLayers.length > 0) {\r\n for (let overlapRoiLayer of overlapRoiLayers) {\r\n if (overlapRoiLayer.layer.regionRois.length > 0) {\r\n // get all Regions that overlap with drawRegion\r\n if (!isObject && overlapRoiLayer.tree) {\r\n let overlapItems = [];\r\n for (let drawRoi of drawRegionRois) {\r\n let drawPoly = turf.polygon(drawRoi.regions);\r\n overlapRoiLayer.tree\r\n .search(drawRoi.treeItem)\r\n .filter((treeItem) => treeItem.roi.isObject === isObject)\r\n .forEach((treeItem) => {\r\n if (clickedOnRoi && treeItem.roi.uuid === clickedOnRoi.uuid)\r\n return;\r\n let poly = turf.polygon(treeItem.roi.regions);\r\n let isIntersecting = true;\r\n try {\r\n isIntersecting = !turf.booleanDisjoint(poly, drawPoly);\r\n } catch (e) {\r\n console.log(\r\n \"intersection check failed, treeting polygon as intersecting!\"\r\n );\r\n isIntersecting = true;\r\n }\r\n if (isIntersecting) {\r\n overlapItems.push(treeItem.roi);\r\n }\r\n });\r\n }\r\n\r\n let multiLayerRegions = overlapItems.map((roi) => roi.regions);\r\n let transformResult = null;\r\n let poly1 = turf.multiPolygon(multiDrawRegions);\r\n let poly2 = turf.multiPolygon(multiLayerRegions);\r\n transformResult = turf.difference(poly1, poly2);\r\n if (transformResult) {\r\n // Reduce size of ROIs for good measure\r\n transformResult = buffer(transformResult, -10);\r\n if (transformResult.geometry.coordinates[0].length > 0) {\r\n transformResult = turf.simplify(transformResult, {\r\n tolerance: 0.05,\r\n highQuality: false,\r\n });\r\n }\r\n }\r\n\r\n let coordArray = [];\r\n if (transformResult === null) {\r\n coordArray = [];\r\n } else if (transformResult.geometry.type === \"Polygon\") {\r\n coordArray = [transformResult.geometry.coordinates];\r\n } else {\r\n coordArray = transformResult.geometry.coordinates;\r\n }\r\n drawRegionRois = [];\r\n for (let coordinates of coordArray) {\r\n if (coordinates[0].length < 1) continue;\r\n let roiToAdd = createRegionRoi(\r\n coordinates,\r\n color,\r\n isSubtype,\r\n name,\r\n fullyLoaded,\r\n structureId,\r\n isObject\r\n );\r\n if (roiToAdd.area > 2) drawRegionRois.push(roiToAdd);\r\n }\r\n multiDrawRegions = drawRegionRois.map((roi) => roi.regions);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Add objects to structure trees\r\n if (tree) {\r\n let overlapItems = [];\r\n for (let drawRoi of drawRegionRois) {\r\n let drawPoly = turf.polygon(drawRoi.regions);\r\n tree\r\n .search(drawRoi.treeItem)\r\n .filter((treeItem) => treeItem.roi.isObject === isObject)\r\n .forEach((treeItem) => {\r\n // if drawPoly is subtype, filter all annotations that aren't of the same subtype\r\n if (isSubtype && clear) {\r\n overlapItems.push(treeItem.roi);\r\n treeItem.roi.comment = \"\";\r\n tree.remove(treeItem);\r\n historyItem.push({\r\n add: false,\r\n id: histId,\r\n roi: treeItem.roi.copy(),\r\n });\r\n\r\n return;\r\n }\r\n let poly = turf.polygon(treeItem.roi.regions);\r\n let isIntersecting = true;\r\n try {\r\n isIntersecting = !turf.booleanDisjoint(poly, drawPoly);\r\n } catch (e) {\r\n console.log(\r\n \"intersection check failed, treating polygon as intersecting!\"\r\n );\r\n isIntersecting = true;\r\n }\r\n if (isIntersecting) {\r\n overlapItems.push(treeItem.roi);\r\n treeItem.roi.comment = \"\";\r\n tree.remove(treeItem);\r\n historyItem.push({\r\n add: false,\r\n id: structureId,\r\n roi: treeItem.roi.copy(),\r\n });\r\n }\r\n });\r\n //overlapItems.push(drawRoi);\r\n }\r\n let multiLayerRegions = overlapItems.map((roi) => roi.regions);\r\n let transformResult = null;\r\n let transformResultInfo = null;\r\n\r\n // Add a polygon\r\n if (!clear) {\r\n if (isObject) {\r\n // Ensure both the new and the old ROI are included.\r\n // No transformation\r\n multiLayerRegions.forEach((region) => {\r\n multiDrawRegions.push(region);\r\n });\r\n transformResult = turf.multiPolygon(multiDrawRegions);\r\n }\r\n // Non-Object ROI was clicked\r\n // Transform according to settings\r\n else {\r\n let poly1 = turf.multiPolygon(multiDrawRegions);\r\n // No overlapping regions\r\n if (multiLayerRegions.length === 0 && !overlap) {\r\n transformResult = poly1;\r\n }\r\n // Overlapping regions exist\r\n else {\r\n let poly2 = turf.multiPolygon(multiLayerRegions);\r\n try {\r\n transformResult = overlap\r\n ? turf.intersect(poly1, poly2)\r\n : turf.union(poly1, poly2);\r\n } catch (e) {\r\n console.debug(\"Overlap error:\", e);\r\n window.openErrorDialog(\r\n \"Overlap Error!\\n Probably too many objects to compute:\\n\" + e\r\n );\r\n }\r\n }\r\n }\r\n }\r\n // Remove a polygon\r\n else {\r\n if (!isObject) {\r\n if (overlapItems.length <= 100) {\r\n transformResult = turf.difference(\r\n turf.multiPolygon(multiLayerRegions),\r\n turf.multiPolygon(multiDrawRegions)\r\n );\r\n transformResultInfo = differenceRegionsAndInfo(\r\n overlapItems,\r\n transformResult\r\n );\r\n } else {\r\n window.showWarningSnackbar(\r\n \"Too many intersections, \" +\r\n overlapItems.length +\r\n \" objects deleted whole!\"\r\n );\r\n }\r\n }\r\n }\r\n\r\n // The new coordinates of the transformed object\r\n let coordArray = [];\r\n if (transformResult === null) {\r\n coordArray = [];\r\n } else if (transformResult.geometry.type === \"Polygon\") {\r\n coordArray = [transformResult.geometry.coordinates];\r\n } else {\r\n coordArray = transformResult.geometry.coordinates;\r\n }\r\n let firstRoiToAdd = null;\r\n for (let idx in coordArray) {\r\n let roiToAdd = createRegionRoi(\r\n coordArray[idx],\r\n transformResultInfo ? transformResultInfo[idx].color : color,\r\n transformResultInfo ? transformResultInfo[idx].subtype : isSubtype,\r\n transformResultInfo ? transformResultInfo[idx].name : name,\r\n fullyLoaded,\r\n transformResultInfo\r\n ? transformResultInfo[idx].structureId\r\n : structureId,\r\n isObject\r\n );\r\n if (roiToAdd.area > 2) {\r\n if (idx === \"0\") {\r\n firstRoiToAdd = roiToAdd;\r\n }\r\n tree.insert(roiToAdd.treeItem);\r\n historyItem.push({ add: true, id: histId, roi: roiToAdd });\r\n }\r\n }\r\n layer.regionRois = tree.all().map((treeItem) => treeItem.roi);\r\n if (firstRoiToAdd !== null && positionInRoiLayer >= 0) {\r\n let fromIndex = layer.regionRois.findIndex(\r\n (item) => item.uuid === firstRoiToAdd.uuid\r\n );\r\n arraymove(layer.regionRois, fromIndex, positionInRoiLayer);\r\n }\r\n }\r\n window.projectHistory.add(historyItem);\r\n}\r\n\r\n/**\r\n * Special findRegion function for CopyTools, since they require additional information of the layer\r\n * @param {Object} p mouse position {x:, y: }\r\n * @param {Array} roiLayers The layers containing all ROIs.\r\n * @param {Array} structures Structures of the project.\r\n * @param {Bool} includeBaseROI Whether or not to include the Base ROI.\r\n * @returns {[*, []]} Array with index of layer where region was found in and array with region in polygon form\r\n */\r\nexport function findRoi(p, roiLayers, structures, includeBaseROI) {\r\n let resultRoi = null;\r\n let targetLayerIndex = -1;\r\n\r\n for (let i = 0; i < roiLayers.length; i++) {\r\n if (\r\n structures[i].visible &&\r\n (includeBaseROI || !structures[i].inversed) &&\r\n roiLayers[i].layer.regionRois.length > 0\r\n ) {\r\n let overlapTreeItems = roiLayers[i].tree.search({\r\n minX: parseInt(p.x, 10),\r\n minY: parseInt(p.y, 10),\r\n maxX: parseInt(p.x, 10),\r\n maxY: parseInt(p.y, 10),\r\n });\r\n for (let treeItem of overlapTreeItems) {\r\n if (pointInside(p, treeItem.roi)) {\r\n if (resultRoi) {\r\n if (resultRoi.area > treeItem.roi.area) {\r\n resultRoi = treeItem.roi;\r\n targetLayerIndex = i;\r\n }\r\n } else {\r\n resultRoi = treeItem.roi;\r\n targetLayerIndex = i;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return [targetLayerIndex, resultRoi];\r\n}\r\n\r\nfunction arraymove(arr, fromIndex, toIndex) {\r\n var element = arr[fromIndex];\r\n arr.splice(fromIndex, 1);\r\n arr.splice(toIndex, 0, element);\r\n}\r\n\r\n/**\r\n * Validates rois in the given array and corrects them in place if necessary.\r\n * Goes to great lengths to attempt to find the correct structure for each roi.\r\n * When provided, uses fallback if no matching structure was found.\r\n * @param {array[RegionROI]} rois Rois to validate and correct.\r\n * @param {array[object]} structures The structures of the project.\r\n * @param {number} fallbackStructureIndex Optional. The index of the fallback structure to use if no matching structure was found. Defaults to null.\r\n */\r\nexport function validateAndCorrectRois(\r\n rois,\r\n structures,\r\n fallbackStructureIndex = null\r\n) {\r\n // Validate and correct rois.\r\n rois.forEach((roi) => {\r\n // Find the corresponding structure by id.\r\n const suggestedStructure = structures.find(\r\n (structure) => structure.id === roi.structureId\r\n );\r\n if (\r\n suggestedStructure?.color === roi.color &&\r\n suggestedStructure.label === roi.subtypeName\r\n ) {\r\n // The roi is valid.\r\n return;\r\n }\r\n\r\n // The roi is invalid. Correct it.\r\n // Check if id and color match.\r\n if (suggestedStructure?.color === roi.color) {\r\n roi.subtypeName = suggestedStructure.label;\r\n return;\r\n }\r\n\r\n // Check if id and label match.\r\n if (suggestedStructure?.label === roi.subtypeName) {\r\n roi.color = suggestedStructure.color;\r\n return;\r\n }\r\n\r\n // Find the corresponding structure by color and label.\r\n const realStructureByNameAndColor = structures.find(\r\n (structure) =>\r\n structure.color === roi.color && structure.label === roi.subtypeName\r\n );\r\n\r\n if (realStructureByNameAndColor) {\r\n roi.structureId = realStructureByNameAndColor.id;\r\n return;\r\n }\r\n\r\n // Find the corresponding structure by parent and color.\r\n const [suggestedStructChildren] = generateChildrenList(structures).filter(\r\n (s) => s[0].id === roi.structureId\r\n );\r\n if (suggestedStructChildren) {\r\n const realStructureByParentAndColor = suggestedStructChildren.find(\r\n (structure) => structure.color === roi.color\r\n );\r\n if (realStructureByParentAndColor) {\r\n roi.structureId = realStructureByParentAndColor.id;\r\n roi.subtypeName = realStructureByParentAndColor.label;\r\n return;\r\n }\r\n\r\n // Find the corresponding structure by parent and label.\r\n const realStructureByParentAndLabel = suggestedStructChildren.find(\r\n (structure) => structure.label === roi.subtypeName\r\n );\r\n if (realStructureByParentAndLabel) {\r\n roi.structureId = realStructureByParentAndLabel.id;\r\n roi.color = realStructureByParentAndLabel.color;\r\n return;\r\n }\r\n }\r\n\r\n const newlyAssignedStructure = structures.find(\r\n (structure) => structure.id === roi.structureId\r\n );\r\n\r\n if (!newlyAssignedStructure) {\r\n // The roi is invalid, cannot be corrected, and no replacement structure was found and no fallback structure was provided.\r\n if (fallbackStructureIndex === null) {\r\n console.debug(\r\n 'Could not correct roi with id \"' +\r\n roi.id +\r\n '\". No structure with color \"' +\r\n roi.color +\r\n '\" and label \"' +\r\n roi.subtypeName +\r\n '\" found. No structure matching structure with id \"' +\r\n roi.structureId +\r\n '\" found. No fallback structure provided.'\r\n );\r\n return;\r\n }\r\n\r\n // The roi is invalid, cannot be corrected, and no replacement structure was found. Use the fallback structure instead.\r\n const fallbackStructure = structures[fallbackStructureIndex];\r\n roi.structureId = fallbackStructure.id;\r\n roi.color = fallbackStructure.color;\r\n roi.subtypeName = fallbackStructure.label;\r\n\r\n console.debug(\r\n 'Corrected roi with id \"' +\r\n roi.id +\r\n '\" using fallback structure: Color \"' +\r\n roi.color +\r\n '\" label \"' +\r\n roi.subtypeName +\r\n '\"'\r\n );\r\n return;\r\n }\r\n\r\n // The roi is invalid and cannot be corrected.\r\n roi.structureId = newlyAssignedStructure.id;\r\n roi.color = newlyAssignedStructure.color;\r\n roi.subtypeName = newlyAssignedStructure.label;\r\n console.debug(\r\n 'Could not correct roi with id \"' +\r\n roi.id +\r\n '\". No structure with color \"' +\r\n roi.color +\r\n '\" and label \"' +\r\n roi.subtypeName +\r\n '\" found. Original structure id: \"' +\r\n roi.structureId +\r\n '\". Assigning it to its suggested structure \"' +\r\n newlyAssignedStructure.label +\r\n '\" with id \"' +\r\n newlyAssignedStructure.id +\r\n '\" and color \"' +\r\n newlyAssignedStructure.color +\r\n '\" instead.'\r\n );\r\n return;\r\n });\r\n}\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n// import classnames from \"classnames\";\r\nimport { DialogTitle, Dialog, LinearProgress } from \"@mui/material\";\r\nimport CircularProgress from \"@mui/material/CircularProgress\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\nimport \"./Spinloader.css\";\r\n\r\nconst SpinloaderContext = React.createContext();\r\n\r\nexport const withSpinloader = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withSpinloader(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\nconst styles = () => ({\r\n progressContainer: {\r\n position: \"fixed\",\r\n top: 64,\r\n left: 0,\r\n right: 390,\r\n bottom: 0,\r\n zIndex: 100000,\r\n margin: \"auto\",\r\n textAlign: \"center\",\r\n height: 50,\r\n },\r\n dialog: { pointerEvents: \"none\", right: 500, top: 60 },\r\n message: {\r\n display: \"inline-block\",\r\n position: \"relative\",\r\n top: -10,\r\n marginLeft: 10,\r\n },\r\n linearProgress: {\r\n height: 10,\r\n },\r\n greyedOutBackground: {\r\n background: \"rgba(0,0,0,0.5)\",\r\n top: 0,\r\n left: 0,\r\n width: \"10000px\",\r\n height: \"10000px\",\r\n position: \"fixed\",\r\n zIndex: 999999,\r\n },\r\n});\r\n\r\n// this is the main component, it has to be added at the root of the app.\r\n// all components that use withSpinloader(...) will have access to it via this.props.spinloader...\r\nclass SpinloaderProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n rightWidth: 100,\r\n show: false,\r\n messagePresent: false,\r\n message: \"\",\r\n indefinite: true,\r\n progress: 0,\r\n };\r\n this.timeout = null;\r\n this.start_time = performance.now();\r\n }\r\n /**\r\n * Shows an indefinte spinloader\r\n */\r\n show() {\r\n this.start_time = performance.now();\r\n if (this.state.show) return;\r\n this.setState(() => ({\r\n show: true,\r\n messagePresent: false,\r\n message: \"\",\r\n indefinite: true,\r\n }));\r\n }\r\n\r\n /**\r\n * Shows a progressbar with a prominent message above\r\n * @param {JSON} progressObject JSON Object with message and progress {message: , progress: }\r\n */\r\n showWithProgress = (progressObject) => {\r\n this.start_time = performance.now();\r\n const progress = parseInt(progressObject.progress);\r\n this.setState({\r\n show: true,\r\n messagePresent: true,\r\n message: progressObject.message + \": \" + progress + \"%\",\r\n progress: isNaN(progress) ? 0 : progress,\r\n indefinite: false,\r\n });\r\n clearTimeout(this.timeout);\r\n };\r\n\r\n showWithAutoProgress = (message, seconds) => {\r\n this.start_time = performance.now();\r\n this.setState(\r\n {\r\n show: true,\r\n messagePresent: true,\r\n message: message,\r\n progress: 0,\r\n indefinite: false,\r\n currentSecond: 0,\r\n predictedSeconds: parseInt(seconds),\r\n },\r\n () => {\r\n setTimeout(() => this.updateAutoProgress(), 1000);\r\n }\r\n );\r\n };\r\n updateAutoProgress = () => {\r\n if (this.state.show) {\r\n const progress =\r\n (100 * this.state.currentSecond) / this.state.predictedSeconds;\r\n this.setState({\r\n currentSecond: this.state.currentSecond + 1,\r\n progress: progress,\r\n });\r\n if (progress < 100) {\r\n setTimeout(() => this.updateAutoProgress(), 1000);\r\n } else {\r\n this.showWithMessage(this.state.message);\r\n }\r\n }\r\n };\r\n /**\r\n * Shows an indefinite loader with a prominent message above\r\n * @param {String} message The info to be displayed\r\n */\r\n showWithMessage = (message) => {\r\n this.start_time = performance.now();\r\n this.setState({\r\n show: true,\r\n messagePresent: true,\r\n message: message,\r\n indefinite: true,\r\n });\r\n };\r\n\r\n /**\r\n * Shows Spinloader and hides it after a defined time to prevent constant blocking of the screen.\r\n * @param {int} scenesLeft Scenes to analyse. Used for delay calculation.\r\n * @param {int} timeoutSeconds Seconds to wait until hiding spinloader\r\n */\r\n showWithTimeout(scenesLeft, timeoutSeconds = 30) {\r\n this.start_time = performance.now();\r\n let waitTime = 300000;\r\n if (scenesLeft) {\r\n waitTime = scenesLeft * timeoutSeconds * 1000;\r\n waitTime = Math.max(waitTime, 60000);\r\n }\r\n this.setState({ show: true });\r\n this.timeout = setTimeout(() => this.timeoutHide(), waitTime);\r\n }\r\n\r\n /**\r\n * Increase the remaining time until hiding spinloader depending on the amount of scenes left.\r\n * @param {int} scenesLeft Scenes left to analyse. Used for delay calculation.\r\n * @param {number} timeoutSeconds Optional. Seconds to wait per scene until hiding spinloader. Default is 30 seconds.\r\n */\r\n resetTimer(scenesLeft, timeoutSeconds = 30) {\r\n let waitTime = scenesLeft * timeoutSeconds * 1000;\r\n waitTime = Math.min(waitTime, 60000);\r\n clearTimeout(this.timeout);\r\n if (scenesLeft > 0) {\r\n this.timeout = setTimeout(() => this.timeoutHide(), waitTime);\r\n } else {\r\n this.hide();\r\n }\r\n }\r\n\r\n measureTime = () => {\r\n const executionTime = (performance.now() - this.start_time) / 1000;\r\n if (executionTime > 10) {\r\n const minutes = parseInt(executionTime / 60, 10);\r\n const seconds = parseInt(executionTime % 60, 10);\r\n const logMessage = `Spinner active time: ${minutes} minutes and ${seconds} seconds!`;\r\n console.debug(logMessage);\r\n }\r\n };\r\n\r\n /**\r\n * Hides the spinloader.\r\n */\r\n hide() {\r\n this.measureTime();\r\n clearTimeout(this.timeout);\r\n this.setState(() => ({ show: false, messagePresent: false, message: \"\" }));\r\n }\r\n\r\n timeoutHide() {\r\n this.hide();\r\n window.showWarningSnackbar(\r\n \"Warning: Timeout! Process is taking especially long.\"\r\n );\r\n }\r\n\r\n hideTimeDelayed(delay) {\r\n setTimeout(() => {\r\n this.hide();\r\n }, delay);\r\n }\r\n\r\n load(func) {\r\n this.setState({ show: true });\r\n setTimeout(() => {\r\n func();\r\n this.setState({ show: false, messagePresent: false });\r\n }, 0);\r\n }\r\n\r\n setRightWidth(width) {\r\n this.setState({ rightWidth: width });\r\n }\r\n\r\n render() {\r\n const { classes } = this.props;\r\n return (\r\n this.show(),\r\n showWithTimeout: (numberScenes) => this.showWithTimeout(numberScenes),\r\n showWithProgress: (progObject) => this.showWithProgress(progObject),\r\n showWithAutoProgress: (message, seconds) =>\r\n this.showWithAutoProgress(message, seconds),\r\n showWithMessage: (message) => this.showWithMessage(message),\r\n resetTimer: (numberRestScenes) => this.resetTimer(numberRestScenes),\r\n hide: () => this.hide(),\r\n hideTimeDelayed: (delay) => this.hideTimeDelayed(delay),\r\n load: (callback) => this.load(callback),\r\n setRightWidth: (width) => this.setRightWidth(width),\r\n }}\r\n >\r\n {this.props.children}\r\n {this.state.show && (\r\n e.preventDefault()}\r\n >\r\n \r\n {this.state.messagePresent ? (\r\n // Dialog option for more text\r\n \r\n \r\n \r\n
{this.state.message}
\r\n
\r\n {this.state.indefinite ? (\r\n \r\n ) : (\r\n \r\n )}\r\n
\r\n ) : (\r\n // Normal, indefinite spinloader\r\n \r\n )}\r\n \r\n \r\n )}\r\n \r\n );\r\n }\r\n}\r\n\r\nSpinloaderProvider.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n children: PropTypes.element.isRequired,\r\n};\r\n\r\nexport default withStyles(styles)(SpinloaderProvider);\r\n","// Backend.jsx\r\n\r\n// Copyright HS Analysis GmbH, 2019\r\n// Author: Sebastian Murgul, Viktor Eberhardt, Lukas Buess, Valentin Haas\r\n\r\n// Framework imports\r\nimport { HubConnectionBuilder, LogLevel } from \"@aspnet/signalr\";\r\nimport { io } from \"socket.io-client\";\r\n\r\n// External packages\r\nimport { v4 as uuidv4 } from \"uuid\";\r\n\r\n// HSA imports\r\nimport {\r\n AudioRoi,\r\n ImageRoi,\r\n ModificationStatus,\r\n RoiType,\r\n} from \"../components/RoiTypes\";\r\nimport { authenticationService } from \"../services\";\r\nimport {\r\n convertDateToDayString,\r\n convertDateToShortIsoString,\r\n} from \"../../common/utils/Localization\";\r\nimport { validateInstance } from \"./Utils\";\r\nimport AITrainingDataContainer from \"../components/AITrainingDataContainer\";\r\nimport AITrainingSettings from \"../components/AITrainingSettings\";\r\nimport AIModel2ProjectTypeMapping from \"../../aiViewer/components/AIModel2ProjectTypeMapping\";\r\nimport InstantAnalysisModule from \"../components/InstantAnalysisModule\";\r\nimport Structure from \"../components/Structure\";\r\n\r\nconst PYTHON_SERVER_PORT = 8051;\r\nconst PYTHON_SERVER_URL = `http://127.0.0.1:${PYTHON_SERVER_PORT}`;\r\n\r\nlet jobProgressConnection = new HubConnectionBuilder()\r\n .withUrl(\"/jobprogress\")\r\n .configureLogging(LogLevel.Warning)\r\n .build();\r\njobProgressConnection.serverTimeoutInMilliseconds = 14 * 24 * 60 * 60 * 1000; // 2 weeks\r\njobProgressConnection.keepAliveIntervalInMilliseconds =\r\n 14 * 24 * 60 * 60 * 1000; // 2 weeks\r\n\r\n/**\r\n * injects authorization header into the fetch() function\r\n * @param {String} url backend endpoint\r\n * @param {Object} config additional stuff https://developer.mozilla.org/de/docs/Web/API/Fetch_API/Using_Fetch\r\n * @returns {Promise} result of fetch function\r\n */\r\nfunction fetch_auth(url, config = {}) {\r\n // return authorization header with jwt token\r\n const currentUser = authenticationService.currentUserValue;\r\n if (!currentUser || !currentUser.token) {\r\n authenticationService.logout();\r\n return Promise.reject(\"No user token available!\");\r\n }\r\n if (currentUser && currentUser.token) {\r\n if (!config.headers) config.headers = {};\r\n\r\n // place bearer token\r\n config.headers.Authorization = `Bearer ${currentUser.token}`;\r\n }\r\n return fetch(url, config);\r\n}\r\n\r\nfunction validateResponse(response, permissionString) {\r\n if (response.status === 403) {\r\n window.showErrorSnackbar(\r\n \"Current user has no permission to \" + permissionString + \"!\"\r\n );\r\n return { success: false, status: response.status };\r\n } else {\r\n return response.json();\r\n }\r\n}\r\n\r\nfunction validateResponseJSON(json, callback) {\r\n if (json.success === false && json.message !== \"\") {\r\n window.showErrorSnackbar(json.message);\r\n }\r\n callback(json);\r\n}\r\n\r\nfunction showHandledProblems(response, errorMessage) {\r\n if (response.permissionDenied === true) {\r\n window.showErrorSnackbar(errorMessage);\r\n }\r\n if (typeof response.errorMessage === \"string\" && window.openErrorDialog) {\r\n window.openErrorDialog(response.errorMessage);\r\n }\r\n return response;\r\n}\r\n\r\n/**\r\n * Generalized function for logging errors in the console.\r\n * Filters out resposnes that are not json.\r\n * @param {string} actionName Name of the action the error occured in.\r\n * @param {string} error The actual error message.\r\n */\r\nfunction customErrorPrint(actionName, error) {\r\n if (error === \"SyntaxError: Unexpected token < in JSON at position 0\") {\r\n console.error(\"Backend could not be connected!\");\r\n return;\r\n }\r\n\r\n console.error(\"Error occured in\", actionName, error);\r\n}\r\n\r\n/**\r\n * Default handeling on a successfully parsed json response that returns an \"error\" key to report errors.\r\n * @param {JSON} res Parsed json object from response.\r\n * @param {Function} callback The function to call to handle a successful request.\r\n * @param {Function} error Optional. The function to call on any error.\r\n */\r\nfunction handleJsonResponse(res, callback, error = () => {}) {\r\n if (res.error) {\r\n console.error(error);\r\n error(res.error);\r\n } else {\r\n callback(res);\r\n }\r\n}\r\n\r\nexport default class Backend {\r\n static validateResponse(response) {\r\n if (!response.ok) {\r\n throw Error(response.statusText);\r\n }\r\n return response;\r\n }\r\n\r\n /**\r\n * UNSAFE: Bypasses authentication of .NET Core backend.\r\n * Returns the socket directly to the python server.\r\n * @returns {SocketIOClient.Socket} SocketIOClient.Socket to python server.\r\n */\r\n static getPythonServerSocket() {\r\n return io(PYTHON_SERVER_URL);\r\n }\r\n\r\n /**\r\n * Checks that the .NET backend can reach the python server via websockets.\r\n * For testing purposes only.\r\n */\r\n static ping() {\r\n fetch_auth(\"/api/websocket/ping\")\r\n .then((response) => response.text())\r\n .then((text) => console.debug(text))\r\n .catch((error) => console.error(error));\r\n }\r\n\r\n // #region Login Controller\r\n /**\r\n * Get user list from login-Page\r\n * @param {Function} callback Success callback\r\n */\r\n static getUserList(callback) {\r\n fetch(\"/api/login/userlist\")\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n // #endregion\r\n\r\n // #region Admin Controller\r\n static createUser(user, callback) {\r\n fetch_auth(`/api/admin/createuser`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(user),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static deleteUser(id, callback) {\r\n fetch_auth(`/api/admin/deleteuser`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(id),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static updateUser(user, callback) {\r\n fetch_auth(`/api/admin/updateuser`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(user),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static loadUserList(callback) {\r\n fetch_auth(`/api/admin/userlist`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static loadGroupList(callback) {\r\n fetch_auth(`/api/admin/grouplist`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static createGroup(group, callback) {\r\n fetch_auth(`/api/admin/createGroup`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(group),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static updateGroup(group, callback) {\r\n fetch_auth(`/api/admin/updateGroup`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(group),\r\n })\r\n .then((response) => validateResponse(response, \"edit groups\"))\r\n .then(callback);\r\n }\r\n\r\n static updateUserGroups(userId, userGroups, callback) {\r\n fetch_auth(`/api/admin/updateUserGroups?id=` + userId, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(userGroups),\r\n })\r\n .then((response) => validateResponse(response, \"edit groups\"))\r\n .then((json) => validateResponseJSON(json, callback));\r\n }\r\n\r\n static deleteGroup(id, callback) {\r\n fetch_auth(`/api/admin/deleteGroup`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(id),\r\n })\r\n .then((response) => validateResponse(response, \"edit groups\"))\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * loads system configuration from appsettings.json\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static async readAppSettings() {\r\n return fetch_auth(`/api/admin/appsettings`)\r\n .then((response) => response.json())\r\n .catch((error) => console.log(error));\r\n }\r\n\r\n /**\r\n * writes system configuration from appsettings.json\r\n * @param {Object} appsettings Appsettings Dictionary\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static writeAppSettings(appsettings, callback) {\r\n fetch_auth(`/api/admin/appsettings`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(appsettings),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * checks, the changes for the case settings to show in frontend in dialog\r\n * @param {Object} appsettings Appsettings Dictionary\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static getPossibleCaseSettingsChanges(appsettings, callback) {\r\n fetch_auth(`/api/admin/check_update_case_settings`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(appsettings),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * loads system configuration from appsettings.json\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static readAppSettingsLicensing(callback) {\r\n fetch(`/api/about/appsettingslicensing`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * writes system configuration from appsettings.json\r\n * @param {Object} appsettings Appsettings Dictionary\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static writeAppSettingsLicensing(appsettings, callback) {\r\n fetch(`/api/about/appsettingslicensing`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(appsettings),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * loads system configuration from appsettings.json\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static readImporterSettings(callback) {\r\n fetch_auth(`/api/admin/importsettings`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * writes system configuration from appsettings.json\r\n * @param {Object} appsettings Appsettings Dictionary\r\n * @param {Function} callback Success callback with ome data model\r\n */\r\n static writeImporterSettings(appsettings, callback) {\r\n fetch_auth(`/api/admin/importsettings`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(appsettings),\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Deletes {../TEMP/files}-folder.\r\n * @param {Function} callback function after the deletion is done\r\n */\r\n static deleteTempFiles(callback) {\r\n fetch_auth(`/api/admin/delete_temp_files`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n // #endregion\r\n\r\n // #region User Controller\r\n /**\r\n * load list of groups of given user\r\n * @param {Function} callback Success callback\r\n */\r\n static getUserGroups(id, callback) {\r\n fetch_auth(`/api/user/getUserGroups?id=` + id)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * load list of groups of logged in user\r\n * @param {Function} callback Success callback\r\n */\r\n static getCurrentUserGroups(callback) {\r\n fetch_auth(`/api/user/getCurrentUserGroups`)\r\n .then((response) => {\r\n if (response.status === 204 || response.status === 401) {\r\n authenticationService.logout();\r\n }\r\n return response.json();\r\n })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Get currently logged in User\r\n * @param {Function} callback Success callback\r\n */\r\n static async getCurrentUser(callback) {\r\n fetch_auth(\"/api/user/current_user\")\r\n .then((response) => {\r\n if (response.status === 204 || response.status === 401) {\r\n authenticationService.logout();\r\n window.showErrorSnackbar(\r\n \"User not authenticated. Please log in again.\"\r\n );\r\n }\r\n return response.json();\r\n })\r\n .then((data) => {\r\n const user = data.user;\r\n user.group = data.group;\r\n if (!user.group) {\r\n // Force new login on missing user\r\n authenticationService.logout();\r\n window.showErrorSnackbar(\r\n \"Could not authenticate user. Are you logged in?\"\r\n );\r\n return;\r\n }\r\n callback(data.user);\r\n })\r\n .catch((error) => {\r\n console.error(error);\r\n });\r\n }\r\n\r\n /**\r\n * get user actions from database\r\n * @param {func} callback returns list of all user actions\r\n */\r\n static getUserActions(date, callback) {\r\n const dateFormated = date.toISOString();\r\n fetch_auth(`/api/user/get_user_actions?date=${dateFormated}`)\r\n .then((response) => {\r\n return response.json();\r\n })\r\n .then(callback);\r\n }\r\n\r\n /**\r\n *\r\n * @param {DateTime} date\r\n */\r\n static downloadUserActions(date) {\r\n const dateFormated = date.toISOString();\r\n const dateDay = convertDateToDayString(date);\r\n fetch_auth(`/api/user/download_user_actions?date=${dateFormated}`)\r\n .then((response) => {\r\n if (response.ok) {\r\n return response.blob();\r\n } else {\r\n window.showErrorSnackbar(\"Download Failed!\");\r\n return null;\r\n }\r\n })\r\n .then((blob) => {\r\n if (blob !== null) {\r\n var url = window.URL.createObjectURL(blob);\r\n var a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = dateDay + \"_userActions.csv\";\r\n document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox\r\n a.click();\r\n a.remove(); //afterwards we remove the element again\r\n }\r\n });\r\n }\r\n // #endregion\r\n\r\n // #region About Controller\r\n /**\r\n * loads version and release notes\r\n * @param {Function} callback Success callback\r\n */\r\n static getAbout(callback) {\r\n fetch(`/api/about/about`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * loads version code\r\n * @param {Function} callback Success callback\r\n */\r\n static getVersion(callback) {\r\n fetch(`/api/about/version`)\r\n .then((response) => response.json())\r\n .then(callback)\r\n .catch((error) => customErrorPrint(\"getVersion\", error));\r\n }\r\n\r\n /**\r\n * Get License Infos for LicensingPage\r\n * @param {function} callback Success callback\r\n */\r\n static getLicensingInfo(callback) {\r\n var requestOptions = {\r\n method: \"GET\",\r\n redirect: \"follow\",\r\n };\r\n\r\n fetch(\"/api/about/licensingInfo\", requestOptions)\r\n .then((response) => response.json())\r\n .then(callback)\r\n .catch((error) => console.error(\"Could not get licensing info:\", error));\r\n }\r\n\r\n /**\r\n * Get Operating System\r\n * @param {Function} callback Success callback\r\n */\r\n static getOS(callback) {\r\n fetch(\"/api/about/os\")\r\n .then((response) => response.text())\r\n .then((result) => {\r\n console.log(result);\r\n callback(result);\r\n })\r\n .catch((error) => console.error(\"Could not get OS information:\", error));\r\n }\r\n // #endregion\r\n\r\n // #region Cases Controller\r\n /**\r\n * List all cases of the logged in user\r\n * @param {Function} callback Success callback with list as parameter\r\n */\r\n static async listCases() {\r\n return fetch_auth(\"/api/cases/list\").then((response) => {\r\n if (response.status === 401) {\r\n console.log(\"not authenticated => logout\");\r\n authenticationService.logout();\r\n return;\r\n }\r\n return response.json();\r\n });\r\n }\r\n\r\n /**\r\n * Creates a new case in database\r\n *\r\n * @param {Object} data - Object with 2 arrays: caseColumns to create 1 case and files for the case files\r\n * @returns {Promise} - Resolves with responseData or rejects with error\r\n */\r\n static async createCase(data) {\r\n try {\r\n const response = await fetch_auth(\"/api/cases/create\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n });\r\n const { data: responseData } = await response.json();\r\n return Promise.resolve(responseData);\r\n } catch (error) {\r\n console.error(error);\r\n return Promise.reject(error);\r\n }\r\n }\r\n\r\n /**\r\n * Updates an existing case in the database based on ID\r\n *\r\n * @param {string} id - ID of the case to update\r\n * @param {Object} data - Object with 1 array: caseColumns to update 1 case\r\n * @returns {Promise} - Resolves with responseData or rejects with error\r\n */\r\n static async editCase(id, data) {\r\n try {\r\n const response = await fetch_auth(`/api/cases/edit/${id}`, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n });\r\n return Promise.resolve(response);\r\n } catch (error) {\r\n console.error(error);\r\n return Promise.reject(error);\r\n }\r\n }\r\n\r\n /**\r\n * Delete a specific case of the logged in user\r\n * @param {string} caseId ID of the case to delete\r\n */\r\n static async deleteCase(caseId) {\r\n return fetch_auth(`/api/cases/delete/${caseId}`, { method: \"DELETE\" }).then(\r\n (response) => {\r\n if (response.status === 401) {\r\n console.log(\"not authenticated => logout\");\r\n authenticationService.logout();\r\n return;\r\n }\r\n return response.json();\r\n }\r\n );\r\n }\r\n // #endregion\r\n\r\n // #region Rendering Controller\r\n /**\r\n * list all folders inside the given path\r\n * @param {*} path is the path to the folder the subfolders should be listed\r\n */\r\n static getDirectories(path) {\r\n return fetch_auth(`/api/admin/directories?path=${path}`).then(\r\n (response) => {\r\n if (response.status === 200) return response.json();\r\n if (response.status === 400) {\r\n window.showErrorSnackbar(\"Access to the path is denied.\");\r\n return null;\r\n }\r\n if (response.status === 401) {\r\n window.showErrorSnackbar(\r\n \"Access for authenticated admin users only.\"\r\n );\r\n return null;\r\n }\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Runs a instant analysis tool with real time updates using signalR\r\n * @param {Object} data Instant analysis configuration\r\n * @param {Function} callback Success callback\r\n * @param {Function} errorCallback Error callback\r\n * @param {Function} progressCallback Progress callback\r\n */\r\n static loadImage(params, callback, errorCallback, progressCallback) {\r\n //console.debug(JSON.stringify(data));\r\n const jobId = \"_\" + Math.random().toString(36).substr(2, 9);\r\n\r\n let connection = new HubConnectionBuilder()\r\n .withUrl(\"/jobprogress\")\r\n .configureLogging(LogLevel.Warning)\r\n .build();\r\n connection.serverTimeoutInMilliseconds = 5000000; // 5000 second\r\n connection.on(\"Progress\", (line) => {\r\n if (line) {\r\n progressCallback(line);\r\n }\r\n });\r\n connection.on(\"StandardOutput\", (line) => {\r\n // output debug prints of python module\r\n if (line) {\r\n console.debug(line);\r\n }\r\n });\r\n connection.on(\"Error\", (line) => {\r\n // output debug prints of python module\r\n if (line) {\r\n console.error(line);\r\n }\r\n });\r\n\r\n connection\r\n .start()\r\n .then(() => connection.invoke(\"AssociateJob\", jobId))\r\n .catch((err) => console.error(err.toString()));\r\n\r\n fetch_auth(`/api/rendering/load_image?id=${params.id}&jobId=${jobId}`)\r\n .then((response) => response.json())\r\n .then((res) => {\r\n res.error ? errorCallback(res.error) : callback(res);\r\n })\r\n .catch((error) => {\r\n errorCallback(error);\r\n });\r\n }\r\n\r\n /**\r\n * generate path for images to render a specific region\r\n */\r\n static renderRegion(params) {\r\n return `/api/rendering/render_region?id=${params.id}&page=${params.page}&level=${params.lv}&x=${params.x}&y=${params.y}`;\r\n }\r\n\r\n /**\r\n * generate path for thumbnail image\r\n */\r\n static renderThumbnail(id) {\r\n return `/api/rendering/render_thumbnail?id=${id}`;\r\n }\r\n\r\n static renderSlideImg(id) {\r\n return `/api/rendering/render_slide_img?id=${id}`;\r\n }\r\n\r\n /**\r\n * get file properties\r\n */\r\n static getFileInfo(id) {\r\n return fetch_auth(`/api/file/get?id=${id}`, {\r\n method: \"GET\",\r\n }).then((response) => response.json());\r\n }\r\n\r\n /**\r\n * generate and load 3d objects\r\n * @param {Object} data Instant analysis configuration\r\n */\r\n static get3dObjects(data) {\r\n return `/api/rendering/get3dObjects?file_id=${data.fileId}&project_id=${data.projectId}&zRange=${data.zRange}&showPointCloud=${data.showPointCloud}`;\r\n }\r\n\r\n /**\r\n * check if Sony QD Job ran\r\n * @param {Object} data Instant analysis configuration\r\n */\r\n static get3DAllObjectsExists(data, callback) {\r\n fetch_auth(\r\n `/api/rendering/get3DAllObjectsExists?file_id=${data.fileId}&project_id=${data.projectId}`,\r\n {\r\n method: \"GET\",\r\n }\r\n )\r\n .then((res) => res.text())\r\n .then((data) => callback(data));\r\n }\r\n\r\n /**\r\n * check, if python server is running\r\n * @param {*} callback\r\n */\r\n static isLocalServerReady(callback) {\r\n fetch_auth(`/api/rendering/is_running`, {\r\n method: \"GET\",\r\n })\r\n .then((res) => res.text())\r\n .then((data) => callback(data.toLowerCase() === \"true\"))\r\n .catch(() => console.log(\"error is_running\"));\r\n }\r\n // #endregion\r\n\r\n // #region Project Controller\r\n /**\r\n * Request a project, before actually loading it.\r\n * Allows to check if the project is available and to inject further actions if not.\r\n * @param {uuidv4} id The id of the project to request.\r\n * @param {Function} callback The function to call to handle a successful request.\r\n * @param {Function} error Optional. The function to call on any error.\r\n */\r\n static async requestProject(id, callback, error = () => {}) {\r\n fetch_auth(`/api/project/request?id=${id}`, {\r\n method: \"GET\",\r\n })\r\n .then((response) => {\r\n if (response.ok) {\r\n return response.json();\r\n }\r\n throw new Error(`Error loading exported projects`);\r\n })\r\n .then((res) => handleJsonResponse(res, callback, error))\r\n .catch((err) => {\r\n console.error(err);\r\n error(err);\r\n });\r\n }\r\n\r\n /**\r\n * Load project meta data from backend.\r\n * @param {uuid} id Project id.\r\n * @returns {Promise} Promise with project data parsed as json.\r\n */\r\n static async loadProject(id) {\r\n return fetch_auth(`/api/project/get?id=${id}`).then((response) =>\r\n response.json()\r\n );\r\n }\r\n\r\n /**\r\n * Clean up and close database after closing a project.\r\n * @param {uuid} projectId Id of the closed project.\r\n * @param {function} callback Function to call upon success.\r\n * @param {function} error Function to call upon error.\r\n */\r\n static closeProject = async (projectId) => {\r\n return fetch_auth(`/api/project/close?projectId=${projectId}`)\r\n .then((res) => {\r\n return res.json();\r\n })\r\n .then((res) => {\r\n if (res.error)\r\n throw Error(`Error closing project ${projectId}:\\n\\n ${res.error}`);\r\n return res;\r\n })\r\n .catch((err) => {\r\n throw Error(`Error closing project ${projectId}:\\n\\n ${err}`);\r\n });\r\n };\r\n\r\n /**\r\n * load file annotations data from Backend\r\n * @param {Object} params object with project id\r\n * @param {Function} callback Success callback with project model object as parameter\r\n */\r\n static async loadAnnotations(params, queryOptions) {\r\n return fetch_auth(\r\n `/api/project/get_annotations?id=${params.id}&fileId=${params.fileId}`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(queryOptions),\r\n }\r\n ).then(async (response) => {\r\n const r = await response.json();\r\n if (response.status === 200) return r;\r\n if (response.status === 400) {\r\n window.showErrorSnackbar(\"Access to the path is denied.\");\r\n return null;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Merges results in multiple projects\r\n * @param {String[]} projectIds\r\n * @returns {Promise} Promise with the result of the merge parsed as JSON.\r\n */\r\n static async mergeProjectResults(projectIds) {\r\n return fetch_auth(`/api/project/merge_project_results`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectIds),\r\n }).then((response) => response.json());\r\n }\r\n\r\n /**\r\n * Init Annotations DB\r\n * @param {UUID} projectId The id of the project to load annotations from.\r\n * @param {RoiType} roiType Type of rois to load.\r\n * @param {function} callback Function to execute on success.\r\n * @param {function} error Function to execute on error.\r\n */\r\n static initAnnotationsFromDB(projectId, roiType, callback, error) {\r\n const start = performance.now();\r\n if (!projectId) {\r\n throw new Error(\"Missing project id, which is required.\");\r\n }\r\n if (!Object.values(RoiType).includes(roiType)) {\r\n throw TypeError(`Invalid roiType ${roiType}.`);\r\n }\r\n // Perform the request\r\n fetch_auth(\r\n `api/project/init_annotations_db?projectId=${projectId}&roiType=${roiType}`,\r\n {\r\n method: \"GET\",\r\n }\r\n )\r\n .then((response) => {\r\n if (response.ok) {\r\n // TODO: Implement byte[] decoding\r\n return response.json();\r\n } else {\r\n return response.json();\r\n }\r\n })\r\n .then((res) => {\r\n if (res?.error) {\r\n error(`Error loading annotations:\\n${res.error}`);\r\n } else {\r\n const end = performance.now();\r\n const timeInSeconds = (end - start) / 1000;\r\n res.time = timeInSeconds;\r\n callback();\r\n }\r\n })\r\n .catch((err) =>\r\n error(`Error initializing annotations database:\\n${err}`)\r\n );\r\n }\r\n\r\n /**\r\n * Load annotations from backend database.\r\n * @param {UUID} projectId The id of the project to load annotations from.\r\n * @param {RoiType} roiType Type of rois to load.\r\n * @param {object} searchOptions Options to narrow down the rois to look for. Must consist of at minimum of fileId.\r\n * @param {function} callback Function to execute on success.\r\n * @param {function} error Function to execute on error.\r\n */\r\n static async loadAnnotationsFromDB(projectId, roiType, searchOptions) {\r\n try {\r\n if (!projectId) {\r\n throw new Error(\"Missing project id, which is required.\");\r\n }\r\n if (!Object.values(RoiType).includes(roiType)) {\r\n throw TypeError(`Invalid roiType ${roiType}.`);\r\n }\r\n if (!searchOptions) {\r\n throw new Error(\r\n \"Missing search options, must consist at minimum of fileId.\"\r\n );\r\n }\r\n if (!searchOptions.fileId) {\r\n throw new Error(\"Missing file id, which is required.\");\r\n }\r\n } catch (err) {\r\n console.error(\r\n \"An error occured fetching the annotaions form the database:\\n\",\r\n err\r\n );\r\n throw new Error(err);\r\n }\r\n\r\n // Perform the request\r\n return fetch_auth(\r\n `api/project/get_annotations_from_db?projectId=${projectId}&roiType=${roiType}`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(searchOptions),\r\n }\r\n )\r\n .then((response) => {\r\n if (response.ok) {\r\n // TODO: Implement byte[] decoding\r\n return response.json();\r\n } else {\r\n return response.json();\r\n }\r\n })\r\n .then((res) => {\r\n if (res?.error) {\r\n const err = `Error loading annotations:\\n${res.error}`;\r\n throw new Error(err);\r\n } else {\r\n let roisNotLoaded = 0;\r\n // Map rois to their respective types\r\n switch (roiType) {\r\n case RoiType.ImageRoi:\r\n res = res.map((incomingRoi) => {\r\n try {\r\n return ImageRoi.fromObject(incomingRoi);\r\n } catch (err) {\r\n console.error(\r\n \"Error converting incoming roi to ImageRoi:\\n\",\r\n err\r\n );\r\n roisNotLoaded++;\r\n return null;\r\n }\r\n });\r\n break;\r\n\r\n case RoiType.AudioRoi:\r\n res = res.map((incomingRoi) => {\r\n try {\r\n return AudioRoi.fromObject(incomingRoi);\r\n } catch (err) {\r\n console.error(\r\n \"Error converting incoming roi to AudioRoi:\\n\",\r\n err\r\n );\r\n roisNotLoaded++;\r\n return null;\r\n }\r\n });\r\n break;\r\n\r\n default:\r\n throw TypeError(`Cannot conver to invalid roiType ${roiType}.`);\r\n }\r\n\r\n if (roisNotLoaded > 0) {\r\n window.showErrorSnackbar(\r\n `Some rois (${roisNotLoaded}) could not be loaded. Please check the console for more information.`\r\n );\r\n window.showWarningSnackbar(\r\n `Saving the project will not save annotations (${roisNotLoaded}) that could not be loaded.`\r\n );\r\n }\r\n res = res.filter((roi) => roi !== null);\r\n return res;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Get the annotation count for a project.\r\n * Can be narrowed down to a specific file and structure.\r\n * @param {uuid} projectId The id of the project to get the annotation count for.\r\n * @param {string} filePath Optional. The path of the file to get the annotation count for. If not provided, the count for all files is returned. Default is null.\r\n * @param {int} structureId Optional. The id of the structure to get the annotation count for. If not provided, the count for all structures is returned. Default is null.\r\n * @returns {Promise} Promise with the annotation count as an integer.\r\n */\r\n static async getAnnotationCount(\r\n projectId,\r\n filePath = null,\r\n structureId = null\r\n ) {\r\n let requestUrl = `/api/project/annotation_count?projectId=${projectId}`;\r\n if (filePath) requestUrl += `&filePath=${encodeURIComponent(filePath)}`;\r\n if (structureId) requestUrl += `&structureId=${structureId}`;\r\n\r\n return fetch_auth(requestUrl, {\r\n method: \"GET\",\r\n }).then((response) => {\r\n if (response.ok) {\r\n return response.text().then((text) => parseInt(text));\r\n }\r\n let errMsg = `Error loading annotation count for project ${projectId}`;\r\n if (filePath) errMsg += `, file ${filePath}`;\r\n if (structureId) errMsg += `, structure ${structureId}`;\r\n errMsg += `[${response.status}]`;\r\n if (response.statusText) errMsg += `: ${response.statusText}`;\r\n throw new Error(errMsg);\r\n });\r\n }\r\n\r\n /**\r\n * load file annotations data from Backend\r\n * @param {Object} params object with project id\r\n * @param {Function} callback Success callback with project model object as parameter\r\n */\r\n static loadAnnotationsObject(params, callback) {\r\n fetch_auth(\r\n `/api/project/get_annotations_object?id=${params.id}&fileId=${params.fileId}`\r\n )\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n static exportGallery(id, fileId, callback) {\r\n fetch_auth(`/api/project/export_gallery?id=${id}&fileId=${fileId}`, {\r\n method: \"POST\",\r\n })\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * List all projects of the logged in user\r\n * @param {Function} callback Success callback with list as parameter\r\n */\r\n static listProjects(callback) {\r\n try {\r\n fetch_auth(\"/api/project/list\")\r\n .then((response) => {\r\n if (response.status === 401) {\r\n console.log(\"not authenticated => logout\");\r\n authenticationService.logout();\r\n return;\r\n }\r\n return response.json();\r\n })\r\n .then(callback)\r\n .catch((error) => {\r\n console.log(error);\r\n });\r\n } catch (ex) {\r\n console.log(\"error:\", ex);\r\n }\r\n }\r\n\r\n /**\r\n * Get message from one project\r\n * @param {String} id\r\n * @returns Promise\r\n */\r\n static async loadProjectMessage(id) {\r\n return fetch_auth(`/api/project/get_message?id=${id}`).then((response) =>\r\n response.json()\r\n );\r\n }\r\n\r\n /**\r\n * Creates a new project in database based on the chosen template\r\n * @param {Object} data Project creation model\r\n * @returns {Promise} result of fetch function\r\n */\r\n static async createProject(data) {\r\n return fetch_auth(`/api/project/create`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n }).then((response) => {\r\n if (response.ok) {\r\n return response.json();\r\n }\r\n throw new Error(response.statusText);\r\n });\r\n }\r\n\r\n /**\r\n * Export Projects\r\n * @param {String[]} projectIds List of project ids to export.\r\n * @param {String} exportName Name of the export file.\r\n * @param {Function} callback Function to call on success.\r\n * @param {Function} err Function to call on error.\r\n */\r\n static exportProjects(projectIds, exportName, callback, err) {\r\n fetch_auth(`/api/project/export`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectIds),\r\n })\r\n .then(async (response) => {\r\n if (response.ok) {\r\n return response.blob();\r\n } else {\r\n const res = await response.json();\r\n if (res.errorMessage) {\r\n throw new Error(res.errorMessage);\r\n }\r\n }\r\n })\r\n .then((blob) => {\r\n var url = window.URL.createObjectURL(blob);\r\n var a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = exportName + \".hsa\";\r\n document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox\r\n a.click();\r\n a.remove(); //afterwards we remove the element again\r\n callback();\r\n })\r\n .catch((error) => {\r\n console.error(error);\r\n err(error);\r\n });\r\n }\r\n\r\n /**\r\n * Import exported projects.\r\n * @param {FormFile} file The file to import projects from.\r\n * @param {Function} callback The function to call to handle a successful request.\r\n * @param {Function} error Optional. The function to call on any error.\r\n */\r\n static importProjects(file, callback, error = () => {}) {\r\n const time1 = performance.now();\r\n var data = new FormData();\r\n data.append(\"file\", file);\r\n\r\n fetch_auth(`/api/project/import`, {\r\n method: \"POST\",\r\n body: data,\r\n })\r\n .then((response) => {\r\n if (response.ok) {\r\n console.info(\"Import took\", (performance.now() - time1) / 1000, \"s\");\r\n return response.json();\r\n }\r\n throw new Error(`Error loading exported projects`);\r\n })\r\n .then((res) => handleJsonResponse(res, callback, error))\r\n .catch((err) => {\r\n console.error(err);\r\n error(err);\r\n });\r\n }\r\n\r\n /**\r\n * Rename Project\r\n * @param {String} projectId\r\n * @param {String} name\r\n * @param {Function} callback\r\n */\r\n static renameProject(projectId, name, callback) {\r\n let params = {\r\n projectId: projectId,\r\n updatedName: name,\r\n };\r\n fetch_auth(`/api/project/rename`, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(params),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => callback(json));\r\n }\r\n\r\n /**\r\n * Merges multiple Projects and creates new Project\r\n * @param {String[]} projectIds\r\n * @param {Function} callback\r\n */\r\n static async mergeProjects(projectIds) {\r\n return fetch_auth(`/api/project/merge`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectIds),\r\n }).then((response) => {\r\n return response.json();\r\n });\r\n }\r\n\r\n /**\r\n * Update Project Files\r\n * @param {String} projectId\r\n * @param {Object} model\r\n * @param {Function} callback\r\n */\r\n static updateProjectFiles(projectId, model, callback) {\r\n fetch_auth(`/api/project/update_files?id=${projectId}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(model),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * Update a project with new data.\r\n * Possible updates include name and files.\r\n * @param {uuid} projectId The id of the project to update.\r\n * @param {object} model The model to update the project with. Uses the ProjectCreationModel format.\r\n * @returns {object} Basic project information.\r\n */\r\n static async updateProject(projectId, model) {\r\n return fetch_auth(`/api/project/update?id=${projectId}`, {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(model),\r\n }).then((response) => {\r\n if (response.ok) {\r\n return response.json();\r\n }\r\n let errMsg = `Failed to update project ${projectId} [${response.status}]`;\r\n if (response.statusText) {\r\n errMsg += `: ${response.statusText}`;\r\n }\r\n throw new Error(errMsg);\r\n });\r\n }\r\n\r\n /**\r\n * Deletes multiple Projects\r\n * @param {String[]} projectIds\r\n * @param {Function} callback\r\n */\r\n static deleteProjects(projectIds, callback) {\r\n fetch_auth(`/api/project/delete`, {\r\n method: \"DELETE\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectIds),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n })\r\n .catch(() => {\r\n window.showErrorSnackbar(\r\n \"Deleting Project failed! Are you the creator?\"\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Checks new or edited proposed file mappings for validity in Backend.\r\n * @param {Tuple(Array, Array)} formData Tuple with list of all projects to import and list of all proposed file mappings.\r\n * @param {String} projectActionMode The action to perform on the projects. Must be a valid value of ProjectActionMode.\r\n * @param {Function} callback The function to call to handle a successful request. Receives {object} Response.\r\n * @param {Function} error Optional. The function to call on any error. Receives {string} Error.\r\n */\r\n static checkFileMappings(\r\n formData,\r\n projectActionMode,\r\n callback,\r\n error = () => {}\r\n ) {\r\n fetch_auth(`/api/project/checkFileMappings?mode=${projectActionMode}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(formData),\r\n })\r\n .then((response) => {\r\n if (response.ok) {\r\n return response.json();\r\n }\r\n const projectCount = formData.projects.length;\r\n throw new Error(\r\n `Error importing ${projectCount} ${\r\n projectCount === 1 ? \"project\" : \"projects\"\r\n }`\r\n );\r\n })\r\n .then((res) => handleJsonResponse(res, callback, error))\r\n .catch((err) => {\r\n console.error(err);\r\n error(err.message);\r\n });\r\n }\r\n\r\n /**\r\n * Exports (starts download) multiple project modules as zip file\r\n * @param {String[]} names\r\n * @param {Function} callback\r\n */\r\n static exportProjectTypes(names, output_name, callback) {\r\n fetch_auth(`/api/project/export_project_module_types`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(names),\r\n })\r\n .then((response) => response.blob())\r\n .then((blob) => {\r\n var url = window.URL.createObjectURL(blob);\r\n var a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = output_name + \".zip\";\r\n document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox\r\n a.click();\r\n a.remove(); //afterwards we remove the element again\r\n callback(\"success\");\r\n });\r\n }\r\n\r\n /**\r\n * Create Project Module Preview Image\r\n * @param {String} name\r\n * @param {String} projectJson\r\n * @param {Function} callback\r\n */\r\n static createProjectTypeJsonFile(name, projectJson, callback) {\r\n fetch_auth(`/api/project/create_project_module_type_json?name=${name}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectJson),\r\n })\r\n .then((response) => response.json())\r\n .then((res) =>\r\n showHandledProblems(res, \"No permission to create project modules!\")\r\n )\r\n .then((res) => callback(res));\r\n }\r\n\r\n /**\r\n * Create Project Module Preview Image\r\n * @param {String} name\r\n * @param {FormFile} img\r\n * @param {Function} callback\r\n */\r\n static createProjectTypeImage(name, img, callback) {\r\n console.log(\"createProjectTypeImage()\");\r\n let data = new FormData();\r\n data.append(\"file\", img);\r\n\r\n fetch_auth(`/api/project/create_project_module_type_image?name=${name}`, {\r\n method: \"POST\",\r\n body: data,\r\n })\r\n .then((response) => response.json())\r\n .then((res) =>\r\n showHandledProblems(res, \"No permission to create project modules!\")\r\n )\r\n .then((res) => callback(res));\r\n }\r\n\r\n /**\r\n * Save screenshot in slides sub folder\r\n * @param {String} name\r\n * @param {FormFile} img\r\n * @param {Function} callback\r\n */\r\n static saveScreenshot(folderPath, fileName, img, callback) {\r\n let data = new FormData();\r\n data.append(\"file\", img);\r\n fetch_auth(\r\n `/api/project/save_screenshot?fileName=${fileName}&folderPath=${folderPath}`,\r\n {\r\n method: \"POST\",\r\n body: data,\r\n }\r\n )\r\n .then((response) => response.json())\r\n .then((res) => callback(res));\r\n }\r\n\r\n /**\r\n * Delete Project Type Preview Image and json file\r\n * @param {String} name project type name\r\n * @returns {Promise} result of fetch function\r\n */\r\n static async deleteProjectType(name) {\r\n return fetch_auth(`/api/project/delete_project_module_type?name=${name}`, {\r\n method: \"POST\",\r\n }).then((response) => response.json());\r\n }\r\n\r\n /**\r\n * Imports Exported Project Types\r\n * @param {FormFile} fileMappings\r\n * @param {Function} callback\r\n * @param {Function} errorCallback\r\n */\r\n static importProjectTypes(fileMappings, callback, errorCallback) {\r\n var data = new FormData();\r\n data.append(\"file\", fileMappings);\r\n fetch_auth(`/api/project/import_project_types`, {\r\n method: \"POST\",\r\n body: data,\r\n })\r\n .then((response) => response.json())\r\n .then((res) => (res.error ? errorCallback(res.error) : callback(res)))\r\n .catch((error) => errorCallback(error));\r\n }\r\n\r\n /**\r\n * edit project type\r\n * @param {Object} projectType\r\n * returns {Promise}\r\n */\r\n static async editProjectType(projectType) {\r\n return fetch_auth(`/api/admin/edit_project_type`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectType),\r\n }).then((response) => response.json());\r\n }\r\n\r\n /**\r\n * Deletes Gallery Export of Projects\r\n * @param {String[]} projectNames\r\n * @param {Function} callback\r\n */\r\n static deleteGalleryExport(projectNames, callback) {\r\n fetch_auth(`/api/project/deleteGallery`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectNames),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * Duplicate multiple Projects\r\n * @param {String[]} projectIds\r\n * @param {Function} callback\r\n */\r\n static duplicateProjects(projectIds, callback) {\r\n fetch_auth(`/api/project/duplicate`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectIds),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * Sets multiple Projects to pending\r\n * @param {String[]} projectIds\r\n * @param {Function} callback\r\n */\r\n static setProjectsPending(projectIds, evalOnly = false, callback) {\r\n fetch_auth(`/api/project/pending`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ projectIds: projectIds, evalOnly: evalOnly }),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * Sets multiple Projects to timed\r\n * @param {String[]} projectIds\r\n * @param {Function} callback\r\n */\r\n static setProjectsTimed(projectIds, callback) {\r\n fetch_auth(`/api/project/timed`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(projectIds),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * saves project data into a json file\r\n * @param {Object} data project model\r\n * @returns {Promise} Feedback from the backend when saving the project.\r\n */\r\n static saveProject(data) {\r\n return fetch_auth(`/api/project/saveProject`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n }).then((response) => response.json());\r\n }\r\n\r\n /**\r\n * saves annotations into json files\r\n * @param {String} projectId\r\n * @param {Object} data project model\r\n * @param {Function} callback\r\n */\r\n static saveAnnotations(projectId, fileId, data, callback) {\r\n // https://stackoverflow.com/questions/50918007/accepting-byte-in-a-net-core-webapi-controller\r\n // data = new Blob([data.buffer]);\r\n fetch_auth(\r\n `/api/project/saveAnnotations?projectId=${projectId}&fileId=${fileId}`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/octet-stream\" },\r\n body: data,\r\n }\r\n )\r\n .then((response) => response.json())\r\n .then((data) => {\r\n if (callback) {\r\n callback(data);\r\n }\r\n })\r\n .catch((error) => console.log(\"error\", error));\r\n }\r\n\r\n /**\r\n * sends image to ftp server to simulate stream\r\n *\r\n */\r\n static streamRenderer(data, remoteUuid, callback) {\r\n fetch_auth(`/api/project/streamRenderer?remoteUuid=${remoteUuid}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/octet-stream\" },\r\n body: data,\r\n })\r\n .then((response) => response.json())\r\n .then((data) => {\r\n callback(data);\r\n })\r\n .catch((error) => console.log(\"error\", error));\r\n }\r\n\r\n /**\r\n * Load the structures of a project from backend.\r\n * @param {uuid} projectId Id of the project to load the structures for.\r\n * @returns {Promise} List of Strucutre objects.\r\n */\r\n static async loadStructures(projectId) {\r\n return fetch_auth(`/api/project/load_structures?projectId=${projectId}`, {\r\n method: \"GET\",\r\n })\r\n .then((res) => {\r\n return res.ok\r\n ? res.json()\r\n : { error: `Failed to load structures for project ${projectId}` };\r\n })\r\n .then((res) => {\r\n if (res.error) {\r\n throw Error(res.error);\r\n } else {\r\n // Cast to structure class\r\n return res.map((s) => Structure.fromObject(s));\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Save structures of a project to its database.\r\n * @param {uuid} projectId Id of project to save annotations for.\r\n * @param {array} structures Structures to save as list.\r\n * @returns {Promise} Promise object representing the result of the request.\r\n */\r\n static async saveStructures(projectId, structures) {\r\n const tmpStructures = structures.map((s) => {\r\n const tmpstruct = Structure.copy(s);\r\n tmpstruct.toolSettings = JSON.stringify(tmpstruct.toolSettings);\r\n return tmpstruct;\r\n });\r\n return fetch_auth(`/api/project/save_structures?projectId=${projectId}`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(tmpStructures),\r\n })\r\n .then((res) => {\r\n if (res.ok) return res.json();\r\n let errMsg = `Failed to save structures to project database [${res.status}]`;\r\n if (res.statusText !== \"\") errMsg += `: ${res.statusText}`;\r\n throw new Error(errMsg);\r\n })\r\n .then((data) => {\r\n if (data?.error) throw new Error(data.error);\r\n return data;\r\n });\r\n }\r\n\r\n /**\r\n * Deletes all annotations for a file (or for a specific structure in a file)\r\n * from the project annotation database.\r\n * WARNING: Only use after ensuring that annotations have been saved (in case of network errors).\r\n * @param {UUID} projectId Id of project to delete annotations from.\r\n * @param {UUID} fileId Id of file to delete annotations from.\r\n * @param {int} structureId Optional. Id of structure to delete annotations from. Default is null.\r\n * @param {boolean} force Optional. If true, will not ask user for explicit confirmation. Default is false.\r\n * @returns {Promise} Promise object representing the result of the request.\r\n */\r\n static async clearAnnotationsFromDb(\r\n projectId,\r\n fileId,\r\n structureId = null,\r\n force = false\r\n ) {\r\n // Confirm deletion by user if not forced.\r\n if (!force) {\r\n const confirmed = await window.openConfirmationDialog(\r\n \"Delete all annotations?\",\r\n structureId\r\n ? `Are you sure you want to delete all annotations for this structure (${structureId}) in this file?`\r\n : \"Are you sure you want to delete all annotations for this file?\"\r\n );\r\n if (!confirmed) return;\r\n }\r\n\r\n let url = `/api/project/clear_annotations_from_db?projectId=${projectId}&fileId=${fileId}`;\r\n if (structureId) url += `&structureId=${structureId}`;\r\n\r\n const response = await fetch_auth(url, { method: \"GET\" });\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Save rois of a project to the projects annotation database.\r\n * Will delete all annotations in db and replace them with the updated ones.\r\n * @param {UUID} projectId Id of project to save annotations for.\r\n * @param {RoiType} roiType Type of rois to be saved.\r\n * @param {array} rois List of all rois to be saved.\r\n * @param {function} callback Function to execute on success.\r\n * @param {function} error Function to execute on error.\r\n */\r\n static saveLegacyAnnotationsToDb(projectId, roiType, rois, callback, error) {\r\n // Check for missing input\r\n if (!projectId || !Object.values(RoiType).includes(roiType) || !rois)\r\n return;\r\n\r\n // Reduce rois to those modified\r\n rois = rois.filter(\r\n (roi) => roi.modificationStatus !== ModificationStatus.Saved\r\n );\r\n\r\n // No rois to save\r\n if (rois.length === 0) {\r\n callback({\r\n success: \"All rois already saved\",\r\n roiUpdate: {\r\n reassignedIds: [],\r\n failedToAdd: [],\r\n failedToDelete: [],\r\n },\r\n });\r\n return;\r\n }\r\n\r\n // Identify new rois\r\n const roisToAdd = rois.filter(\r\n (roi) => roi.modificationStatus === ModificationStatus.Added\r\n );\r\n roisToAdd\r\n .filter((roi) => roi instanceof ImageRoi)\r\n .forEach((roi) => {\r\n roi.coordinates =\r\n typeof roi.coordinates === \"string\"\r\n ? roi.coordinates\r\n : JSON.stringify(roi.coordinates);\r\n });\r\n\r\n // Identify deleted rois, keep only ids\r\n const roiIdsToDelete = rois\r\n .filter((roi) => roi.modificationStatus === ModificationStatus.Deleted)\r\n .map((roi) => roi.id);\r\n\r\n const data = new Blob([JSON.stringify({ roisToAdd, roiIdsToDelete })]);\r\n\r\n fetch_auth(\r\n `/api/project/saveLegacyAnnotations?projectId=${projectId}&roiType=${roiType}`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/octet-stream\" },\r\n body: data,\r\n }\r\n )\r\n .then((res) => res.json())\r\n .then((data) => {\r\n data.error || data.warning ? error(data) : callback(data);\r\n })\r\n .catch((err) => error({ error: err.toString() }));\r\n }\r\n\r\n /**\r\n * Save rois of a project to the projects annotation database.\r\n * @param {UUID} projectId Id of project to save annotations for.\r\n * @param {RoiType} roiType Type of rois to be saved.\r\n * @param {array} rois List of all rois to be saved.\r\n * @param {function} callback Function to execute on success.\r\n * @param {function} error Function to execute on error.\r\n */\r\n static saveAnnotationsToDb(projectId, roiType, rois, callback, error) {\r\n // Check for missing input\r\n if (!projectId || !Object.values(RoiType).includes(roiType) || !rois)\r\n return;\r\n\r\n // Reduce rois to those modified\r\n rois = rois.filter(\r\n (roi) => roi.modificationStatus !== ModificationStatus.Saved\r\n );\r\n\r\n // No rois to save\r\n if (rois.length === 0) {\r\n callback({\r\n success: \"All rois already saved\",\r\n roiUpdate: {\r\n reassignedIds: [],\r\n failedToAdd: [],\r\n failedToDelete: [],\r\n },\r\n });\r\n return;\r\n }\r\n\r\n // Identify new rois\r\n const roisToAdd = rois.filter(\r\n (roi) => roi.modificationStatus === ModificationStatus.Added\r\n );\r\n\r\n roisToAdd\r\n .filter((roi) => roi instanceof ImageRoi)\r\n .forEach((roi) => {\r\n roi.coordinates =\r\n typeof roi.coordinates === \"string\"\r\n ? roi.coordinates\r\n : JSON.stringify(roi.coordinates);\r\n });\r\n\r\n // Identify deleted rois, keep only ids\r\n const roiIdsToDelete = rois\r\n .filter((roi) => roi.modificationStatus === ModificationStatus.Deleted)\r\n .map((roi) => roi.id);\r\n\r\n const data = new Blob([JSON.stringify({ roisToAdd, roiIdsToDelete })]);\r\n\r\n fetch_auth(\r\n `/api/project/save_annotations_to_db?projectId=${projectId}&roiType=${roiType}`,\r\n {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/octet-stream\" },\r\n body: data,\r\n }\r\n )\r\n .then((res) => res.json())\r\n .then((data) => {\r\n data.error || data.warning ? error(data) : callback(data);\r\n })\r\n .catch((err) => error({ error: err.toString() }));\r\n }\r\n\r\n /**\r\n * saves project data into a json file\r\n * @param {Object} data project model\r\n * @param {Function} callback\r\n */\r\n static saveGallery() {}\r\n\r\n /**\r\n * load project type viewer configuration\r\n * @param {String} projectType name of project type\r\n * @param {Function} callback\r\n */\r\n static loadViewerConfig(projectType, callback) {\r\n fetch_auth(\r\n `/api/project/load_viewer_config?name=${encodeURIComponent(projectType)}`\r\n )\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * load all available project types\r\n * only load once, otherwise wait for a variable to be filled before returning result\r\n * @param {Boolean} forceReload force reload/fetch of project types\r\n * @returns {Promise} list of all project types\r\n */\r\n static loadAvailableProjectTypes(forceReload) {\r\n return new Promise((resolve, reject) => {\r\n if (forceReload || typeof window.availabeProjectTypes === \"undefined\") {\r\n window.availabeProjectTypes = \"blocked\";\r\n\r\n fetch_auth(\"/api/project/get_project_types\")\r\n .then((response) => response.json())\r\n .then((modules) => {\r\n modules.forEach((module) => {\r\n module.structures.forEach((structure) => {\r\n structure.tools = structure.tools.map((tool) =>\r\n InstantAnalysisModule.fromObject(tool)\r\n );\r\n });\r\n });\r\n\r\n window.availabeProjectTypes = modules;\r\n resolve(modules);\r\n })\r\n .catch((error) => {\r\n console.log(error);\r\n reject(error);\r\n });\r\n } else {\r\n const waitForElement = () => {\r\n if (window.availabeProjectTypes !== \"blocked\") {\r\n resolve(window.availabeProjectTypes);\r\n } else {\r\n setTimeout(waitForElement, 200);\r\n }\r\n };\r\n waitForElement();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * load all available project types, but only return reduced information, to be faster\r\n * also save and load from local storage\r\n * @param {Function} callback contains list of all project types\r\n */\r\n static loadReducedAvailableProjectTypes(callback) {\r\n //let t0 = performance.now();\r\n Backend.getVersion((data) => {\r\n const ptKey = \"projectTypes_\" + data.version;\r\n let projectTypes = JSON.parse(localStorage.getItem(ptKey));\r\n if (projectTypes === null) {\r\n Backend.loadAvailableProjectTypes(false).then((projectTypesList) => {\r\n projectTypes = projectTypesList.map((item) => {\r\n return {\r\n annotations: item.annotations,\r\n description: item.description,\r\n isUserModule: item.isUserModule,\r\n name: item.name,\r\n order: item.order,\r\n label: item.label,\r\n };\r\n });\r\n localStorage.setItem(ptKey, JSON.stringify(projectTypes));\r\n //console.log(\"loadRAPTs time:\", performance.now() - t0);\r\n callback(projectTypes);\r\n });\r\n } else {\r\n //console.log(\"loadRAPTs time:\", performance.now() - t0);\r\n callback(projectTypes);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * load all available project types\r\n * @param {String} dir directory to list files within\r\n * @param {Function} callback contains list of all project types\r\n */\r\n static walkCaseFiles(path, isRelative, callback) {\r\n fetch_auth(\r\n `/api/project/walk_caseFiles?path=${encodeURIComponent(\r\n path\r\n )}&isRelative=${isRelative}`\r\n )\r\n .then((response) => response.json())\r\n .then(callback)\r\n .catch((error) => {\r\n console.log(\"error\", error);\r\n window.showErrorSnackbar(\"Error loading directory!\");\r\n });\r\n }\r\n\r\n /**\r\n * load all available project types\r\n * @param {String} dir directory to list files within\r\n * @param {Function} callback contains list of all project types\r\n */\r\n static walkProjectDirFiles(dir, callback) {\r\n fetch_auth(\r\n `/api/project/walk_project_dir_files?path=${encodeURIComponent(dir)}`\r\n )\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Cancel Job\r\n * @param {String} id\r\n */\r\n static cancelJob(id) {\r\n fetch_auth(`/api/project/cancel`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(id),\r\n }).then((response) => response.json());\r\n }\r\n\r\n static async editCaseProjects(caseId, projectId, task) {\r\n try {\r\n return fetch_auth(\"/api/cases/editCaseProjects\", {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify({ caseId, projectId, task }),\r\n })\r\n .then((response) => response.json())\r\n .then((result) => {\r\n return result;\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n }\r\n\r\n /**\r\n * Check if String has JSON-Format\r\n * @param {String} str\r\n */\r\n static isJsonString(str) {\r\n try {\r\n // for (var i = 0; i < str.length; i++) {\r\n\r\n // }\r\n JSON.parse(str);\r\n } catch (e) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the loaction of thumbnails for a image based on its path.\r\n * @param {string} image_path Path to the image being loaded.\r\n * @returns {string} Api link to image thumbnail.\r\n */\r\n static imageThumbnail(image_path) {\r\n return `/api/project/image_thumbnail?path=${image_path}`;\r\n }\r\n\r\n /**\r\n * Get the loaction of thumbnails for a image based on its path.\r\n * @param {string} image_path Path to the image being loaded.\r\n * @returns {object} object containing uuid.\r\n */\r\n static async getFileUuid(image_path) {\r\n let obj = {};\r\n await fetch_auth(\r\n `/api/project/file_uuid?path=${encodeURIComponent(image_path)}`,\r\n {\r\n method: \"GET\",\r\n }\r\n )\r\n .then((res) => res.json())\r\n .then((data) => {\r\n obj = data;\r\n });\r\n\r\n return obj;\r\n }\r\n\r\n /**\r\n * Trigger download of file.\r\n * @param {String} id Project UUID\r\n * @param {String} exportName Name of the file to be exported. Defaults to \"report\".\r\n */\r\n static downloadReport(id, exportName = `report`) {\r\n // Add timestamp to exported file.\r\n exportName += `_${convertDateToShortIsoString(Date.now())}`;\r\n fetch_auth(`/api/project/report?id=${id}`, {\r\n method: \"GET\",\r\n })\r\n .then((response) => response.blob())\r\n .then((blob) => {\r\n var url = window.URL.createObjectURL(blob);\r\n var a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = exportName;\r\n document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox\r\n a.click();\r\n a.remove(); //afterwards we remove the element again\r\n });\r\n }\r\n\r\n /**\r\n * Retrieve report for a specific project from backend.\r\n * @param {UUID} id Project id for which to get the report.\r\n * @param {function} callback Function processing the loaded report. Recieves a UInt8Array.\r\n * @param {function} error Fallback function on error.\r\n */\r\n static loadReport(id, callback, error) {\r\n const currentUser = authenticationService.currentUserValue;\r\n let url = `${window.location.origin}/api/project/report?id=${id}`;\r\n\r\n // Set up XHR Request\r\n let req = new XMLHttpRequest();\r\n req.open(\"GET\", url, true);\r\n req.setRequestHeader(\"Authorization\", `Bearer ${currentUser.token}`);\r\n req.responseType = \"arraybuffer\";\r\n req.onload = () => {\r\n let data = new Uint8Array(req.response);\r\n callback(data);\r\n };\r\n req.onerror = (err) => {\r\n error(err);\r\n };\r\n req.send();\r\n }\r\n\r\n /**\r\n * generate image source to report chart\r\n * @param {String} id Project ID\r\n */\r\n static renderReportChart(path) {\r\n return `/api/project/report_chart?path=${path}`;\r\n }\r\n\r\n /**\r\n * Runs a instant analysis tool with real time updates using signalR\r\n * @param {Object} data Instant analysis configuration\r\n * @param {Function} callback Success callback\r\n * @param {Function} error Error callback\r\n */\r\n static aiTrainingSignalR(\r\n data,\r\n progressCallback,\r\n successCallback,\r\n errorCallback\r\n ) {\r\n let modelType = \"none\";\r\n let isVdlModel = false;\r\n if (data.parameters && data.parameters.modelType) {\r\n modelType = data.parameters.modelType;\r\n if (modelType == \"instance segmentation\") {\r\n // check if vdl model\r\n if (data.parameters.advancedSettings.comDLArchitecture === null) {\r\n isVdlModel = true;\r\n } else if (\r\n data.parameters.advancedSettings.comDLArchitecture &&\r\n data.parameters.advancedSettings.comDLArchitecture.label ==\r\n \"Mask R-CNN VDL\"\r\n ) {\r\n isVdlModel = true;\r\n }\r\n }\r\n }\r\n\r\n jobProgressConnection.off(\"Progress\");\r\n jobProgressConnection.on(\"Progress\", (line) => {\r\n if (line) {\r\n progressCallback(line);\r\n }\r\n });\r\n jobProgressConnection.off(\"StandardOutput\");\r\n jobProgressConnection.on(\"StandardOutput\", (line) => {\r\n // output debug prints of python module\r\n if (line) {\r\n console.debug(line);\r\n if (typeof window.trainingProgress !== \"function\") return;\r\n window.trainingProgress(line);\r\n\r\n if (typeof window.updateTrainingData !== \"function\") return;\r\n window.updateTrainingData(line, modelType, isVdlModel);\r\n }\r\n });\r\n jobProgressConnection.off(\"StandardError\");\r\n jobProgressConnection.on(\"StandardError\", (line) => {\r\n // output debug prints of python module\r\n if (line) {\r\n window.trainingProgress(line);\r\n if (typeof window.updateTrainingData === \"function\") {\r\n window.updateTrainingData(line, modelType, isVdlModel);\r\n }\r\n }\r\n });\r\n jobProgressConnection.off(\"Result\");\r\n jobProgressConnection.on(\"Result\", (json) => {\r\n if (json.error) {\r\n console.log(\"training callback error:\", json);\r\n // there was an exception in python module\r\n errorCallback(json.error);\r\n } else {\r\n // success\r\n successCallback(json.project);\r\n }\r\n });\r\n\r\n fetch_auth(`/api/ai/train`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n })\r\n .then((response) => response.json())\r\n .then((myJson) => {\r\n if (jobProgressConnection.state === 0) {\r\n jobProgressConnection\r\n .start()\r\n .then(() =>\r\n jobProgressConnection.invoke(\"AssociateJob\", myJson.jobId)\r\n )\r\n .catch((err) => console.error(err.toString()));\r\n } else {\r\n jobProgressConnection\r\n .invoke(\"AssociateJob\", myJson.jobId)\r\n .catch((err) => console.error(err.toString()));\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Runs a Grid annotation tool with real time updates\r\n * @param {Object} data export Data\r\n * @param {Function} callback Success callback\r\n * @param {Function} error Error callback\r\n */\r\n static tileExport(data) {\r\n let connection = new HubConnectionBuilder()\r\n .withUrl(\"/jobprogress\")\r\n .configureLogging(LogLevel.Warning)\r\n .build();\r\n connection.serverTimeoutInMilliseconds = 5000000; // 5000 second\r\n connection.on(\"Progress\", (line) => {\r\n if (line) {\r\n console.log(\"line\", line);\r\n }\r\n });\r\n connection.on(\"StandardOutput\", (line) => {\r\n if (line) {\r\n window.tileExportProgress(line);\r\n }\r\n });\r\n connection.on(\"Result\", (json) => {\r\n if (json.error) {\r\n console.log(\"json error\");\r\n }\r\n });\r\n\r\n fetch_auth(`/api/project/tileexport`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n })\r\n .then((response) => response.json())\r\n .then((myJson) => {\r\n connection\r\n .start()\r\n .then(() => connection.invoke(\"AssociateJob\", myJson.jobId))\r\n .catch((err) => {\r\n console.error(err.toString());\r\n console.log(\"error catch\");\r\n });\r\n });\r\n }\r\n // #endregion\r\n\r\n // #region Ai Controller\r\n /**\r\n * Get all model inforamtion from both local as well as optionally from online sources.\r\n * The respose will be parsed and the models passed to callback as json.\r\n * @param {String} model_path \"hsa_models\".\r\n * @param {Bool} online Should models be donwloaded from the HSA online server. Defaults to false.\r\n * @returns {Promise} List of all models.\r\n */\r\n static async getModelMetadata(model_path, online = false) {\r\n return fetch_auth(\r\n `/api/ai/get_model_metadata?model_path=${model_path}&online=${online}`,\r\n {\r\n method: \"GET\",\r\n }\r\n )\r\n .then((response) => {\r\n if (!response.ok) {\r\n console.log(`Received status code: ${response.status}`);\r\n throw new Error(\r\n `Network response was not ok, status: ${response.status}`\r\n );\r\n }\r\n return response.json();\r\n })\r\n .then((result) => {\r\n if (result.error) {\r\n throw new Error(result.details || result.error);\r\n }\r\n\r\n // In case of models that could not be loaded\r\n if (result.unlistedModels !== \"[]\") {\r\n const unlistedModels = JSON.parse(result.unlistedModels);\r\n const modelErrs = unlistedModels.map(\r\n (model) => `\\n${model.name} - ${model.version}: \\t${model.shortErr}`\r\n );\r\n throw Error(\r\n `Not all models could be loaded, missing models are:${modelErrs}\\n\\nFor further information see console.`\r\n );\r\n }\r\n\r\n const models = {\r\n models: JSON.parse(result.models),\r\n newModels: JSON.parse(result.new_model).map((m) =>\r\n AITrainingDataContainer.fromObject(m)\r\n ),\r\n };\r\n return models;\r\n });\r\n }\r\n\r\n /**\r\n * Read AI Model to Project Module mapping json\r\n * @returns {Promise} list of AIModel2ProjectTypeMapping objects\r\n */\r\n static async readAIModel2ProjectModuleMapping() {\r\n return fetch_auth(\"/api/ai/read_model_2_project_type_mapping\", {\r\n method: \"GET\",\r\n })\r\n .then((response) => {\r\n return response.json();\r\n })\r\n .then((json) => {\r\n return json.map((i) => AIModel2ProjectTypeMapping.fromObject(i));\r\n });\r\n }\r\n\r\n /**\r\n * Read Module mapping for one AI Model\r\n */\r\n static async readProjectTypeMappingForAIModel(modelName) {\r\n return fetch_auth(\r\n `/api/ai/read_project_type_mapping_for_model?modelName=${modelName}`,\r\n {\r\n method: \"GET\",\r\n }\r\n ).then((response) => {\r\n return response.json();\r\n });\r\n }\r\n\r\n /**\r\n *\r\n * @param {string} modelName name of the model\r\n * @param {array[object]} projectTypeMapping list of module mappings\r\n * @returns\r\n */\r\n static writeProjectTypeMappingForAIModel(modelName, projectTypeMapping) {\r\n const jsonString = JSON.stringify(projectTypeMapping);\r\n const fetch_url = `/api/ai/write_project_type_mapping_for_model?modelName=${modelName}`;\r\n return fetch_auth(fetch_url, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: jsonString,\r\n });\r\n }\r\n\r\n /**\r\n * Pre-load python modules in backend to save loading times when actually needed.\r\n */\r\n static initPythonModules() {\r\n fetch_auth(`/api/ai/init_python_modules`, {\r\n method: \"POST\",\r\n });\r\n }\r\n\r\n /**\r\n * Export an AI model to a .modelhsa file and triggers its download.\r\n * @param {Object} aiModel The model to export.\r\n * @param {Function} callback What to\r\n */\r\n static exportAIModel(aiModel, callback, errorCallback = null) {\r\n fetch_auth(`/api/ai/export_ai_model`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(aiModel),\r\n })\r\n .then((response) => {\r\n if (response.ok) {\r\n callback(response);\r\n return response.blob();\r\n } else {\r\n callback(response);\r\n window.showErrorSnackbar(\"No permission to export models!\");\r\n return null;\r\n }\r\n })\r\n .then((blob) => {\r\n if (blob !== null) {\r\n var url = window.URL.createObjectURL(blob);\r\n var a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = JSON.parse(aiModel)[\"Name\"] + \".modelhsa\";\r\n document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox\r\n a.click();\r\n a.remove(); //afterwards we remove the element again\r\n }\r\n })\r\n .catch((error) => {\r\n if (errorCallback) {\r\n errorCallback(error);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Export an AI model dataset to a .hsa file and triggers its download.\r\n * @param {Object} aiModel The model to export.\r\n * @param {Function} callback What to\r\n */\r\n static exportAIModelDataset(aiModel, callback) {\r\n fetch_auth(`/api/ai/export_ai_model_dataset`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(aiModel),\r\n })\r\n .then((response) => {\r\n if (response.ok) {\r\n callback(response);\r\n return response.blob();\r\n } else {\r\n callback(response);\r\n window.showErrorSnackbar(\"No permission to export models!\");\r\n return null;\r\n }\r\n })\r\n .then((blob) => {\r\n if (blob !== null) {\r\n var url = window.URL.createObjectURL(blob);\r\n var a = document.createElement(\"a\");\r\n a.href = url;\r\n a.download = JSON.parse(aiModel)[\"Name\"] + \"_dataset_project.hsa\";\r\n document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox\r\n a.click();\r\n a.remove(); //afterwards we remove the element again\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Deletes selected Custom AI Model\r\n * @param {*} selectedAIModel\r\n * @param {*} callback\r\n */\r\n static deleteAIModel(aiModel, callback) {\r\n fetch_auth(`/api/ai/delete_models`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(aiModel),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * Imports Exported AI Models\r\n * @param {FormFile} file\r\n * @param {Function} callback\r\n */\r\n static importAIModels(file, callback) {\r\n var data = new FormData();\r\n data.append(\"file\", file);\r\n\r\n fetch_auth(`/api/ai/import_ai_model`, {\r\n method: \"POST\",\r\n body: data,\r\n })\r\n .then((response) => response.json())\r\n .then((res) =>\r\n showHandledProblems(res, \"No permission to import models!\")\r\n )\r\n .then((res) => callback(res));\r\n }\r\n\r\n /**\r\n * Get Cuda status from backend.\r\n * @param {Function} callback Success callback with cuda status as parameter.\r\n * @param {Function} error Error callback.\r\n */\r\n static getCudaStatus(callback, error) {\r\n fetch_auth(`/api/ai/cuda_status`)\r\n .then((response) => response.json())\r\n .then((res) => {\r\n if (res.error !== \"\") {\r\n error(\"Could not get Cuda status: \", res.error);\r\n } else if (!res.payload) {\r\n error(\"Could not get Cuda status, missing payload.\");\r\n }\r\n callback(res.payload);\r\n })\r\n .catch((err) => {\r\n error(\"Error getting Cuda status: \", err);\r\n });\r\n }\r\n\r\n /**\r\n * Runs a instant analysis tool with real time updates using signalR.\r\n * New version of the previous function, Backend.aiTrainingSignalR.\r\n * @param {AITrainingSettings} data Contains the projectId as well as the parameters for the training.\r\n */\r\n static async trainModel(data) {\r\n validateInstance(\"data\", data, AITrainingSettings);\r\n\r\n // Structure Parameters and Toolsettings must be stringified\r\n data.structures.forEach((s) => {\r\n s.toolSettings = JSON.stringify(s.toolSettings);\r\n s.optionalParams = JSON.stringify(s.optionalParams);\r\n });\r\n\r\n window.showSuccessSnackbar(\"Sent training parameters.\");\r\n\r\n return fetch_auth(`/api/ai/train_model`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n }).then((response) => response.json());\r\n }\r\n\r\n /**\r\n * Get the tensorboard scalars.\r\n * @param {string} modelName Id of the closed project.\r\n * @param {function} callback Function to call upon success.\r\n * @param {function} error Function to call upon error.\r\n */\r\n static loadTensorboardScalarData = (\r\n modelName = \"\",\r\n callback,\r\n error = () => {}\r\n ) => {\r\n // TBD send API Call to ASP.NET\r\n fetch_auth(`/api/ai/scalar_data?modelName=${modelName}`)\r\n .then((res) => {\r\n if (res.ok) {\r\n return res.json();\r\n } else if (!res.ok) {\r\n return {};\r\n }\r\n })\r\n .then((res) =>\r\n res.error\r\n ? error(`Error closing project ${modelName}:\\n\\n ${res.error}`)\r\n : callback(res)\r\n )\r\n .catch((err) =>\r\n error(`Error parsing response, actions failed:\\n\\n ${err}`)\r\n );\r\n };\r\n\r\n /**\r\n * Get the current training epoch from tensorboard.\r\n * @param {string} modelName Name of the model.\r\n * @param {function} callback Function to call upon success.\r\n * @param {function} error Function to call upon error.\r\n */\r\n static getTrainingEpochProgress = (\r\n modelName = \"\",\r\n callback,\r\n error = () => {}\r\n ) => {\r\n // TBD send API Call to ASP.NET\r\n fetch_auth(`/api/ai/training_epochs_progress?modelName=${modelName}`)\r\n .then((res) => {\r\n if (res.ok) {\r\n return res.json();\r\n } else if (!res.ok) {\r\n return {};\r\n }\r\n })\r\n .then((res) =>\r\n res.error\r\n ? error(\r\n `Error reading epochs progress ${modelName}:\\n\\n ${res.error}`\r\n )\r\n : callback(res)\r\n )\r\n .catch((err) =>\r\n error(`Error parsing response, actions failed:\\n\\n ${err}`)\r\n );\r\n };\r\n\r\n /**\r\n * Runs a instant analysis tool with real time updates using signalR\r\n * @param {Function} callback Success callback\r\n */\r\n static stopAITraining(callback) {\r\n fetch_auth(`/api/ai/stop_train`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Opens a dialog where you can select an AI model for the selected structure\r\n * @param {Function} callback\r\n */\r\n static getAIModelDialogData(callback) {\r\n fetch_auth(`/api/ai/custom_models`)\r\n .then((response) => response.json())\r\n .then(callback);\r\n }\r\n\r\n /**\r\n * Copies the selected AI models to {../TEMP/custom_models/verified}-folder. This folder is accessable from the AICockpit.\r\n * @param {string} verifiedAIModel selected ai model which gets copied to verified models folder\r\n * @param {Function} callback\r\n */\r\n static addCustomAIModels(verifiedAIModel, callback) {\r\n fetch_auth(`/api/ai/add_custom_models?verifiedAIModel=${verifiedAIModel}`)\r\n .then((response) => response.json())\r\n .then((res) => callback(res));\r\n }\r\n\r\n /**\r\n * Deletes selected Custom AI Model\r\n * @param {*} selectedAIModel\r\n * @param {*} callback\r\n */\r\n static deleteCustomAIModels(selectedAIModel, callback) {\r\n fetch_auth(`/api/ai/delete_custom_models`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(selectedAIModel),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * gets the sourcepath of selected verified model\r\n * @param {*} selectedAIModel\r\n * @param {*} callback\r\n */\r\n static getSelectedModelSourcepath(selectedAIModel, callback) {\r\n fetch_auth(`/api/ai/get_model_sourcepath`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(selectedAIModel),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n // success\r\n callback(json);\r\n });\r\n }\r\n\r\n /**\r\n * sends imageData and points to backend to get a poygon using SAM\r\n *\r\n * @param {object} samData - p1, p2 and points for foreground and background with form {x: x, y: y, isForeground: boolean}\r\n **/\r\n static async useSAM(data) {\r\n return fetch_auth(\"/api/ai/use_sam\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n })\r\n .then((response) => response.json())\r\n .catch((error) => console.error(\"caught error:\", error));\r\n }\r\n // #endregion\r\n\r\n // #region File Controller\r\n /**\r\n * load all available project types\r\n * @param {String} dir directory to list files within\r\n * @param {Boolean} isRelative if dir is relative to HSA Slides directory.\r\n * @param {Function} callback contains list of all project types\r\n */\r\n static async walkDir(dir, isRelative) {\r\n return fetch_auth(\r\n `/api/file/walk_dir?path=${encodeURIComponent(\r\n dir\r\n )}&isRelative=${isRelative}`\r\n )\r\n .then((response) => response.json())\r\n .catch((error) => {\r\n console.log(\"error\", error);\r\n window.showErrorSnackbar(\"Error loading directory!\");\r\n });\r\n }\r\n\r\n /**\r\n * load a list of all jobs\r\n * @returns {Promise} list of all jobs\r\n */\r\n static async getModuleDirNames() {\r\n return fetch_auth(\"/api/file/get_module_dir_names\")\r\n .then((response) => response.json())\r\n .catch((error) => {\r\n console.log(\"error\", error);\r\n window.showErrorSnackbar(\"Error loading directory names!\");\r\n });\r\n }\r\n // #endregion\r\n\r\n // #region Analysis Controller\r\n /**\r\n * Runs a instant analysis tool with real time updates using signalR\r\n * @param {Object} data Instant analysis configuration\r\n * @param {Function} callback Success callback\r\n * @param {Function} error Error callback\r\n */\r\n static instantAnalysisSignalR(data, spinloader, callback, error) {\r\n //console.log(\"data:\", data);\r\n\r\n // connection.on(\"Progress\", (line) => {\r\n // // output debug prints of python module\r\n // //console.debug(line);\r\n // });\r\n jobProgressConnection.off(\"StandardOutput\");\r\n jobProgressConnection.on(\"StandardOutput\", (line) => {\r\n // output debug prints of python module\r\n\r\n // output warning\r\n if (line) {\r\n if (this.isJsonString(line)) {\r\n const jsonLine = JSON.parse(line);\r\n for (var k in jsonLine) {\r\n switch (k) {\r\n case \"warning\":\r\n window.showWarningSnackbar(jsonLine[\"warning\"]);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n } else {\r\n window.trainingProgress(line);\r\n }\r\n if (line.includes(\"[DownloadProgress]\")) {\r\n let progress = line.replace(\"[DownloadProgress]\", \"\");\r\n spinloader.showWithProgress({\r\n message: \"Download Model\",\r\n progress: parseInt(progress, 10),\r\n });\r\n } else if (line.includes(\"[IAMProgress]\")) {\r\n let progress = line.replace(\"[IAMProgress]\", \"\");\r\n spinloader.showWithProgress({\r\n message: \"Progress\",\r\n progress: parseInt(progress, 10),\r\n });\r\n } else if (!line.includes(\"[MESSAGE]\")) {\r\n console.debug(line);\r\n spinloader.show();\r\n } else if (line.includes(\"iam error:\")) {\r\n console.error(line);\r\n error(line);\r\n }\r\n }\r\n });\r\n jobProgressConnection.off(\"Result\");\r\n jobProgressConnection.on(\"Result\", (json) => {\r\n if (Object.keys(json).includes(\"error\") && json.error !== false) {\r\n console.error(\"Error running iam:\", json.error);\r\n // there was an exception in python module\r\n error(`Error running iam: ${json.error}`);\r\n } else {\r\n // success\r\n json.project.files.forEach((file) => {\r\n file.annotations.forEach((annotation) => {\r\n annotation.geoJSON = JSON.parse(annotation.serializedGeoJSON);\r\n annotation.serializedGeoJSON = null;\r\n });\r\n });\r\n callback(json.project);\r\n }\r\n });\r\n\r\n fetch_auth(`/api/analysis/iam`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n })\r\n .then((response) => response.json())\r\n .then((myJson) => {\r\n if (jobProgressConnection.state === 0) {\r\n // 0 = disconnected\r\n jobProgressConnection\r\n .start()\r\n .then(() =>\r\n jobProgressConnection.invoke(\"AssociateJob\", myJson.jobId)\r\n )\r\n .catch((err) => console.error(err.toString()));\r\n } else {\r\n jobProgressConnection\r\n .invoke(\"AssociateJob\", myJson.jobId)\r\n .catch((err) => console.error(err.toString()));\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Runs a instant analysis tool\r\n * @param {Object} data Instant analysis configuration\r\n * @param {Function} callback Success callback\r\n * @param {Function} error Error callback\r\n */\r\n static instantAnalysis(data, callback, error) {\r\n fetch_auth(`/api/analysis/iam`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n })\r\n .then((response) => response.json())\r\n .then((json) => {\r\n console.log(json.stdout);\r\n if (json.error) {\r\n error(json.error);\r\n } else {\r\n // success\r\n callback(json.project);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Run a IAM with the given configuration.\r\n * @param {IAMConfig} iamConfig Configuration for the IAM.\r\n * @returns {Promise} Promise containing the jobId.\r\n */\r\n static async runIAM(iamConfig) {\r\n fetch_auth(`/api/analysis/run_iam`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(iamConfig),\r\n }).then((res) => {\r\n if (res.ok) return res.json().then((json) => json.jobId);\r\n\r\n let errMsg = `Error running IAM [${res.status}]`;\r\n if (res.statusText) errMsg += `: ${res.statusText}`;\r\n console.error(errMsg);\r\n throw new Error(errMsg);\r\n });\r\n }\r\n\r\n /**\r\n * Runs a instant analysis tool with real time updates using signalR\r\n * @param {Object} data Instant analysis configuration\r\n * @param {Function} callback Success callback\r\n * @param {Function} error Error callback\r\n */\r\n static activeLearningSignalR(data, callback, error) {\r\n //console.debug(JSON.stringify(data));\r\n\r\n let connection = new HubConnectionBuilder()\r\n .withUrl(\"/jobprogress\")\r\n .configureLogging(LogLevel.Warning)\r\n .build();\r\n connection.serverTimeoutInMilliseconds = 5000000; // 5000 second\r\n // connection.on(\"Progress\", (line) => {\r\n // // output debug prints of python module\r\n // //console.debug(line);\r\n // });\r\n connection.on(\"StandardOutput\", (line) => {\r\n // output debug prints and warnings of python module\r\n if (line) {\r\n if (this.isJsonString(line)) {\r\n const jsonLine = JSON.parse(line);\r\n for (var k in jsonLine) {\r\n switch (k) {\r\n case \"warning\":\r\n window.showWarningSnackbar(jsonLine[\"warning\"]);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n } else {\r\n window.galleryTrainingProgress(line);\r\n }\r\n console.debug(line);\r\n }\r\n });\r\n connection.on(\"Result\", (json) => {\r\n if (json.error) {\r\n // there was an exception in python module\r\n error(json.error);\r\n } else {\r\n // success\r\n callback(json.alModel);\r\n }\r\n });\r\n\r\n fetch_auth(`/api/analysis/alm`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(data),\r\n })\r\n .then((response) => response.json())\r\n .then((myJson) => {\r\n connection\r\n .start()\r\n .then(() => connection.invoke(\"AssociateJob\", myJson.jobId))\r\n .catch((err) => console.error(err.toString()));\r\n });\r\n }\r\n\r\n /**\r\n * Receives instructions on how to perform PCA in json format\r\n * Sends results in json format. Gives real time updates.\r\n * @param {JSON} graphRequestSettings Specification of the request\r\n * @param {Function} callback Success callback on json request\r\n * @param {Function} error Error callback on json request\r\n * @param {Function} progressCallback Webhook callback for progress\r\n */\r\n static requestSpectraData(\r\n graphRequestSettings,\r\n callback,\r\n error,\r\n progressCallback\r\n ) {\r\n let connection = new HubConnectionBuilder()\r\n .withUrl(\"/jobprogress\")\r\n .configureLogging(LogLevel.Warning)\r\n .build();\r\n connection.serverTimeoutInMilliseconds = 5000000; // 5000 second\r\n connection.on(\"StandardOutput\", (line) => {\r\n // output debug prints of python module\r\n if (line) {\r\n // NOTE: [MESSAGE] is kept as compatibility with independent import functions\r\n // used for Image import, background AI processes, etc.\r\n if (line.startsWith(\"[MESSAGE]\")) {\r\n // Remove [MESSAGE] and extract JSON payload\r\n progressCallback(JSON.parse(line.slice(9)));\r\n } else {\r\n console.debug(line);\r\n }\r\n }\r\n });\r\n\r\n // Add GUID for WebHook\r\n graphRequestSettings.jobId = uuidv4();\r\n connection\r\n .start()\r\n .then(() => connection.invoke(\"AssociateJob\", graphRequestSettings.jobId))\r\n .catch((err) => {\r\n console.log(\"error catch\");\r\n console.error(err.toString());\r\n });\r\n\r\n var requestOptions = {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"application/json\",\r\n },\r\n body: JSON.stringify(graphRequestSettings),\r\n };\r\n\r\n fetch_auth(\"/api/analysis/pcaupdate\", requestOptions)\r\n .then((response) => response.json())\r\n .then((json) => {\r\n if (json.result.error) {\r\n // there was an exception in python module\r\n error(json.result.error);\r\n } else {\r\n // success\r\n callback(json.result);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Request all IAMs from the backend, with their default settings.\r\n * If a specific IAM is requested, only that IAM with its default settings will be returned.\r\n * @param {string} iamName Optional. The name of the IAM to get the data for. If not provided, all IAMs will be returned. Defaults to null.\r\n * @returns {Promise} Promise containing the IAMs.\r\n */\r\n static async getIams(iamName = null) {\r\n const requestString = iamName\r\n ? `/api/analysis/iams?name=${iamName}`\r\n : `/api/analysis/iams`;\r\n return fetch_auth(requestString)\r\n .then((response) => response.json())\r\n .then((res) => res.map((iam) => InstantAnalysisModule.fromObject(iam)));\r\n }\r\n\r\n /**\r\n * Request the names of the default IAMs from the backend.\r\n * If not type is not provided, return a mapping of annotation type to default iams.\r\n * Otherwise, return a list of the default IAM names.\r\n * @param {string} type The type of IAMs to get the names for.\r\n * @returns {Promise} Promise containing a list of the default IAM names for the annotation type.\r\n */\r\n static async getDefaultIamNames(type) {\r\n return fetch_auth(`/api/analysis/default_iam_names?type=${type}`).then(\r\n (res) => {\r\n if (res.ok) {\r\n return res.json();\r\n }\r\n let errorStr = `Failed to get default IAM names [${res.status}]`;\r\n if (res.statusMessage) {\r\n errorStr += `: ${res.statusMessage}`;\r\n }\r\n throw new Error(errorStr);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Request all Job names from the backend.\r\n * @returns {Promise} Promise containing the job names.\r\n */\r\n static async getJobNames() {\r\n return fetch_auth(`/api/analysis/jobs`).then((response) => response.json());\r\n }\r\n // #endregion\r\n\r\n // #region Audio Controller\r\n /**\r\n * Load a specific audio file to frontend.\r\n * @param {string} id UUID of the file to be loaded.\r\n * @returns {Promise} Promise containing the audio file.\r\n */\r\n static async loadAudioFile(id) {\r\n return fetch_auth(`/api/audio/load_audio_file?id=${id}`)\r\n .then((res) => {\r\n if (res.ok) {\r\n return res.blob();\r\n } else {\r\n try {\r\n return res.json();\r\n } catch {\r\n return { error: `Could not load file ${id}` };\r\n }\r\n }\r\n })\r\n .then((res) => {\r\n if (res.error)\r\n throw Error(`Failed to load file ${id}:\\n\\n${res.error}`);\r\n return window.URL.createObjectURL(res);\r\n });\r\n }\r\n // #endregion\r\n\r\n // #region UNSAFE: Direct, unauthenticated python server calls\r\n /**\r\n * gets metadata from .hsasld file\r\n */\r\n static getFileMetadata(path, callback) {\r\n fetch(PYTHON_SERVER_URL + \"/api/v1/scan/get_hsasld_meta?path=\" + path)\r\n .then((response) => {\r\n return response.json();\r\n })\r\n .then((myJson) => callback(myJson));\r\n }\r\n // #endregion\r\n}\r\n","// Copyright HS Analysis GmbH, 2024\r\n// Author: Viktor Eberhardt\r\n\r\n// Description: Mapping Model to map one AI model to one projectType\r\n\r\n// Keep in sync C# and js frontend\r\n// Source\\HSA-Kit\\Models\\AIModel2ProjectTypeMapping.cs\r\n\r\n/**\r\n * AIModel2ProjectTypeMapping class for AI Model to ProjectType mapping.\r\n */\r\n\r\n// HSA imports\r\nimport {\r\n AudioInferenceParameters,\r\n ImageInferenceParameters,\r\n InferenceParameters,\r\n} from \"../../common/components/IAMConfig\";\r\nimport { TargetDataFormat } from \"../../common/components/AITrainingSettings\";\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n validateInEnum,\r\n validateInstance,\r\n validateType,\r\n ValidationType,\r\n} from \"../../common/utils/Utils\";\r\n\r\nexport default class AIModel2ProjectTypeMapping {\r\n /**\r\n * Constructor for AIModel2ProjectTypeMapping.\r\n * @param {string} projectType ProjectType name.\r\n * @param {string} aiModel AI Model name.\r\n * @param {TargetDataFormat} targetDataFormat The type of the target format of the AI model.\r\n * @param {List[StructureMapping]} structureMappings Mapping of old structures to new Structures of selected project type.\r\n * @param {InferenceParameters} inferenceParameters Model specific parameters.\r\n * @param {Int} outerStructureId OuterId of the mapping.\r\n * @param {bool} isActive Is model active.\r\n */\r\n constructor(\r\n projectType,\r\n aiModel,\r\n targetDataFormat,\r\n structureMappings,\r\n inferenceParameters,\r\n outerStructureId,\r\n isActive\r\n ) {\r\n // Input validation\r\n validateType(\"projectType\", projectType, ValidationType.String);\r\n validateType(\"aiModel\", aiModel, ValidationType.String);\r\n validateInEnum(\"targetDataFormat\", targetDataFormat, TargetDataFormat);\r\n validateInstance(\"structureMappings\", structureMappings, Array);\r\n structureMappings.forEach((structureMapping) => {\r\n validateInstance(\"structureMapping\", structureMapping, StructureMapping);\r\n });\r\n\r\n validateInstance(\r\n \"inferenceParameters\",\r\n inferenceParameters,\r\n InferenceParameters\r\n );\r\n\r\n validateType(\"outerStructureId\", outerStructureId, ValidationType.Int);\r\n validateType(\"isActive\", isActive, ValidationType.Bool);\r\n\r\n this.projectType = projectType;\r\n this.aiModel = aiModel;\r\n this.structureMappings = structureMappings;\r\n this.inferenceParameters = inferenceParameters;\r\n this.outerStructureId = outerStructureId;\r\n this.isActive = isActive;\r\n }\r\n\r\n /**\r\n * Create new AIModel2ProjectTypeMapping from an object without needing to define all parameters individually.\r\n * Accepts camelCase and PascalCase properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per AIModel2ProjectTypeMapping contructor.\r\n * @param {object} obj An object containing all necessary properties of AIModel2ProjectTypeMapping.\r\n * @returns {AIModel2ProjectTypeMapping} New AIModel2ProjectTypeMapping.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n validateInstance(\"structureMappings\", obj.structureMappings, Array);\r\n validateInEnum(\"targetDataFormat\", obj.targetDataFormat, TargetDataFormat);\r\n\r\n // Depending on the targetDataFormat, the inferenceParameters must be set\r\n switch (obj.targetDataFormat) {\r\n case TargetDataFormat.Image:\r\n obj.inferenceParameters = ImageInferenceParameters.fromObject(\r\n obj.inferenceParameters\r\n );\r\n break;\r\n case TargetDataFormat.Audio:\r\n obj.inferenceParameters = AudioInferenceParameters.fromObject(\r\n obj.inferenceParameters\r\n );\r\n break;\r\n default:\r\n obj.inferenceParameters = InferenceParameters.fromObject(\r\n obj.inferenceParameters\r\n );\r\n break;\r\n }\r\n\r\n return new AIModel2ProjectTypeMapping(\r\n obj.projectType,\r\n obj.aiModel,\r\n obj.targetDataFormat,\r\n obj.structureMappings.map((structureMapping) =>\r\n StructureMapping.fromObject(structureMapping)\r\n ),\r\n obj.inferenceParameters,\r\n obj.outerStructureId,\r\n obj.isActive\r\n );\r\n }\r\n}\r\n\r\nexport class StructureMapping {\r\n /**\r\n * Constructor for StructureMapping.\r\n * @param {Number} oldId Old structure id.\r\n * @param {Number} newId New structure id.\r\n */\r\n constructor(oldId, newId) {\r\n // Input validation\r\n if (oldId !== null) validateType(\"oldId\", oldId, ValidationType.Int);\r\n if (newId !== null) validateType(\"newId\", newId, ValidationType.Int);\r\n\r\n this.oldId = oldId;\r\n this.newId = newId;\r\n }\r\n\r\n /**\r\n * Create new StructureMapping from an object without needing to define all parameters individually.\r\n * Accepts camelCase and PascalCase properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per StructureMapping contructor.\r\n *\r\n * @param {object} obj An object containing all necessary properties of StructureMapping.\r\n * @returns {Structure} New StructureMapping.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n const oldId = obj.oldId;\r\n let newId = obj.newId;\r\n\r\n // explicitly allow \"newId\" to be null\r\n if (newId === undefined) {\r\n newId = null;\r\n }\r\n\r\n return new StructureMapping(oldId, newId);\r\n }\r\n}\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nconst PersistentStorageContext = React.createContext();\r\n\r\nexport const withPersistentStorage = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withPersistentStorage(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\n// this is the main component, it has to be added at the root of the app.\r\n// all components that use withPersistentStorage(...) will have access to it via this.props.persistentStorage...\r\nclass PersistentStorageProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n this._isMounted = false;\r\n const loadedProjectState = JSON.parse(\r\n localStorage.getItem(this.props.projectId)\r\n );\r\n this.projectState = loadedProjectState ? loadedProjectState : {};\r\n this.projectTypeState = null;\r\n }\r\n\r\n save(key, value) {\r\n let v = JSON.stringify(value);\r\n let stateObject = { ...this.projectState }; //copy whole state for saving\r\n stateObject[key] = v;\r\n localStorage.setItem(this.props.projectId, JSON.stringify(stateObject));\r\n this.projectState[key] = v;\r\n }\r\n\r\n load(key) {\r\n if (typeof this.projectState[key] === \"string\") {\r\n try {\r\n return JSON.parse(this.projectState[key]);\r\n } catch (e) {\r\n return this.projectState[key];\r\n }\r\n } else {\r\n return this.projectState[key];\r\n }\r\n }\r\n\r\n saveProjectTypeValue(projectType, key, value) {\r\n let v = JSON.stringify(value);\r\n let stateObject = { ...this.projectTypeState }; //copy whole state for saving\r\n stateObject[key] = v;\r\n localStorage.setItem(\"local_\" + projectType, JSON.stringify(stateObject));\r\n this.projectState[key] = v;\r\n }\r\n\r\n loadProjectTypeValue(projectType, key) {\r\n if (this.projectTypeState == null) {\r\n this.projectTypeState = JSON.parse(\r\n localStorage.getItem(\"local_\" + projectType)\r\n );\r\n }\r\n if (this.projectTypeState == null) return null;\r\n if (typeof this.projectTypeState[key] === \"string\") {\r\n try {\r\n return JSON.parse(this.projectTypeState[key]);\r\n } catch (e) {\r\n return this.projectTypeState[key];\r\n }\r\n } else {\r\n return this.projectTypeState[key];\r\n }\r\n }\r\n\r\n loadAll() {\r\n let stateObject = {};\r\n for (const [key, value] of Object.entries(this.projectState)) {\r\n try {\r\n stateObject[key] = JSON.parse(value);\r\n } catch (e) {\r\n stateObject[key] = value;\r\n }\r\n }\r\n return stateObject;\r\n }\r\n\r\n render() {\r\n return (\r\n this.save(key, value),\r\n saveProjectTypeValue: (projectType, key, value) =>\r\n this.saveProjectTypeValue(projectType, key, value),\r\n load: (key) => this.load(key),\r\n loadProjectTypeValue: (projectType, key) =>\r\n this.loadProjectTypeValue(projectType, key),\r\n loadAll: () => this.loadAll(),\r\n }}\r\n >\r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nPersistentStorageProvider.propTypes = {\r\n projectId: PropTypes.string,\r\n children: PropTypes.element.isRequired,\r\n};\r\n\r\nexport default PersistentStorageProvider;\r\n","// RandomColorGenerator.jsx\r\n// This file contains functions to generate \"random\" colors from a predetermined list of colors.\r\n\r\n// Copyright HS Analysis GmbH, 2022\r\n// Author: Valentin Haas\r\n\r\nimport Structure from \"../components/Structure\";\r\nimport { ValidationType, validateType, validateInstance } from \"./Utils\";\r\n\r\n/**\r\n * Predetermined colors to be used.\r\n */\r\nexport const presetColors = [\r\n \"#e6194b\",\r\n \"#3cb44b\",\r\n \"#ffe119\",\r\n \"#4363d8\",\r\n \"#f58231\",\r\n \"#911eb4\",\r\n \"#46f0f0\",\r\n \"#f032e6\",\r\n \"#bcf60c\",\r\n \"#fabebe\",\r\n \"#008080\",\r\n \"#e6beff\",\r\n \"#9a6324\",\r\n \"#fffac8\",\r\n \"#800000\",\r\n \"#aaffc3\",\r\n \"#808000\",\r\n \"#ffd8b1\",\r\n \"#000075\",\r\n \"#808080\",\r\n \"#000000\",\r\n];\r\n\r\n/**\r\n * Get a random color, the first 21 colors are predetermined.\r\n * @param {int} colorIdx Optional. Used when querying a color and wanting to use the predetermined colors. Defaults to -1.\r\n * @returns {string} A string representing a color #01234EF.\r\n */\r\nexport function getRandomColor(colorIdx = null) {\r\n if (colorIdx !== null) validateType(\"colorIdx\", colorIdx, ValidationType.Int);\r\n if (colorIdx !== null && colorIdx < 0)\r\n throw RangeError(\r\n `colorIdx must be of type integer >= 0, received ${typeof colorIdx}: ${colorIdx}`\r\n );\r\n\r\n var letters = \"0123456789ABCDEF\";\r\n var color = \"#\";\r\n if (colorIdx >= 0 && colorIdx < presetColors.length) {\r\n color = presetColors[colorIdx];\r\n colorIdx++;\r\n } else {\r\n for (var i = 0; i < 6; i++) {\r\n color += letters[Math.floor(Math.random() * 16)];\r\n }\r\n }\r\n return color;\r\n}\r\n\r\n/**\r\n * Get a color currently not used in structures.\r\n * @param {array} structures Existing structures.\r\n * @param {bool} UNSAFE_checkStructureType Optional. Validate structure type. Defaults to true.\r\n * @returns {string} A string representing a color #01234EF.\r\n */\r\nexport function getUnusedColor(structures, UNSAFE_checkStructureType = true) {\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n if (UNSAFE_checkStructureType) {\r\n structures.forEach((s) => {\r\n validateInstance(\"structure\", s, Structure);\r\n });\r\n }\r\n\r\n let counter = 0;\r\n let color = getRandomColor(counter);\r\n while (structures.some((s) => s.color === color) && counter < 50) {\r\n counter++;\r\n color = getRandomColor(counter);\r\n }\r\n return color;\r\n}\r\n","// FindFilesDialog.jsx\r\n// Screen shown when importing a project to verify automatically found files and specify missing or duplicate files. Map files of imported project or re-map missing files.\r\n\r\n// Copyright HS Analysis GmbH, 2019\r\n// Author: Sebastian Murgul, Valentin Haas, Viktor Eberhardt\r\n\r\n// Framework imports\r\nimport React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// Material-UI imports\r\nimport Accordion from \"@mui/material/Accordion\";\r\nimport AccordionDetails from \"@mui/material/AccordionDetails\";\r\nimport AccordionSummary from \"@mui/material/AccordionSummary\";\r\nimport Button from \"@mui/material/Button\";\r\nimport CheckIcon from \"@mui/icons-material/Check\";\r\nimport CircularProgress from \"@mui/material/CircularProgress\";\r\nimport ContentCopyIcon from \"@mui/icons-material/ContentCopy\";\r\nimport Dialog from \"@mui/material/Dialog\";\r\nimport DialogActions from \"@mui/material/DialogActions\";\r\nimport DialogContent from \"@mui/material/DialogContent\";\r\nimport DialogContentText from \"@mui/material/DialogContentText\";\r\nimport DialogTitle from \"@mui/material/DialogTitle\";\r\nimport ErrorIcon from \"@mui/icons-material/Error\";\r\nimport IconButton from \"@mui/material/IconButton\";\r\nimport InputAdornment from \"@mui/material/InputAdornment\";\r\nimport RefreshIcon from \"@mui/icons-material/Refresh\";\r\nimport TextField from \"@mui/material/TextField\";\r\nimport Tooltip from \"@mui/material/Tooltip\";\r\nimport Typography from \"@mui/material/Typography\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\n// HSA imports\r\nimport Backend from \"../../common/utils/Backend\";\r\nimport LazyRender from \"../../common/components/LazyRender\";\r\n\r\nconst styles = () => ({\r\n root: {},\r\n dialogContent: {\r\n paddingTop: 0,\r\n maxWidth: 900,\r\n minWidth: 750,\r\n },\r\n});\r\n\r\n/**\r\n * Enum for project action mode.\r\n */\r\nexport const ProjectActionMode = Object.freeze({\r\n Import: 0,\r\n Update: 1,\r\n Query: 2,\r\n});\r\n\r\n/**\r\n * Content of the dialog, depending on the project action mode.\r\n */\r\nconst _dialogContent = Object.freeze({\r\n [ProjectActionMode.Import]: {\r\n title: \"Map Files of Imported Project\",\r\n text: \"An exported project does not contain image files, only their respective names. \",\r\n },\r\n [ProjectActionMode.Update]: {\r\n title: \"Re-Map Missing Files\",\r\n text: \"Not all files previously associated with this project could be found in their original location. \",\r\n },\r\n});\r\n\r\nclass FindFilesDialog extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n formData: props.formData ?? {\r\n fileMappings: [],\r\n },\r\n openAccordion: null,\r\n dialogIsOpen: Boolean(props.open),\r\n onSuccess: props.onSuccess ?? (() => {}),\r\n };\r\n }\r\n\r\n /**\r\n * Set the mounted state of the component. This is used to prevent setting the state after the component has been unmounted.\r\n * @param {object} stateObject The state object to set.\r\n * @param {function} callback The callback function to call after setting the state.\r\n */\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n /**\r\n * Open/Show FindFilesDialog.\r\n * Main way to open this dialog.\r\n * @param {JSON} formData File mappings, mapping previous to new files.\r\n */\r\n show(formData, onSuccess = () => {}) {\r\n this.setState({ dialogIsOpen: true, formData, onSuccess: onSuccess });\r\n }\r\n\r\n /**\r\n * Close FindFilesDialog. Resets state.\r\n */\r\n handleClose = () => {\r\n this.setState({\r\n dialogIsOpen: false,\r\n openAccordion: null,\r\n formData: {\r\n fileMappings: [],\r\n projects: [],\r\n },\r\n isValidating: false,\r\n });\r\n };\r\n\r\n /**\r\n * Re-run the automatic file search and update the file mappings.\r\n * @param {boolean} checkUnique If true, check if all files are uniquely mapped after refresh.\r\n */\r\n handleRefresh = (checkUnique = true) => {\r\n const { formData } = this.state;\r\n Backend.checkFileMappings(\r\n formData,\r\n ProjectActionMode.Query,\r\n (res) => {\r\n // Incomplete file mappings\r\n if (checkUnique && !res.allUniquelyMapped) {\r\n window.showWarningSnackbar(\r\n `Not all files could be uniquely associated. Please adapt the paths of all missing or duplicate paths.`\r\n );\r\n }\r\n this.setState({ formData: res });\r\n },\r\n // Error\r\n (err) => {\r\n console.error(err);\r\n window.openWarningDialog(err);\r\n }\r\n );\r\n };\r\n\r\n /**\r\n * Submit all updated filepaths to backend for check and - if successfull - project completion.\r\n */\r\n handleSubmit = () => {\r\n const { formData } = this.state;\r\n const { projectActionMode } = this.props;\r\n this.setState({ isValidating: true });\r\n Backend.checkFileMappings(\r\n formData,\r\n projectActionMode,\r\n (res) => {\r\n // Incomplete file mappings\r\n if (!res.allUniquelyMapped) {\r\n window.showWarningSnackbar(\r\n `Not all files could be uniquely associated. Please adapt the paths of all missing or duplicate paths.`\r\n );\r\n this.setState({ formData: res });\r\n return;\r\n }\r\n // Import completed without changes\r\n this.handleClose();\r\n this.state.onSuccess();\r\n this.setMountedState({ isValidating: false });\r\n },\r\n // Error\r\n (err) => {\r\n console.error(err);\r\n window.openWarningDialog(err);\r\n this.setMountedState({ isValidating: false });\r\n }\r\n );\r\n };\r\n\r\n /**\r\n * Generates a formatted file list, so that all three types of files may ues the same code.\r\n * @param {Array} files Files to map to screen.\r\n * @returns {div} Files mapped and formatted.\r\n */\r\n generateFileList(files) {\r\n return (\r\n \r\n {files.map((f) => (\r\n
\r\n \r\n \r\n \r\n \r\n \r\n ) : f.found ? (\r\n // Files found\r\n \r\n \r\n \r\n \r\n \r\n ) : (\r\n // Missing files\r\n \r\n \r\n \r\n \r\n \r\n ),\r\n }}\r\n disabled\r\n margin=\"dense\"\r\n label=\"Old Path\"\r\n fullWidth\r\n variant=\"filled\"\r\n />\r\n {\r\n f.newPath = e.target.value;\r\n this.forceUpdate();\r\n }}\r\n margin=\"dense\"\r\n label=\"New Path\"\r\n fullWidth\r\n error={!f.found || f.duplicatePath}\r\n />\r\n
\r\n ))}\r\n
\r\n );\r\n }\r\n\r\n render() {\r\n const { dialogIsOpen, formData } = this.state;\r\n const { classes, projectActionMode } = this.props;\r\n // Only show unique source files, not one per scene of file.\r\n const uniqueFiles = formData.fileMappings\r\n .filter(\r\n (mapping, index, array) =>\r\n array.findIndex(\r\n (el) => el.file.sourcePath === mapping.file.sourcePath\r\n ) === index\r\n )\r\n .sort((a, b) => a.file.sourcePath.localeCompare(b.file.sourcePath));\r\n\r\n const filesFound = uniqueFiles.filter((f) => f.found);\r\n const missing = uniqueFiles.filter((f) => !f.found && !f.duplicatePath);\r\n // Duplicates are files that have the same source path as another file.\r\n // Sort them by their file name, to group them together for easier editing.\r\n const duplicates = uniqueFiles\r\n .filter((f) => f.duplicatePath)\r\n .sort((a, b) =>\r\n a.newPath.split(\"/\").pop().localeCompare(b.newPath.split(\"/\").pop())\r\n );\r\n\r\n return (\r\n \r\n \r\n
\r\n {_dialogContent[projectActionMode].title}\r\n \r\n this.handleRefresh(false)}\r\n >\r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n {_dialogContent[projectActionMode].text}\r\n Please select the corresponding files from your hard drive.\r\n \r\n {\r\n this.setState({ openAccordion: expanded ? \"found\" : null });\r\n }}\r\n >\r\n \r\n {`Files Found (${filesFound.length})`}\r\n \r\n \r\n \r\n No further action needed. These files could automatically be\r\n associated with existing files inside your slides folder.\r\n \r\n {this.generateFileList(filesFound)}\r\n \r\n \r\n {\r\n this.setState({ openAccordion: expanded ? \"missing\" : null });\r\n }}\r\n >\r\n \r\n {`Files Missing (${missing.length})`}\r\n \r\n \r\n \r\n These files could not be automatically found inside your slides\r\n folder. Perhaps their names have changed or they need to be\r\n added again. Please insert missing files to the slides folder or\r\n specify their new name.\r\n \r\n {this.generateFileList(missing)}\r\n \r\n \r\n {\r\n this.setState({ openAccordion: expanded ? \"duplicate\" : null });\r\n }}\r\n >\r\n \r\n {`Duplicate Files (${duplicates.length})`}\r\n \r\n \r\n \r\n Multiple of the imported files have been associated with the\r\n same file inside your slides folder. It could not be\r\n automatically determined which on is correct, so the first one\r\n was chosen. It is not allowed to have the same file twice in a\r\n project, therefore, please inspect all duplicated and specify\r\n their correct path.\r\n \r\n {this.generateFileList(duplicates)}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {this.state.isValidating ? : \"Ok\"}\r\n \r\n \r\n
\r\n );\r\n }\r\n}\r\n\r\nFindFilesDialog.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n formData: PropTypes.object,\r\n onSuccess: PropTypes.func,\r\n open: PropTypes.bool,\r\n projectActionMode: PropTypes.number.isRequired,\r\n};\r\n\r\nexport default withStyles(styles)(FindFilesDialog);\r\n","// Copyright HS Analysis GmbH, 2023\r\n// Author: Lukas Buess\r\n\r\n// HSA imports\r\n\r\n// Keep in sync with:\r\n// Source\\HSA-KIT\\modules\\hsa\\core\\ai\\....py\r\n// Source\\HSA-KIT\\ClientApp\\src\\common\\components\\....jsx\r\n\r\n// HSA imports\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n validateInstance,\r\n validateType,\r\n ValidationType,\r\n} from \"../utils/Utils\";\r\n\r\n/**\r\n * All dataset specific parameters of an AI Training.\r\n * @param {String} os Operating system. Default: \"No Information!\".\r\n * @param {String} cpu Name of CPU. Default: \"No Information!\".\r\n * @param {String} gpu Name of GPU. Default: \"No Information!\".\r\n * @param {String} ram Amount of RAM. Default: \"No Information!\".\r\n */\r\nexport class SystemInformation {\r\n constructor(\r\n os = \"No Information!\",\r\n cpu = \"No Information!\",\r\n gpu = \"No Information!\",\r\n ram = \"No Information!\"\r\n ) {\r\n // Input validation\r\n validateType(\"os\", os, ValidationType.String);\r\n validateType(\"cpu\", cpu, ValidationType.String);\r\n validateType(\"gpu\", gpu, ValidationType.String);\r\n validateType(\"ram\", ram, ValidationType.String);\r\n\r\n this.os = os;\r\n this.cpu = cpu;\r\n this.gpu = gpu;\r\n this.ram = ram;\r\n }\r\n\r\n /**\r\n * Create a new SystemInformation from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per SystemInformation constructor.\r\n * @param {object} obj An object containing all necessary properties of SystemInformation.\r\n * @returns {SystemInformation} New SystemInformation.\r\n */\r\n static fromObject(obj) {\r\n return new SystemInformation(\r\n obj.os ?? obj.Os,\r\n obj.cpu ?? obj.Cpu,\r\n obj.gpu ?? obj.Gpu,\r\n obj.ram ?? obj.Ram\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Information of an AI Training.\r\n * @param {String} creationDate Date when training was started.\r\n * @param {String} completionDate Date when training was completed.\r\n * @param {SystemInformation} systemInformation Information about the system used for training.\r\n * @param {String} trainingStatus status of the AI Training.\r\n * @param {String} errorMessage Error message if training failed.\r\n */\r\nexport class AITrainingInformation {\r\n constructor(\r\n creationDate = \"\",\r\n completionDate = \"\",\r\n systemInformation = new SystemInformation(),\r\n trainingStatus = \"pending\",\r\n errorMessage = \"\"\r\n ) {\r\n // Input validation\r\n validateType(\"creationDate\", creationDate, ValidationType.String);\r\n validateType(\"completionDate\", completionDate, ValidationType.String);\r\n validateInstance(\"systemInformation\", systemInformation, SystemInformation);\r\n validateType(\"trainingStatus\", trainingStatus, ValidationType.String);\r\n validateType(\"errorMessage\", errorMessage, ValidationType.String);\r\n\r\n // Set parameters\r\n this.creationDate = creationDate;\r\n this.completionDate = completionDate;\r\n this.systemInformation = systemInformation;\r\n this.trainingStatus = trainingStatus;\r\n this.errorMessage = errorMessage;\r\n }\r\n\r\n /**\r\n * Create a new AITrainingInformation from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per AITrainingInformation constructor.\r\n * @param {object} obj An object containing all necessary properties of AITrainingInformation.\r\n * @returns {AITrainingInformation} New AITrainingInformation.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new AITrainingInformation(\r\n obj.creationDate,\r\n obj.completionDate,\r\n SystemInformation.fromObject(obj.systemInformation),\r\n obj.trainingStatus,\r\n obj.errorMessage\r\n );\r\n }\r\n}\r\n","// Copyright HS Analysis GmbH, 2023\r\n// Author: Lukas Buess\r\n\r\n// HSA imports\r\nimport AITrainingSettings from \"./AITrainingSettings.jsx\";\r\nimport { AITrainingInformation } from \"./AITrainingInformation.jsx\";\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n validateInstance,\r\n} from \"../utils/Utils\";\r\n\r\n/**\r\n * Information of an AI Training.\r\n * @param {AITrainingSettings} settings Settings used to train the AI model.\r\n * @param {AITrainingInformation} information Information about the AI training (e.g. progress, hardware, ...).\r\n */\r\nexport default class AITrainingDataContainer {\r\n constructor(\r\n settings = new AITrainingSettings(),\r\n information = new AITrainingInformation()\r\n ) {\r\n // Input validation\r\n validateInstance(\"settings\", settings, AITrainingSettings);\r\n validateInstance(\"information\", information, AITrainingInformation);\r\n\r\n // Set parameters\r\n this.settings = settings;\r\n this.information = information;\r\n }\r\n\r\n /**\r\n * Create a new AITrainingDataContainer from an object without needing to define all parameters individually.\r\n * Accepts camelCase and PascalCase properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per AITrainingDataContainer constructor.\r\n * @param {object} obj An object containing all necessary properties of AITrainingDataContainer.\r\n * @returns {AITrainingDataContainer} New AITrainingDataContainer.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new AITrainingDataContainer(\r\n AITrainingSettings.fromObject(obj.settings),\r\n AITrainingInformation.fromObject(obj.information)\r\n );\r\n }\r\n}\r\n","// ProjectContext.jsx\r\n// Project properties that are shared between many components.\r\n\r\n// Copyright HS Analysis GmbH, 2019\r\n// Author: Viktor Eberhardt, Sebastian Murgul, Jakob Burkhardt, Valentin Haas\r\n\r\n// Framework imports\r\nimport React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// External imports\r\n\r\n// Other imports\r\nimport RBush from \"rbush\";\r\n\r\n// HSA imports\r\nimport { createRoisFromAnno } from \"../utils/ROI\";\r\nimport {\r\n getParentIndexLayer,\r\n updateStructures,\r\n} from \"../utils/StructuresUtils\";\r\nimport { getUnusedColor } from \"../../common/utils/RandomColorGenerator\";\r\nimport Backend from \"../../common/utils/Backend\";\r\nimport Structure from \"../../common/components/Structure\";\r\n\r\nconst ProjectContext = React.createContext();\r\nexport { ProjectContext };\r\n\r\nexport const withProject = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withProject(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\n// this is the main component, it has to be added at the root of the app.\r\n// all components that use withProject(...) will have access to it via this.props.Project...\r\nclass ProjectProvider extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this._isMounted = false;\r\n this.state = {\r\n wasSavedByUser: false,\r\n structures: [],\r\n roiLayers: {},\r\n commentLayers: {},\r\n selectedLayer: 0,\r\n ome: null,\r\n activeTab: 0,\r\n changingFile: false,\r\n user: \"\",\r\n isLoadingAnnotations: false,\r\n galleryImageSize: 300,\r\n userPermissions: {\r\n canImportModels: true,\r\n canExportModels: true,\r\n },\r\n groupPermissions: {\r\n canAnnotate: true,\r\n canTrainModel: true,\r\n canRunJob: true,\r\n canComment: true,\r\n canEditStructures: true,\r\n canAccessAITab: true,\r\n canEditModel: true,\r\n },\r\n annotationsReduced: false,\r\n totalRoiCount: -1,\r\n shortCutButtonIdList: [],\r\n aiModel2ProjectModuleMappings: [],\r\n allAiModels: [],\r\n projectStructures: [],\r\n opacity: 1.2,\r\n };\r\n this.usersData = {};\r\n Backend.getModelMetadata(\"hsa_models\", false)\r\n .then((aiModels) => {\r\n this.setMountedState({ allAiModels: aiModels.newModels });\r\n })\r\n .catch((error) => {\r\n console.error(\"Error loading model metadata: \", error);\r\n });\r\n }\r\n\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n componentDidMount() {\r\n this._isMounted = true;\r\n }\r\n\r\n componentWillUnmount() {\r\n this._isMounted = false;\r\n }\r\n\r\n // init ai models\r\n initAIData = () => {\r\n Backend.readAIModel2ProjectModuleMapping().then((mappingData) => {\r\n this.setMountedState({ aiModel2ProjectModuleMappings: mappingData });\r\n if (this.state.wasSavedByUser) return;\r\n\r\n // Project was not saved yet\r\n const projectObject = { ...this.state.project };\r\n const structures = projectObject.viewerConfig.project.structures;\r\n const projectType = this.state.project.type;\r\n const filteredMappingData = mappingData.filter(\r\n (item) => item.projectType === projectType\r\n );\r\n\r\n for (const mappingItem of filteredMappingData) {\r\n for (const structureMapping of mappingItem.structureMappings) {\r\n const newId = structureMapping.newId;\r\n const structureIdx = structures.findIndex((s) => s.id === newId);\r\n const structure = structures[structureIdx];\r\n if (!structure) continue;\r\n\r\n const toolIdx = structure.tools.findIndex(\r\n (t) => t.name === \"iam_ai_inference\"\r\n );\r\n const tool = structure.tools[toolIdx];\r\n for (const toolParam of tool.toolParams) {\r\n switch (toolParam.name) {\r\n case \"ai_model_name\":\r\n if (mappingItem.isActive) {\r\n toolParam.ui.default = mappingItem.aiModel;\r\n toolParam.ui.value = mappingItem.aiModel;\r\n }\r\n break;\r\n case \"area_min\":\r\n toolParam.ui.default = mappingItem.inferenceParameters.minSize;\r\n break;\r\n case \"area_max\":\r\n toolParam.ui.default = mappingItem.inferenceParameters.maxSize;\r\n break;\r\n case \"intensity_range\":\r\n toolParam.ui.default = [\r\n mappingItem.inferenceParameters.minIntensity,\r\n mappingItem.inferenceParameters.maxIntensity,\r\n ];\r\n break;\r\n case \"confience_threshold\":\r\n toolParam.ui.default =\r\n mappingItem.inferenceParameters.confidence;\r\n break;\r\n case \"depending_structure\":\r\n toolParam.ui.default =\r\n mappingItem.inferenceParameters.dependingStructure;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n this.setMountedState({ project: projectObject });\r\n });\r\n };\r\n\r\n // init ai model to projectType mapping\r\n initModel2ProjectTypeMapping = () => {\r\n Backend.readAIModel2ProjectModuleMapping().then((response) => {\r\n this.setMountedState({ aiModel2ProjectModuleMappings: response });\r\n });\r\n };\r\n\r\n // set project from viewer, when project opens\r\n initProject = (project) => {\r\n this.setMountedState({ project }, () => {\r\n const projectStructures = project.viewerConfig.project.structures.map(\r\n (structure) => {\r\n let stuct = { ...structure };\r\n if (stuct.parentId === 0) {\r\n stuct.parentId = null;\r\n }\r\n return Structure.fromObject(stuct);\r\n }\r\n );\r\n if (projectStructures) {\r\n this.setMountedState({ projectStructures });\r\n }\r\n });\r\n if (project.viewerConfig.project.toolsInProject.AICockpit) {\r\n this.initAIData();\r\n }\r\n // this.initSocket(project.id); // TODO: fix by changing flask-sock to socketio\r\n };\r\n\r\n initForeignHistory = () => {\r\n if (this.socket) {\r\n this.socket.send(\r\n JSON.stringify({\r\n state: \"init\",\r\n })\r\n );\r\n }\r\n };\r\n\r\n componentDidUpdate = () => {\r\n if (this.persistentStorage && this.state.project) {\r\n const structuresStateList = this.state.structures.map((structure) => {\r\n return {\r\n isUnfolded: structure.isUnfolded,\r\n showSubtypes: structure.showSubtypes,\r\n visible: structure.visible,\r\n };\r\n });\r\n this.persistentStorage.saveProjectTypeValue(\r\n this.state.project.type,\r\n \"structuresStateList\",\r\n structuresStateList\r\n );\r\n }\r\n };\r\n\r\n updateProjectStructures = (structures) => {\r\n const projectStructures = structures.map((structure) => {\r\n return Structure.fromObject(structure);\r\n });\r\n this.setMountedState({ structures, projectStructures });\r\n };\r\n\r\n //remove users, that didn't send updates for 10 seconds\r\n cleanUsersData = () => {\r\n const timeNow = performance.now();\r\n for (const key of Object.keys(this.usersData)) {\r\n if (timeNow - this.usersData[key].updateTime > 10000) {\r\n console.debug(\r\n \"Old user deleted from usersData:\",\r\n this.usersData[key].user\r\n );\r\n delete this.usersData[key];\r\n }\r\n }\r\n };\r\n\r\n receiveSocketMessage = (data) => {\r\n if (data.state) {\r\n if (data.state === \"pos\") {\r\n data.updateTime = performance.now();\r\n this.usersData[data.uuid] = data;\r\n this.cleanUsersData();\r\n } else if (data.state === \"syncStructures\") {\r\n this.syncStructures(data.structures);\r\n } else {\r\n window.projectHistory.receive(data);\r\n }\r\n }\r\n };\r\n\r\n syncStructures = (structures) => {\r\n const { roiLayers } = this.state;\r\n const fileRoiLayers = roiLayers[this.state.fileId];\r\n const newRoiLayers = [];\r\n for (const structure of structures) {\r\n const tempRoiLayer = fileRoiLayers.find(\r\n (roiLayer) => roiLayer.id === structure.id\r\n );\r\n if (tempRoiLayer) {\r\n newRoiLayers.push(tempRoiLayer);\r\n } else {\r\n newRoiLayers.push({\r\n id: structure.id,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n });\r\n }\r\n }\r\n\r\n roiLayers[this.state.fileId] = newRoiLayers;\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({\r\n roiLayers: roiLayers,\r\n });\r\n };\r\n\r\n // set web socket for communication between current viewer/user and server\r\n initSocket = (projectId) => {\r\n this.socket = Backend.getAnnotationSocket(projectId);\r\n window.projectHistory.socket = this.socket;\r\n this.socket.onmessage = (ev) => {\r\n const data = JSON.parse(ev.data);\r\n this.receiveSocketMessage(data);\r\n };\r\n\r\n Backend.getCurrentUser((user) => {\r\n this.setMountedState({ user: user.fullName });\r\n let lastSendObject = null;\r\n\r\n const intervalId = setInterval(() => {\r\n if (\r\n this.socket.readyState === 1 &&\r\n typeof window.getMousePositionInImage === \"function\"\r\n ) {\r\n const p = window.getMousePositionInImage();\r\n let objectToSend = {\r\n state: \"pos\",\r\n projectId: projectId,\r\n user: user.fullName,\r\n x: parseInt(p.x, 10),\r\n y: parseInt(p.y, 10),\r\n };\r\n // send new position, if it has changed\r\n if (\r\n lastSendObject === null ||\r\n lastSendObject.x === objectToSend.x ||\r\n lastSendObject.y === objectToSend.y\r\n ) {\r\n this.socket.send(JSON.stringify(objectToSend));\r\n }\r\n } else {\r\n console.log(\"socket not ready, readyState:\", this.socket.readyState);\r\n if (this.socket.readyState === 3) {\r\n console.log(\"socket broke, stopping interval!\");\r\n clearInterval(intervalId);\r\n }\r\n }\r\n }, 100);\r\n });\r\n };\r\n\r\n /**\r\n * Initializes the Project provider and passes a viewer component\r\n *\r\n * @param {object} viewer - Viewer Component\r\n */\r\n init = (viewer) => {\r\n this.viewer = viewer;\r\n };\r\n\r\n /**\r\n * Updates the roiLayers with the annotations for projectModel\r\n * @param {object} project - projectModel with annotations\r\n */\r\n updateProject = (project) => {\r\n const { roiLayers, fileId, structures } = this.state;\r\n for (const file of project.files) {\r\n for (const structureIdx of file.annotations.map((a) =>\r\n // Caution!: Legacy datastructure: id is Index sometimes!\r\n // See also https://hsa.atlassian.net/wiki/spaces/HSAKIT/pages/16116235173917/Annotations+Data+Structure#Legacy\r\n a.id >= 0\r\n ? // Assigned Id\r\n a.id\r\n : // Save to currently selected structure\r\n project.structures.findIndex((s) => s.id === project.selStructureId)\r\n )) {\r\n const anno = file.annotations[structureIdx];\r\n const structureId = structures[structureIdx].id;\r\n const newRegionRois = createRoisFromAnno(anno, structureId);\r\n if (newRegionRois.length > 0 || fileId === file.id) {\r\n roiLayers[file.id][structureIdx].layer.regionRois = newRegionRois;\r\n roiLayers[file.id][structureIdx].tree.load(\r\n newRegionRois.map((item) => item.treeItem)\r\n );\r\n }\r\n }\r\n }\r\n this.setState({ roiLayers: roiLayers });\r\n };\r\n\r\n setChangingFile = (a) => {\r\n this.setMountedState({ changingFile: a });\r\n };\r\n\r\n setActiveTab = (tab) => {\r\n this.setMountedState({ activeTab: tab });\r\n this.activeTab = tab;\r\n this.forceUpdate();\r\n };\r\n\r\n getActiveTab = () => {\r\n return this.state.activeTab;\r\n };\r\n\r\n /**\r\n * Returns Roi Region Object\r\n *\r\n * @param {int} structureId - id of the structure\r\n * @param {int} fileId - id of the file, if undefined the currently opened file will be used\r\n */\r\n getRegionById = (structureId, fileId) => {\r\n if (!fileId) fileId = this.state.fileId;\r\n return this.state.roiLayers[fileId].find((c) => c.id === structureId);\r\n };\r\n\r\n getNumberOfChilds = (parentStructure) => {\r\n const { structures } = this.state;\r\n\r\n return structures.filter(\r\n (element) => element.parentId === parentStructure.id\r\n ).length;\r\n };\r\n\r\n importStructures = (structures) => {\r\n const { roiLayers } = this.state;\r\n\r\n for (let structure of structures) {\r\n if (structure.tools.length === 0) {\r\n if (structure.parentId > 0) {\r\n let parentStructure = structures.find(\r\n (item) => item.id === structure.parentId\r\n );\r\n if (parentStructure) {\r\n structure.tools = parentStructure.tools;\r\n }\r\n }\r\n }\r\n for (let layerId in roiLayers) {\r\n const roiLayer = roiLayers[layerId].find((c) => c.id === structure.id);\r\n if (!roiLayer) {\r\n roiLayers[layerId].push({\r\n id: structure.id,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n });\r\n }\r\n }\r\n }\r\n\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({ roiLayers });\r\n };\r\n\r\n /**\r\n * Adds a new Dynamic Structure to the Project Model\r\n *\r\n * @param {string} name - Display name of the new structure\r\n */\r\n addStructure = (name, grid = false) => {\r\n const { structures, roiLayers, viewerConfig } = this.state;\r\n\r\n // findHighest id number\r\n const newLayerId = structures.reduce((a, c) => Math.max(a, c.id), 0) + 1;\r\n\r\n let newStructure = {\r\n id: newLayerId,\r\n dynamic: true,\r\n label: name,\r\n color: grid ? \"#00000000\" : getUnusedColor(structures, false),\r\n visible: true,\r\n allToolNames: structures[0].allToolNames,\r\n tools: viewerConfig.project.dynamicStructure.tools,\r\n classFrequencies: {\r\n class_0: 0,\r\n class_1: 0,\r\n class_2: 0,\r\n class_3: 0,\r\n class_4: 0,\r\n class_5: 0,\r\n class_6: 0,\r\n },\r\n avgClassFrequnecy: 0,\r\n isSubtype: false,\r\n isUnfolded: true,\r\n classificationSubtype: false,\r\n parentId: null,\r\n showSubtypes: false,\r\n subtypeLevel: 0,\r\n defaultSelected: false,\r\n };\r\n newStructure = this.viewer.alterStructure(newStructure);\r\n\r\n for (let layerId in roiLayers) {\r\n let newRoilayer = {\r\n id: newLayerId,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n };\r\n roiLayers[layerId].push(newRoilayer);\r\n }\r\n\r\n structures.push(newStructure);\r\n\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({ roiLayers });\r\n };\r\n\r\n // update structure for other users without saving yet\r\n // eslint-disable-next-line no-unused-vars\r\n sendStructures = (structures) => {\r\n // console.log(\"sending structures wip:\", structures);\r\n // const { project } = this.state;\r\n // const toSend = {\r\n // state: \"syncStructures\",\r\n // projectId: project.id,\r\n // structures: structures,\r\n // };\r\n // this.socket.send(JSON.stringify(toSend));\r\n };\r\n\r\n addSubStructure = (parent, name, fromHistoModule) => {\r\n const { structures, roiLayers, selectedLayer } = this.state;\r\n\r\n // findHighest id number\r\n const newLayerId = structures.reduce((a, c) => Math.max(a, c.id), 0) + 1;\r\n\r\n let subStructure = {\r\n id: newLayerId,\r\n dynamic: true,\r\n parentId: parent.id,\r\n label: name ? name : parent.label,\r\n color: getUnusedColor(structures),\r\n visible: true,\r\n allToolNames: parent.allToolNames,\r\n tools: parent.tools, // what tools should be used?\r\n classFrequencies: {\r\n class_0: 0,\r\n class_1: 0,\r\n class_2: 0,\r\n class_3: 0,\r\n class_4: 0,\r\n class_5: 0,\r\n class_6: 0,\r\n },\r\n avgClassFrequnecy: 0,\r\n showSubtypes: false,\r\n isSubtype: true,\r\n parentColor: parent.color,\r\n subtypeColor: getUnusedColor(structures),\r\n isUnfolded: true,\r\n subtypeLevel: parent.subtypeLevel + 1,\r\n hasChild: false,\r\n classificationSubtype: false,\r\n defaultSelected: false,\r\n };\r\n // add substructure as last child (for now just in histo modules / for other modules check if this works too)\r\n let numberChilds = 0;\r\n if (fromHistoModule) {\r\n numberChilds = this.getNumberOfChilds(structures[selectedLayer]);\r\n }\r\n\r\n structures.splice(selectedLayer + 1 + numberChilds, 0, subStructure);\r\n\r\n for (let key in roiLayers) {\r\n const roiIndex = roiLayers[key].findIndex(\r\n (c) => c.id === structures[selectedLayer].id\r\n );\r\n roiLayers[key].splice(roiIndex + 1, 0, {\r\n id: newLayerId,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n });\r\n }\r\n parent.addSubtypeText = \"\";\r\n parent.hasChild = true;\r\n\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({ roiLayers });\r\n };\r\n\r\n addSubType = (parent, name, fromHistoModule) => {\r\n const { structures, roiLayers, selectedLayer } = this.state;\r\n\r\n // findHighest id number\r\n const newLayerId = structures.reduce((a, c) => Math.max(a, c.id), 0) + 1;\r\n\r\n let subStructure = {\r\n id: newLayerId,\r\n dynamic: true,\r\n parentId: parent.id,\r\n label: name ? name : parent.label,\r\n color: getUnusedColor(structures),\r\n visible: true,\r\n allToolNames: parent.allToolNames,\r\n tools: parent.tools, // what tools should be used?\r\n classFrequencies: {\r\n class_0: 0,\r\n class_1: 0,\r\n class_2: 0,\r\n class_3: 0,\r\n class_4: 0,\r\n class_5: 0,\r\n class_6: 0,\r\n },\r\n avgClassFrequnecy: 0,\r\n showSubtypes: false,\r\n isSubtype: true,\r\n isUnfolded: fromHistoModule ? false : true,\r\n subtypeLevel: parent.subtypeLevel + 1,\r\n hasChild: false,\r\n classificationSubtype: true,\r\n defaultSelected: false,\r\n };\r\n // add substructure as last child (for now just in histo modules / for other modules check if this works too)\r\n let numberChilds = 0;\r\n if (fromHistoModule) {\r\n numberChilds = this.getNumberOfChilds(structures[selectedLayer]);\r\n // for point counting module only 11 subtypes are possible because of template\r\n if (numberChilds >= 10) {\r\n window.showWarningSnackbar(\"Reached maximum amount of subtypes.\");\r\n return;\r\n }\r\n }\r\n\r\n structures.splice(selectedLayer + 1 + numberChilds, 0, subStructure);\r\n\r\n for (let key in roiLayers) {\r\n const roiIndex = roiLayers[key].findIndex(\r\n (c) => c.id === structures[selectedLayer].id\r\n );\r\n\r\n roiLayers[key].splice(roiIndex + 1 + numberChilds, 0, {\r\n id: newLayerId,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n });\r\n }\r\n parent.addSubtypeText = \"\";\r\n parent.hasChild = true;\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({ roiLayers });\r\n };\r\n\r\n findChilds = (subType) => {\r\n const { structures } = this.state;\r\n\r\n return structures.filter(\r\n (element) =>\r\n element.subtypeLevel === subType.subtypeLevel + 1 &&\r\n element.parentId === subType.id\r\n );\r\n };\r\n\r\n /**\r\n * Removes a structure and corresponding regions from project model.\r\n *\r\n * @param {object} structure - Structure to remove.\r\n * @returns {Int} The id of the next layer to be selected.\r\n */\r\n deleteStructure = (structure) => {\r\n const { selectedLayer } = this.state;\r\n let { structures, roiLayers } = this.state;\r\n\r\n // Recursively delete all children.\r\n if (structure.hasChild) {\r\n let childs = this.findChilds(structure);\r\n for (let i = 0; i < childs.length; i++) {\r\n this.deleteStructure(childs[i]);\r\n }\r\n }\r\n\r\n let toplevelParentId = null;\r\n // In case of subtypes, find the next (sub-)structure\r\n if (structure.classificationSubtype) {\r\n toplevelParentId =\r\n structures[getParentIndexLayer(structure, structures)].id;\r\n }\r\n // Otherwise, get the direct parent\r\n else {\r\n toplevelParentId = structure.parentId;\r\n }\r\n\r\n // Delete from structure\r\n const structureIndex = structures.findIndex((c) => c.id === structure.id);\r\n structures.splice(structureIndex, 1);\r\n\r\n // Delete from ROIs.\r\n for (let key in roiLayers) {\r\n const roiIndex = roiLayers[key].findIndex((c) => c.id === structure.id);\r\n roiLayers[key].splice(roiIndex, 1);\r\n }\r\n\r\n // In case of subtype, delete ROIs from containing layer.\r\n if (structure.isSubtype) {\r\n for (let key in roiLayers) {\r\n // Get structure where ROIs are stored\r\n let roiIdx = roiLayers[key].findIndex(\r\n (struct) => struct.id === toplevelParentId\r\n );\r\n\r\n // Only keep ROIs not from the deleted subtype\r\n let subtypesRemoved = roiLayers[key][roiIdx].tree\r\n .all()\r\n .filter((treeItem) => {\r\n return (\r\n treeItem.roi.isSubtype &&\r\n treeItem.roi.subtypeName !== structure.label\r\n );\r\n });\r\n\r\n // Overwrite previous ROIs\r\n roiLayers[key][roiIdx].tree.data.children = subtypesRemoved;\r\n }\r\n }\r\n // Update children status of parent.\r\n let parentStruct = structures.find(\r\n (struct) => struct.id === structure.parentId\r\n );\r\n // Only update if there is something to update\r\n if (parentStruct) {\r\n structures = updateStructures(parentStruct, structures);\r\n }\r\n\r\n // if last layer gets deleted make selectedLayer 0\r\n let newSelectedLayer =\r\n selectedLayer >= structures.length ? 0 : selectedLayer;\r\n\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({\r\n roiLayers,\r\n selectedLayer: newSelectedLayer,\r\n });\r\n\r\n return newSelectedLayer;\r\n };\r\n\r\n /**\r\n * Duplicates a structure and corresponding parameters from project model.\r\n *\r\n * @param {object} structure - Structure to remove\r\n */\r\n duplicateStructure = (structure) => {\r\n const { structures, roiLayers } = this.state;\r\n\r\n // findHighest id number\r\n const newLayerId =\r\n structures.reduce((a, c) => (a ? Math.max(a, c.id) : c.id), 0) + 1;\r\n\r\n // clone structure\r\n const pureLabel = structure.label.split(\" - copy\")[0];\r\n const copiesCount = structures.reduce(\r\n (a, c) => (c.label.startsWith(pureLabel + \" - copy\") ? a + 1 : a),\r\n 0\r\n );\r\n let newStructure = Object.assign(JSON.parse(JSON.stringify(structure)), {\r\n id: newLayerId,\r\n label:\r\n copiesCount > 0\r\n ? pureLabel + \" - copy(\" + (copiesCount + 1) + \")\"\r\n : pureLabel + \" - copy\",\r\n });\r\n\r\n structures.push(newStructure);\r\n\r\n for (let layerId in roiLayers) {\r\n let newRoilayer = {\r\n id: newLayerId,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n };\r\n roiLayers[layerId].push(newRoilayer);\r\n }\r\n\r\n this.duplicateChildren(structure, newStructure);\r\n\r\n let newSelectedLayer = structures.findIndex((c) => c.id === newLayerId);\r\n\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({\r\n roiLayers,\r\n selectedLayer: newSelectedLayer,\r\n });\r\n\r\n return newSelectedLayer;\r\n };\r\n\r\n findChildren = (structure) => {\r\n const { structures } = this.state;\r\n\r\n return structures.filter(\r\n (element) =>\r\n element.subtypeLevel === structure.subtypeLevel + 1 &&\r\n element.parentId === structure.id\r\n );\r\n };\r\n\r\n duplicateChildren = (oldParent, newParent) => {\r\n const { structures, roiLayers } = this.state;\r\n\r\n for (let structure of this.findChildren(oldParent)) {\r\n // findHighest id number\r\n const newId =\r\n structures.reduce((a, c) => (a ? Math.max(a, c.id) : c.id)) + 1;\r\n\r\n // clone structure\r\n let newStructure = Object.assign(JSON.parse(JSON.stringify(structure)), {\r\n id: newId,\r\n parentId: newParent.id,\r\n });\r\n\r\n structures.push(newStructure);\r\n for (let layerId in roiLayers) {\r\n let newRoilayer = {\r\n id: newId,\r\n layer: {\r\n regionRois: [],\r\n inverted: false,\r\n },\r\n tree: new RBush(),\r\n };\r\n roiLayers[layerId].push(newRoilayer);\r\n }\r\n\r\n this.duplicateChildren(structure, newStructure);\r\n }\r\n };\r\n\r\n /**\r\n * Checks if a structure can be moved in a direction.\r\n *\r\n * @param {Object} selectedStructure - Structure to move\r\n * @param {int} direction - 1 is up -1 is down\r\n * @returns {bool} Move in this direction possible\r\n */\r\n canMoveStructure = (selectedStructure, direction) => {\r\n const { structures } = this.state;\r\n if (!selectedStructure.dynamic) return false;\r\n\r\n let structuresSameLevel = {\r\n structure: [],\r\n index: [],\r\n };\r\n\r\n // get structures in same level of same parent\r\n structuresSameLevel.structure = structures.filter(\r\n (element) =>\r\n element.parentId === selectedStructure.parentId &&\r\n element.subtypeLevel === selectedStructure.subtypeLevel\r\n );\r\n\r\n // if parent is selected (e.g. Base Roi)\r\n if (!selectedStructure.isSubtype) {\r\n structuresSameLevel.structure = structures.filter(\r\n (element) => element.subtypeLevel === selectedStructure.subtypeLevel\r\n );\r\n }\r\n // get indices in all structures\r\n structuresSameLevel.structure.forEach((element) =>\r\n structuresSameLevel.index.push(\r\n structures.findIndex((structure) => structure === element)\r\n )\r\n );\r\n\r\n // index of selected layer of structures in same level\r\n let index = structuresSameLevel.structure.findIndex(\r\n (structure) => structure === selectedStructure\r\n );\r\n\r\n if (direction > 0) {\r\n // if first object --> move up not possible.\r\n // Also, moving above fixed, non-dynamic structures is forbidden.\r\n if (index === 0 || !structuresSameLevel.structure[index - 1].dynamic) {\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n } else {\r\n // if last object --> move down not possible\r\n if (index === structuresSameLevel.structure.length - 1) {\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Moves a structure up or down in structure list\r\n *\r\n * @param {Object} selectedStructure - Structure to move\r\n * @param {int} direction - 1 is up -1 is down\r\n */\r\n moveStructure = (selectedStructure, direction) => {\r\n const { structures, roiLayers } = this.state;\r\n\r\n let structuresSameLevel = {\r\n structure: [],\r\n index: [],\r\n };\r\n\r\n // get structures in same level of same parent\r\n structuresSameLevel.structure = structures.filter(\r\n (element) =>\r\n element.parentId === selectedStructure.parentId &&\r\n element.subtypeLevel === selectedStructure.subtypeLevel\r\n );\r\n\r\n // if parent is selected (e.g. Base Roi)\r\n if (!selectedStructure.isSubtype) {\r\n structuresSameLevel.structure = structures.filter(\r\n (element) => element.subtypeLevel === selectedStructure.subtypeLevel\r\n );\r\n }\r\n // get indices in all structures\r\n structuresSameLevel.structure.forEach((element) =>\r\n structuresSameLevel.index.push(\r\n structures.findIndex((structure) => structure === element)\r\n )\r\n );\r\n\r\n // index of selected layer of structures in same level\r\n let index = structuresSameLevel.structure.findIndex(\r\n (structure) => structure === selectedStructure\r\n );\r\n\r\n if (direction > 0) {\r\n // if first object --> move up not possible.\r\n // Also, moving above fixed, non-dynamic structures is forbidden.\r\n if (index === 0 || !structuresSameLevel.structure[index - 1].dynamic) {\r\n window.showWarningSnackbar(\"Moving structure up not possible!\");\r\n return;\r\n }\r\n // swap two neighbor structures with subtypes\r\n // get all elements of selected structure\r\n let strt = structuresSameLevel.index[index];\r\n let ed = structuresSameLevel.index[index + 1];\r\n // if structure to move up is last structure\r\n if (!ed) {\r\n // get index first structure in same level\r\n let idxFirstSubtype = structures.findIndex(\r\n (structure) => structure === structuresSameLevel.structure[0]\r\n );\r\n for (let i = idxFirstSubtype; i < structures.length; i++) {\r\n if (structures[i].subtypeLevel < selectedStructure.subtypeLevel) {\r\n ed = i;\r\n break;\r\n }\r\n }\r\n }\r\n // Get all children of the selected structure.\r\n let allElements_1 = structures.slice(strt, ed);\r\n\r\n // delete elements to swap from structures\r\n structures.splice(structuresSameLevel.index[index], allElements_1.length);\r\n\r\n // put elements to right index in structures\r\n let start = structures.findIndex(\r\n (structure) => structure === structuresSameLevel.structure[index - 1]\r\n );\r\n for (let i = allElements_1.length - 1; i >= 0; i--) {\r\n structures.splice(start, 0, allElements_1[i]);\r\n }\r\n } else {\r\n // if last object --> move down not possible\r\n if (index === structuresSameLevel.structure.length - 1) {\r\n window.showWarningSnackbar(\"Moving structure down not possible!\");\r\n return;\r\n }\r\n\r\n // swap two neighbor structures with subtypes\r\n // get all elements of selected structure\r\n let strt = structuresSameLevel.index[index];\r\n let ed = structuresSameLevel.index[index + 1];\r\n let allElements_1 = structures.slice(strt, ed);\r\n\r\n // delete elements of first structure to swap\r\n structures.splice(structuresSameLevel.index[index], allElements_1.length);\r\n\r\n // put elements to right index in structures\r\n let start = structures.findIndex(\r\n (structure) => structure === structuresSameLevel.structure[index + 2]\r\n );\r\n\r\n // if structure to swap is last subtype\r\n let lastStructure = false;\r\n if (start === -1) {\r\n // get index of structure to swap\r\n let idxSwapStructure = structures.findIndex(\r\n (structure) => structure === structuresSameLevel.structure[index + 1]\r\n );\r\n // if it is the last structure of all structures\r\n // search next parent structure\r\n let otherParent = false;\r\n for (let i = idxSwapStructure; i < structures.length; i++) {\r\n if (structures[i].subtypeLevel < selectedStructure.subtypeLevel) {\r\n otherParent = true;\r\n }\r\n }\r\n if (!otherParent) {\r\n lastStructure = true;\r\n } else {\r\n // search next parent structure\r\n for (let i = idxSwapStructure; i < structures.length; i++) {\r\n if (structures[i].subtypeLevel < selectedStructure.subtypeLevel) {\r\n start = i;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!lastStructure) {\r\n // put all elements to index after structure to swap\r\n for (let i = allElements_1.length - 1; i >= 0; i--) {\r\n structures.splice(start, 0, allElements_1[i]);\r\n }\r\n } else {\r\n // if last structure push elements to the end\r\n for (let i = 0; i < allElements_1.length; i++) {\r\n structures.push(allElements_1[i]);\r\n }\r\n }\r\n }\r\n\r\n // Match roiLayer structure to new structure structure.\r\n // Sorts the roilayers for each scene in project by having their ID-order\r\n // match the order set by the structures.\r\n for (let sceneGUID in roiLayers) {\r\n roiLayers[sceneGUID].sort((roi_layer_a, roi_layer_b) => {\r\n // Location of the first roi-Layer Id in strcutures\r\n let index_of_roi_layer_a_in_structures = structures.findIndex(\r\n (element) => {\r\n return element.id === roi_layer_a.id;\r\n }\r\n );\r\n\r\n // Location of the second roi-Layer Id in strcutures\r\n let index_of_roi_layer_b_in_structures = structures.findIndex(\r\n (element) => {\r\n return element.id === roi_layer_b.id;\r\n }\r\n );\r\n\r\n // Check if the first index comes before the second.\r\n // Else, swap per sort algorithm.\r\n return (\r\n index_of_roi_layer_a_in_structures -\r\n index_of_roi_layer_b_in_structures\r\n );\r\n });\r\n }\r\n\r\n let newSelectedLayer = structures.findIndex((c) => c === selectedStructure);\r\n\r\n this.sendStructures(structures);\r\n this.updateProjectStructures(structures);\r\n this.setMountedState({ selectedLayer: newSelectedLayer });\r\n return newSelectedLayer;\r\n };\r\n\r\n getProjectStringInfos = () => {\r\n const project = this.state.project;\r\n const file = project.files.find((file) => file.id === this.state.fileId);\r\n const fileName = file.fileName.split(\".\").slice(0, -1).join(\".\");\r\n let today = new Date();\r\n let dd = String(today.getDate()).padStart(2, \"0\");\r\n let mm = String(today.getMonth() + 1).padStart(2, \"0\"); //January is 0!\r\n let yyyy = today.getFullYear();\r\n today = yyyy + \"-\" + mm + \"-\" + dd;\r\n\r\n // projekt_methode_filename_SceneNr_001.png\r\n return {\r\n name: project.name,\r\n type: project.type,\r\n fileName: fileName,\r\n date: today,\r\n };\r\n };\r\n\r\n setStateNow = (newState) => {\r\n Object.assign(this.state, newState);\r\n this.forceUpdate();\r\n };\r\n\r\n getUserData = () => {\r\n return this.usersData;\r\n };\r\n\r\n setPersistentStorage = (persistentStorage) => {\r\n this.persistentStorage = persistentStorage;\r\n };\r\n\r\n render() {\r\n return (\r\n this.setMountedState(e, callback),\r\n forceUpdate: () => this.forceUpdate(),\r\n getRegionById: this.getRegionById,\r\n setChangingFile: this.setChangingFile,\r\n setActiveTab: this.setActiveTab,\r\n getActiveTab: this.getActiveTab,\r\n /* Handle Structures */\r\n importStructures: this.importStructures,\r\n addStructure: this.addStructure,\r\n addSubStructure: this.addSubStructure,\r\n addSubType: this.addSubType,\r\n sendStructures: this.sendStructures,\r\n deleteStructure: this.deleteStructure,\r\n moveStructure: this.moveStructure,\r\n canMoveStructure: this.canMoveStructure,\r\n duplicateStructure: this.duplicateStructure,\r\n setStateNow: this.setStateNow,\r\n getProjectStringInfos: this.getProjectStringInfos,\r\n updateProject: this.updateProject,\r\n getFileRoiLayers: this.getFileRoiLayers,\r\n /* State */\r\n ...this.state,\r\n fileRoiLayers:\r\n this.state.roiLayers && this.state.roiLayers[this.state.fileId],\r\n }}\r\n >\r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nProjectProvider.propTypes = {\r\n children: PropTypes.element.isRequired,\r\n};\r\n\r\nexport default ProjectProvider;\r\n","//import React from 'react';\r\nimport React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// make a new context\r\nconst TilesContext = React.createContext();\r\n\r\nexport const withTiles = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withTiles(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\n// create provider component\r\nexport class TilesProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {};\r\n\r\n this.visibleImage = [];\r\n this.visibleImageUpdatedAt = [];\r\n this.coloredImages = [];\r\n this.coloredImagesUpdatedAt = [];\r\n this.imgWidth = 0;\r\n this.imgHeight = 0;\r\n this.pageIndex = 0;\r\n this.histogramConfig = null;\r\n this.selectedLayerColor = \"#fff\";\r\n this.selcetedLayerIndex = 0;\r\n this.annotationCount = 0;\r\n this.firstIteration = true;\r\n this.accPoints = [];\r\n this.pointCount = 0;\r\n this.galleryVisible = false;\r\n this.isMousedown = false;\r\n this.isOnImage = false;\r\n this.IsInOtherImage = false;\r\n this.onPageInput = false;\r\n this.strAnnoCount = [];\r\n this.strSubtypesPages = [];\r\n this.structure = null;\r\n this.structureBefore = null;\r\n this.graphAcc = [];\r\n this.roiProps = {\r\n color: \"\",\r\n isSubtype: false,\r\n subtypeName: \"\",\r\n pos: -1,\r\n };\r\n this.histoClassificationStarted = false;\r\n this.fileId = null;\r\n this.zLevel = 0;\r\n this.chainLeaderId = null;\r\n this.transformationMatrix = {};\r\n this.transformationFactor = {};\r\n this.transformationOffset = {};\r\n }\r\n\r\n getIndex = (a) => {\r\n if (this.strAnnoCount) {\r\n for (let i = 0; i < this.strAnnoCount.length; i++) {\r\n if (this.strAnnoCount[i][0] === a) {\r\n return i;\r\n }\r\n }\r\n }\r\n return -1;\r\n };\r\n\r\n getIndexObj = (a) => {\r\n if (this.strSubtypesPages) {\r\n for (let i = 0; i < this.strSubtypesPages.length; i++) {\r\n if (this.strSubtypesPages[i].id === a) {\r\n return i;\r\n }\r\n }\r\n }\r\n return -1;\r\n };\r\n\r\n resetStPg = () => {\r\n if (this.strSubtypesPages) {\r\n for (let i = 0; i < this.strSubtypesPages.length; i++) {\r\n this.strSubtypesPages[i].page = 0;\r\n }\r\n }\r\n };\r\n\r\n render() {\r\n return (\r\n {\r\n this.visibleImage = a;\r\n },\r\n clearTiles: () => {\r\n for (let key of Object.keys(this.visibleImage)) {\r\n this.visibleImage[key] = null;\r\n }\r\n for (let key of Object.keys(this.visibleImage)) {\r\n delete this.visibleImage[key];\r\n }\r\n for (let key of Object.keys(this.coloredImages)) {\r\n this.coloredImages[key] = null;\r\n }\r\n for (let key of Object.keys(this.coloredImages)) {\r\n delete this.coloredImages[key];\r\n }\r\n },\r\n pushVisibleImage: (a, tileId) => {\r\n this.visibleImage[tileId] = a;\r\n this.visibleImageUpdatedAt[tileId] = new Date().getTime();\r\n\r\n // 275 imgs ~ 1GB RAM\r\n if (Object.keys(this.visibleImage).length > 150) {\r\n let sorted = [];\r\n for (let tileId in this.visibleImageUpdatedAt) {\r\n sorted.push([tileId, this.visibleImageUpdatedAt[tileId]]);\r\n }\r\n sorted.sort(function (a, b) {\r\n return a[1] - b[1];\r\n });\r\n\r\n let i = 0;\r\n while (\r\n Object.keys(this.visibleImage).length > 125 &&\r\n i < sorted.length\r\n ) {\r\n if (\r\n sorted &&\r\n sorted[i] &&\r\n this.visibleImage[sorted[i][0]] &&\r\n this.visibleImageUpdatedAt[sorted[i][0]] &&\r\n sorted[i][0] !== \"0,0,0,0\"\r\n ) {\r\n this.visibleImage[sorted[i][0]].onload = null;\r\n this.visibleImage[sorted[i][0]].src = null;\r\n this.visibleImage[sorted[i][0]] = null;\r\n delete this.visibleImage[sorted[i][0]];\r\n delete this.visibleImageUpdatedAt[sorted[i][0]];\r\n } else {\r\n if (this.visibleImageUpdatedAt[sorted[i][0]] === undefined) {\r\n delete this.visibleImageUpdatedAt[sorted[i][0]];\r\n }\r\n }\r\n i++;\r\n }\r\n }\r\n },\r\n resetVisibleImages: () => {\r\n for (let f in this.visibleImage) {\r\n if (f !== \"0,0,0,0\") {\r\n this.visibleImage[f].onload = null;\r\n this.visibleImage[f].src = null;\r\n this.visibleImage[f] = null;\r\n delete this.visibleImage[f];\r\n delete this.visibleImageUpdatedAt[f];\r\n }\r\n }\r\n // this.visibleImage = [];\r\n },\r\n getVisibleImages: () => {\r\n return this.visibleImage;\r\n },\r\n getVisibleImage: (tileId) => {\r\n let img = this.visibleImage[tileId];\r\n if (img !== undefined) {\r\n this.visibleImageUpdatedAt[tileId] = new Date().getTime();\r\n }\r\n return img;\r\n },\r\n\r\n // Colored Images\r\n setColoredImages: (a) => {\r\n this.coloredImages = a;\r\n },\r\n pushColoredImages: (a, tileId) => {\r\n this.coloredImages[tileId] = a;\r\n this.coloredImagesUpdatedAt[tileId] = new Date().getTime();\r\n\r\n // 275 imgs ~ 1GB RAM\r\n if (Object.keys(this.coloredImages).length > 150) {\r\n let sorted = [];\r\n for (let tileId in this.coloredImagesUpdatedAt) {\r\n sorted.push([tileId, this.coloredImagesUpdatedAt[tileId]]);\r\n }\r\n\r\n sorted.sort(function (a, b) {\r\n return a[1] - b[1];\r\n });\r\n\r\n let i = 0;\r\n while (\r\n Object.keys(this.coloredImages).length > 125 &&\r\n i < sorted.length\r\n ) {\r\n if (\r\n sorted &&\r\n sorted[i] &&\r\n this.coloredImages[sorted[i][0]] &&\r\n this.coloredImagesUpdatedAt[sorted[i][0]] &&\r\n sorted[i][0] !== \"0,0,0,0\"\r\n ) {\r\n this.coloredImages[sorted[i][0]].onload = null;\r\n this.coloredImages[sorted[i][0]].src = null;\r\n this.coloredImages[sorted[i][0]] = null;\r\n delete this.coloredImages[sorted[i][0]];\r\n delete this.coloredImagesUpdatedAt[sorted[i][0]];\r\n } else {\r\n if (this.coloredImagesUpdatedAt[sorted[i][0]] === undefined) {\r\n delete this.coloredImagesUpdatedAt[sorted[i][0]];\r\n }\r\n }\r\n i++;\r\n }\r\n }\r\n },\r\n resetColoredImages: () => {\r\n for (let f in this.coloredImages) {\r\n if (this.coloredImages[f] && f !== \"0,0,0,0\") {\r\n this.coloredImages[f].onload = null;\r\n this.coloredImages[f].src = null;\r\n this.coloredImages[f] = null;\r\n delete this.coloredImages[f];\r\n delete this.coloredImagesUpdatedAt[f];\r\n }\r\n }\r\n },\r\n getColoredImages: () => {\r\n return this.coloredImages;\r\n },\r\n getColoredImage: (tileId) => {\r\n let img = this.coloredImages[tileId];\r\n if (img !== undefined) {\r\n this.coloredImagesUpdatedAt[tileId] = new Date().getTime();\r\n }\r\n return img;\r\n },\r\n\r\n setImgWidth: (a) => {\r\n this.imgWidth = a;\r\n },\r\n getImgWidth: () => {\r\n return this.imgWidth;\r\n },\r\n\r\n setImgHeight: (a) => {\r\n this.imgHeight = a;\r\n },\r\n getImgHeight: () => {\r\n return this.imgHeight;\r\n },\r\n\r\n setPageIndex: (a) => {\r\n this.pageIndex = a;\r\n },\r\n getPageIndex: () => {\r\n return this.pageIndex;\r\n },\r\n\r\n setHistogramConfig: (a) => {\r\n this.histogramConfig = a;\r\n },\r\n getHistogramConfig: () => {\r\n return this.histogramConfig;\r\n },\r\n\r\n setSelectedLayerColor: (a) => {\r\n this.selectedLayerColor = a;\r\n },\r\n getSelectedLayerColor: () => {\r\n return this.selectedLayerColor;\r\n },\r\n\r\n setSelectedLayerIndex: (a) => {\r\n this.selectedLayerIndex = a;\r\n },\r\n getSelectedLayerIndex: () => {\r\n return this.selectedLayerIndex;\r\n },\r\n\r\n addAnnotationCount: (x) => {\r\n this.annotationCount = this.annotationCount + x;\r\n },\r\n setAnnotationCount: (x) => {\r\n return (this.annotationCount = x);\r\n },\r\n getAnnotationCount: () => {\r\n return this.annotationCount;\r\n },\r\n\r\n setFirstIteration: (x) => {\r\n this.firstIteration = x;\r\n },\r\n getFirstIteration: () => {\r\n return this.firstIteration;\r\n },\r\n\r\n pushAccPoint: (x) => {\r\n let point = {\r\n x: 30 * this.pointCount,\r\n y: x,\r\n };\r\n this.accPoints.push(point);\r\n this.pointCount = this.pointCount + 1;\r\n },\r\n getAccPoints: () => {\r\n return this.accPoints;\r\n },\r\n\r\n setGalleryVisible: (a) => {\r\n this.galleryVisible = a;\r\n },\r\n getGalleryVisible: () => {\r\n return this.galleryVisible;\r\n },\r\n\r\n setIsMousedown: (a) => {\r\n this.isMousedown = a;\r\n },\r\n getIsMousedown: () => {\r\n return this.isMousedown;\r\n },\r\n\r\n setIsOnImage: (a) => {\r\n this.isOnImage = a;\r\n },\r\n getIsOnImage: () => {\r\n return this.isOnImage;\r\n },\r\n\r\n setIsInOtherImage: (a) => {\r\n this.isInOtherImage = a;\r\n },\r\n getIsInOtherImage: () => {\r\n return this.isInOtherImage;\r\n },\r\n\r\n setRoiProps: (a) => {\r\n this.roiProps.color = a.color;\r\n this.roiProps.isSubtype = a.isSubtype;\r\n this.roiProps.subtypeName = a.subtypeName;\r\n },\r\n getRoiProps: () => {\r\n return this.roiProps;\r\n },\r\n\r\n setPositionRoi: (a) => {\r\n this.roiProps.pos = a;\r\n },\r\n\r\n setOnPageInput: (a) => {\r\n this.onPageInput = a;\r\n },\r\n getOnPageInput: () => {\r\n return this.onPageInput;\r\n },\r\n\r\n pushStrAnnoCount: (a) => {\r\n this.strAnnoCount.push([a, 0]);\r\n },\r\n pushDynamicStructureAC: (a, b) => {\r\n this.strAnnoCount.splice(b, 0, [a, 0]);\r\n },\r\n setStrAnnoCount: (a, b) => {\r\n let idx = this.getIndex(a);\r\n if (this.strAnnoCount[idx]) {\r\n this.strAnnoCount[idx][1] = this.strAnnoCount[idx][1] + b;\r\n }\r\n },\r\n setParentAnnoCount: (a, b) => {\r\n let idx = this.getIndex(a);\r\n if (this.strAnnoCount[idx]) {\r\n this.strAnnoCount[idx][1] = this.strAnnoCount[idx][1] + b;\r\n }\r\n },\r\n getStrAnnoCountElement: (a) => {\r\n let idx = this.getIndex(a);\r\n return this.strAnnoCount[idx][1];\r\n },\r\n getStrAnnoCount: () => {\r\n return this.strAnnoCount;\r\n },\r\n setAnnoCount: (a) => {\r\n this.strAnnoCount = a;\r\n },\r\n changeAnnoCount: (a, b) => {\r\n let idx_a = this.getIndex(a);\r\n let idx_b = this.getIndex(b);\r\n if (this.strAnnoCount[idx_a] && this.strAnnoCount[idx_b]) {\r\n this.strAnnoCount[idx_a][1] = this.strAnnoCount[idx_a][1] + 1;\r\n this.strAnnoCount[idx_b][1] = this.strAnnoCount[idx_b][1] - 1;\r\n }\r\n },\r\n\r\n pushSubtypesPages: (a, b) => {\r\n let obj = {\r\n name: a,\r\n page: 0,\r\n tilePage: 0,\r\n subtypes: [],\r\n id: b,\r\n };\r\n this.strSubtypesPages.push(obj);\r\n },\r\n pushDynamicStructureSP: (a, b) => {\r\n let obj = {\r\n name: a.label,\r\n page: 0,\r\n tilePage: 0,\r\n subtypes: [],\r\n id: a.id,\r\n };\r\n this.strSubtypesPages.splice(b, 0, obj);\r\n },\r\n getSubtypesPages: () => {\r\n return this.strSubtypesPages;\r\n },\r\n setSubtypesPages: (a) => {\r\n this.strSubtypesPages = a;\r\n },\r\n setPage: (a, b) => {\r\n let idx = this.getIndexObj(a);\r\n this.strSubtypesPages[idx].page = b;\r\n },\r\n getPage: (a) => {\r\n let idx = this.getIndexObj(a);\r\n if (this.strSubtypesPages[idx]) {\r\n return this.strSubtypesPages[idx].page;\r\n } else {\r\n return 0;\r\n }\r\n },\r\n setTilePage: (a, b) => {\r\n let idx = this.getIndexObj(a);\r\n this.strSubtypesPages[idx].tilePage = b;\r\n },\r\n getTilePage: (a) => {\r\n let idx = this.getIndexObj(a);\r\n return this.strSubtypesPages[idx].tilePage;\r\n },\r\n setSubtypes: (a, b) => {\r\n let idx = this.getIndexObj(a);\r\n this.strSubtypesPages[idx].subtypes = b;\r\n },\r\n setSingleSubtype: (a, b, c) => {\r\n let idx = this.getIndexObj(a);\r\n this.strSubtypesPages[idx].subtypes[c] = b;\r\n },\r\n getSubtypes: (a) => {\r\n let idx = this.getIndexObj(a);\r\n return this.strSubtypesPages[idx].subtypes;\r\n },\r\n resetSubtypesPages: () => {\r\n this.resetStPg();\r\n //this.strSubtypesPages = [];\r\n },\r\n\r\n setStructure: (a) => {\r\n this.structureBefore = this.structure;\r\n this.structure = a;\r\n },\r\n getStructure: () => {\r\n return this.structure;\r\n },\r\n getStructureBefore: () => {\r\n return this.structureBefore;\r\n },\r\n\r\n setGraphAcc: (a) => {\r\n this.graphAcc = a;\r\n },\r\n pushGraphAcc: (a) => {\r\n this.graphAcc.push(a);\r\n },\r\n getGraphAcc: () => {\r\n return this.graphAcc;\r\n },\r\n\r\n setHistoClassificationStarted: (a) => {\r\n this.histoClassificationStarted = a;\r\n },\r\n getHistoClassificationStarted: () => {\r\n return this.histoClassificationStarted;\r\n },\r\n\r\n setFileId: (a) => {\r\n this.fileId = a;\r\n },\r\n getFileId: () => {\r\n return this.fileId;\r\n },\r\n\r\n setZLevel: (a) => {\r\n this.zLevel = a;\r\n },\r\n getZLevel: () => {\r\n return this.zLevel;\r\n },\r\n setTransformationMatnFactnOff: (a, fileId, fact, Off) => {\r\n this.transformationMatrix[fileId] = a;\r\n this.transformationFactor[fileId] = fact;\r\n this.transformationOffset[fileId] = Off;\r\n },\r\n getTransformationMatrix: (fileId) => {\r\n return this.transformationMatrix[fileId];\r\n },\r\n getTransformationFactor: (fileId) => {\r\n return this.transformationFactor[fileId];\r\n },\r\n getTransformationOffset: (fileId) => {\r\n return this.transformationOffset[fileId];\r\n },\r\n removeTransformationMatrix: (fileId) => {\r\n delete this.transformationMatrix[fileId];\r\n delete this.transformationFactor[fileId];\r\n delete this.transformationOffset[fileId];\r\n },\r\n resetAllTransformationMatnFact: () => {\r\n this.transformationMatrix = {};\r\n this.transformationFactor = {};\r\n this.transformationOffset = {};\r\n },\r\n getAllTransformationMatrices: () => {\r\n return this.transformationMatrix;\r\n },\r\n getAllTransformationFactors: () => {\r\n return this.transformationFactor;\r\n },\r\n getAllTransformationOffsets: () => {\r\n return this.transformationOffset;\r\n },\r\n }}\r\n >\r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nTilesProvider.propTypes = {\r\n children: PropTypes.element.isRequired,\r\n};\r\n\r\nexport default TilesContext;\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nconst SpectraViewerContext = React.createContext();\r\n\r\n/**\r\n * Allow other classes to use the SpectraViewer context with withSpectraViewer().\r\n * @param {*} Component The class using the context.\r\n * @returns The Component wrapped inside the SpectraViewer.\r\n */\r\nexport const withSpectraViewer = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withSpectraViewer(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\nclass SpectraViewerProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n selectedSpectrum: 0,\r\n areas: [],\r\n operationSets: [[[\"scores\", 1]]],\r\n maxScores: 0,\r\n useSavedCalcs: true,\r\n rawSpectra: [], // Permanently save spectra in frontend once loaded\r\n rawSpectraLoaded: false,\r\n pcas: [], // Permanently save pcas in frontend once loaded, only cahnge on update\r\n pcaOrder: \"asc\", // The order in which the PCAs are sorted\r\n selectedPca: null,\r\n selectedPcaId: null,\r\n focusedPca: {\r\n info: null,\r\n scores: null,\r\n approximations: null,\r\n }, // The pca which is currently being focused in analysis. Includes spectra both before and after trimming and preprocessing.\r\n analysisResults: [], // Permanently save results of analysis with focussed pca, only change on update\r\n analysisResultsLoaded: false,\r\n selectedPcaScore: 0,\r\n selectedProcessedSpectrum: 0,\r\n currentlyShownData: null,\r\n ratedSpectra: [],\r\n models: [], // AI Models provided\r\n selectedModelIdx: null,\r\n selectedModelName: null,\r\n passingCriteria: [],\r\n passingCriteria_idx: null,\r\n passingCriteria_min: 0.99,\r\n passingCriteria_max: 1.0,\r\n spectraPredictionSettings: [], // Format: {substance: \"\", concentration: 0.0}\r\n };\r\n }\r\n\r\n /**\r\n * Allows to set state of context from outside the class\r\n * @param {*} object Stateobject to be set.\r\n * @param {function} callback Function to be called after state has been updated.\r\n */\r\n setContextState = (object, callback) => {\r\n this.setState(object, callback);\r\n };\r\n\r\n /**\r\n * Saves all areas to state. Also assigns each sub-area a reference.\r\n * @param {array} areas\r\n */\r\n updateAreas = (areas) => {\r\n this.setState({\r\n areas: areas.map((area) => {\r\n area.refs = [React.createRef(), React.createRef()];\r\n return area;\r\n }),\r\n });\r\n };\r\n\r\n /**\r\n * Toggles the status of useSavedCalcs on or off.\r\n */\r\n toggleSavedCalcs = () => {\r\n this.setState({\r\n useSavedCalcs: !this.state.useSavedCalcs,\r\n });\r\n };\r\n\r\n /**\r\n * Ensure that not too many scores can be chosen.\r\n * Should no spectra be visible, all are used for pca.\r\n */\r\n setMaxScores = () => {\r\n let availableSamples = 0;\r\n availableSamples = this.state.rawSpectra.filter((el) => el.checked).length;\r\n this.setState({\r\n maxScores:\r\n availableSamples === 0\r\n ? this.state.rawSpectra.length - 1\r\n : availableSamples - 1,\r\n });\r\n };\r\n\r\n /**\r\n * Sort the pcas by a value from the result in ascending or descending order\r\n * @param {string} valueToSortBy The key used to sort the pcas\r\n * @param {string} order \"asc\" or \"desc\" for ascending or descending order respectively\r\n */\r\n sortPCAs = (valueToSortBy, order = \"desc\") => {\r\n // Sort PCAs in descending order by R² value\r\n let temp_pcas = this.state.pcas.sort((a, b) => {\r\n return b.result[valueToSortBy] - a.result[valueToSortBy];\r\n });\r\n // Invert array if decending order is wanted\r\n if (order === \"asc\") {\r\n temp_pcas.reverse();\r\n }\r\n // replace with sorted PCAs\r\n this.setState({ pcas: temp_pcas, pcaOrder: order });\r\n };\r\n\r\n render() {\r\n return (\r\n \r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nSpectraViewerProvider.propTypes = {\r\n children: PropTypes.element,\r\n};\r\n\r\nexport default SpectraViewerProvider;\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nconst ResultTabContext = React.createContext();\r\n\r\nexport const withResultTab = (Component) => {\r\n const WrappedComponent = ({ ...propsWithoutClasses }) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withResultTab(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\n// this is the main component, it has to be added at the root of the app.\r\n// all components that use withResultTab(...) will have access to it via this.props.resultTab...\r\nclass ResultTabProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.selectedRoi = 0;\r\n this.selectedChildIndex = 1;\r\n this.selectedStructure = 0;\r\n this.changeFile = false;\r\n this.hundredTiles = false;\r\n this.rendererInitialized = false;\r\n this.rendererCanvas = null;\r\n this.rendererCtx = null;\r\n this.zoomLevelFixed = false;\r\n this.gridExists = false;\r\n this.resetPressed = false;\r\n this.selSampleSet = false;\r\n this.fileChange = false;\r\n }\r\n\r\n getSelectedRoi() {\r\n return this.selectedRoi;\r\n }\r\n\r\n setSelectedRoi(a) {\r\n this.selectedRoi = a;\r\n }\r\n\r\n getSelectedChildIndex() {\r\n return this.selectedChildIndex;\r\n }\r\n\r\n setSelectedChildIndex(a) {\r\n this.selectedChildIndex = a;\r\n }\r\n\r\n getSelectedStructure() {\r\n return this.selectedStructure;\r\n }\r\n\r\n setSelectedStructure(a) {\r\n this.selectedStructure = a;\r\n }\r\n\r\n getChangeFile() {\r\n return this.changeFile;\r\n }\r\n\r\n setChangeFile(a) {\r\n this.changeFile = a;\r\n }\r\n\r\n getHundredTiles() {\r\n return this.hundredTiles;\r\n }\r\n\r\n setHundredTiles(a) {\r\n this.hundredTiles = a;\r\n }\r\n\r\n getRendererInitialized() {\r\n return this.rendererInitialized;\r\n }\r\n\r\n setRendererInitialized(a) {\r\n this.rendererInitialized = a;\r\n }\r\n\r\n getRendererCanvas() {\r\n return this.rendererCanvas;\r\n }\r\n\r\n setRendererCanvas(a) {\r\n this.rendererCanvas = a;\r\n }\r\n\r\n getRendererCtx() {\r\n return this.rendererCtx;\r\n }\r\n\r\n setRendererCtx(a) {\r\n this.rendererCtx = a;\r\n }\r\n\r\n // returns position of our image\r\n getPosition = () => {\r\n return {\r\n x: -this.rendererCtx.getTransform().e,\r\n y: -this.rendererCtx.getTransform().f,\r\n };\r\n };\r\n\r\n // returns the current zoom scale\r\n getScale = () => {\r\n return this.rendererCtx ? this.rendererCtx.getTransform().a : 1;\r\n };\r\n\r\n /**\r\n * Is the current zoom level be fixed?\r\n * @returns {bool} Is the current zoom level fixed?\r\n */\r\n getZoomLevelFixed() {\r\n return this.zoomLevelFixed;\r\n }\r\n\r\n /**\r\n * Toggle the state of zoomLevelFixed.\r\n */\r\n toggleZoomLevelFixed() {\r\n this.zoomLevelFixed = !this.zoomLevelFixed;\r\n }\r\n\r\n /**\r\n * Set the attribute zoomLevelFixed to true or false.\r\n * @param {bool} value Should the zoom be fixed?\r\n */\r\n setZoomLevelFixed(value) {\r\n this.zoomLevelFixed = value;\r\n }\r\n\r\n getGridExists() {\r\n return this.gridExists;\r\n }\r\n\r\n setGridExists(a) {\r\n this.gridExists = a;\r\n }\r\n\r\n getResetPressed() {\r\n return this.resetPressed;\r\n }\r\n\r\n setResetPressed(a) {\r\n this.resetPressed = a;\r\n }\r\n\r\n getSelSampleSet() {\r\n return this.selSampleSet;\r\n }\r\n\r\n setSelSampleSet(a) {\r\n this.selSampleSet = a;\r\n }\r\n\r\n getFileChange() {\r\n return this.fileChange;\r\n }\r\n\r\n setFileChange(a) {\r\n this.fileChange = a;\r\n }\r\n\r\n render() {\r\n return (\r\n this.getSelectedRoi(),\r\n setSelectedRoi: (a) => this.setSelectedRoi(a),\r\n getSelectedChildIndex: () => this.getSelectedChildIndex(),\r\n setSelectedChildIndex: (a) => this.setSelectedChildIndex(a),\r\n getSelectedStructure: () => this.getSelectedStructure(),\r\n setSelectedStructure: (a) => this.setSelectedStructure(a),\r\n getChangeFile: () => this.getChangeFile(),\r\n setChangeFile: (a) => this.setChangeFile(a),\r\n getHundredTiles: () => this.getHundredTiles(),\r\n setHundredTiles: (a) => this.setHundredTiles(a),\r\n getRendererInitialized: () => this.getRendererInitialized(),\r\n setRendererInitialized: (a) => this.setRendererInitialized(a),\r\n getRendererCanvas: () => this.getRendererCanvas(),\r\n setRendererCanvas: (a) => this.setRendererCanvas(a),\r\n getRendererCtx: () => this.getRendererCtx(),\r\n setRendererCtx: (a) => this.setRendererCtx(a),\r\n getPosition: () => this.getPosition(),\r\n getScale: () => this.getScale(),\r\n getZoomLevelFixed: () => this.getZoomLevelFixed(),\r\n toggleZoomLevelFixed: () => this.toggleZoomLevelFixed(),\r\n setZoomLevelFixed: (a) => this.setZoomLevelFixed(a),\r\n getGridExists: () => this.getGridExists(),\r\n setGridExists: (a) => this.setGridExists(a),\r\n getResetPressed: () => this.getResetPressed(),\r\n setResetPressed: (a) => this.setResetPressed(a),\r\n getSelSampleSet: () => this.getSelSampleSet(),\r\n setSelSampleSet: (a) => this.setSelSampleSet(a),\r\n getFileChange: () => this.getFileChange(),\r\n setFileChange: (a) => this.setFileChange(a),\r\n }}\r\n >\r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nResultTabProvider.propTypes = {\r\n children: PropTypes.element.isRequired,\r\n};\r\n\r\nexport default ResultTabProvider;\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nimport { withSpinloader } from \"../../common/components/Spinloader\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport Backend from \"../../common/utils/Backend\";\r\n\r\nconst ScanViewerContext = React.createContext();\r\n\r\nexport const withScanViewerContext = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withScanViewerContext(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\n/**\r\n * handles the communication with backend.\r\n * this is the main component, it has to be added at the root of the app.\r\n * all components that use withPersistentStorage(...) will have access to it via this.props.persistentStorage...\r\n */\r\nclass ScanViewerProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n this._isMounted = false;\r\n this.state = {\r\n mapVisible: true,\r\n cameraVisible: false,\r\n gridVisible: true,\r\n debugDataVisible: false,\r\n commentsVisible: true,\r\n automationVisible: true,\r\n automatedMicroscopeStatus: \"notConnected\",\r\n focusPeakingOn: true,\r\n sideBarContent: \"fluorescence\",\r\n streamReady: false,\r\n slideScanning: false,\r\n activeTab: 0,\r\n filePath: \"\",\r\n commentCount: 0,\r\n w: 400,\r\n h: 400,\r\n fluorescenceChannels: \"\",\r\n selectedChannel: \"\",\r\n cameraMinFramerate: 0,\r\n cameraMaxFramerate: 30,\r\n cameraMinExposureTime: 30,\r\n cameraMaxExposureTime: 99999,\r\n cameraMinGain: 0.1,\r\n cameraMaxGain: 12.0,\r\n cameraMinGamma: 0.0,\r\n cameraMaxGamma: 3.95,\r\n cameraMinBlackValue: 0.0,\r\n cameraMaxBlackValue: 31.9,\r\n pixelSizeCamera: 3.45,\r\n cameraColorMin: 0,\r\n cameraColorMax: 15.99,\r\n importFilePath: \"\",\r\n };\r\n this.lenseType = null;\r\n this.adapterType = null;\r\n\r\n this.channels = [];\r\n this.io = Backend.getPythonServerSocket();\r\n this.io.on(\"connect\", () => {\r\n this.io.emit(\"scan_connect\", \"\");\r\n });\r\n\r\n this.io.on(\"scan_message\", (message_content) => {\r\n const data = JSON.parse(message_content);\r\n if (data.state) {\r\n if (data.state === \"stream_ready\") {\r\n this.setState({ streamReady: true });\r\n } else if (data.state === \"stitching_start\") {\r\n props.spinloader.show();\r\n } else if (data.state === \"stitching\") {\r\n props.spinloader.showWithProgress({\r\n message: \"Progress\",\r\n progress: data.progress,\r\n });\r\n } else if (data.state === \"stitching_end\") {\r\n props.spinloader.hide();\r\n } else if (data.state === \"camera_error\") {\r\n window.openResponseDialog(\r\n \"Camera could not be found. Retry?\",\r\n (response) => {\r\n if (!response) {\r\n this.props.history.push(\"/\");\r\n }\r\n }\r\n );\r\n } else if (data.state === \"saving_error\") {\r\n props.spinloader.hide();\r\n window.openWarningDialog(\r\n \"Number of channels not equal. Please save in separate file.\"\r\n );\r\n } else if (data.state === \"cameraParameters\") {\r\n this.setState({\r\n cameraMinFramerate: data.cameraMinFramerate,\r\n cameraMaxFramerate: data.cameraMaxFramerate,\r\n cameraMinExposureTime: data.cameraMinExposureTime,\r\n cameraMaxExposureTime: data.cameraMaxExposureTime,\r\n cameraMinGain: data.cameraMinGain,\r\n cameraMaxGain: data.cameraMaxGain,\r\n cameraMinGamma: data.cameraMinGamma,\r\n cameraMaxGamma: data.cameraMaxGamma,\r\n cameraMinBlackValue: data.cameraMinBlackValue,\r\n cameraMaxBlackValue: data.cameraMaxBlackValue,\r\n pixelSizeCamera: data.pixelSizeCamera,\r\n });\r\n } else if (data.state === \"automatedMicroscope\") {\r\n if (data.status) {\r\n this.setState({ automatedMicroscopeStatus: data.status });\r\n }\r\n } else if (data.state === \"toggle_state\") {\r\n // if (data.paused) {\r\n this.setMountedState({\r\n slideScanning: !data.paused,\r\n cameraVisible: data.cameraVisible,\r\n gridVisible: data.gridVisible,\r\n });\r\n // }\r\n }\r\n }\r\n });\r\n }\r\n\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n componentDidMount() {\r\n this._isMounted = true;\r\n window.addEventListener(\"beforeunload\", this.exitScanner);\r\n const cameraVisibleValue =\r\n localStorage.getItem(\"scanCameraVisible\") === \"undefined\"\r\n ? false\r\n : localStorage.getItem(\"scanCameraVisible\") === \"true\"\r\n ? true\r\n : false;\r\n const mapVisibleValue =\r\n localStorage.getItem(\"scanMapVisible\") === \"undefined\"\r\n ? true\r\n : localStorage.getItem(\"scanMapVisible\") === \"true\"\r\n ? true\r\n : false;\r\n const gridVisibleValue =\r\n localStorage.getItem(\"scanGridVisible\") === \"undefined\"\r\n ? true\r\n : localStorage.getItem(\"scanGridVisible\") === \"true\"\r\n ? true\r\n : false;\r\n const debugDataVisibleValue =\r\n localStorage.getItem(\"scanDebugDataVisible\") === \"undefined\"\r\n ? false\r\n : localStorage.getItem(\"scanDebugDataVisible\") === \"true\"\r\n ? true\r\n : false;\r\n const commentsVisibleValue =\r\n localStorage.getItem(\"scanCommentsVisible\") === \"undefined\"\r\n ? true\r\n : localStorage.getItem(\"scanCommentsVisible\") === \"true\"\r\n ? true\r\n : false;\r\n const automationVisibleValue =\r\n localStorage.getItem(\"automationVisibleValue\") === \"undefined\"\r\n ? true\r\n : localStorage.getItem(\"automationVisibleValue\") === \"true\"\r\n ? true\r\n : false;\r\n const focusPeakingOnValue =\r\n localStorage.getItem(\"focusPeakingOnValue\") === \"undefined\"\r\n ? true\r\n : localStorage.getItem(\"focusPeakingOnValue\") === \"true\"\r\n ? true\r\n : false;\r\n const sideBarContentValue = localStorage.getItem(\"scanSideBarContent\");\r\n this.setState({\r\n cameraVisible: cameraVisibleValue,\r\n mapVisible: mapVisibleValue,\r\n gridVisible: gridVisibleValue,\r\n debugDataVisible: debugDataVisibleValue,\r\n commentsVisible: commentsVisibleValue,\r\n sideBarContent: sideBarContentValue,\r\n automationVisible: automationVisibleValue,\r\n focusPeakingOn: focusPeakingOnValue,\r\n });\r\n }\r\n\r\n componentWillUnmount() {\r\n this.exitScanner();\r\n window.removeEventListener(\"beforeunload\", this.exitScanner);\r\n this._isMounted = false;\r\n }\r\n\r\n setLenseType = (lenseType) => {\r\n this.lenseType = lenseType;\r\n console.log(\"this.lenseType\", this.lenseType);\r\n };\r\n\r\n setAdapterType = (adapterType) => {\r\n this.adapterType = adapterType;\r\n console.log(\"this.adapterType\", this.adapterType);\r\n };\r\n\r\n changeScanState = (scanState) => {\r\n if (scanState === \"scan_save\") {\r\n this.changeTab(0);\r\n }\r\n if (this.io) {\r\n this.send({ state: scanState });\r\n this.setMountedState({ slideScanning: scanState === \"scan_start\" });\r\n if (scanState === \"scan_start\") {\r\n this.setState({ commentCount: 5 });\r\n } else if (scanState === \"scan_pause\") {\r\n this.setState({ commentCount: 6 });\r\n } else if (scanState === \"scan_reset\") {\r\n this.setState({ commentCount: 0 });\r\n this.channels = [];\r\n }\r\n }\r\n };\r\n\r\n send = (objectToSend) => {\r\n if (this.io?.connected) {\r\n this.io.emit(\"scan_message\", JSON.stringify(objectToSend));\r\n }\r\n };\r\n\r\n setScanRendererSize = (w, h) => {\r\n this.setState({ w: w });\r\n this.setState({ h: h });\r\n this.send({\r\n state: \"renderSize\",\r\n w: w,\r\n h: h,\r\n });\r\n };\r\n\r\n changeMicroscopeParams = (paramJson) => {\r\n paramJson.state = \"microscope_params\";\r\n this.send(paramJson);\r\n };\r\n\r\n changeImportParams = (param) => {\r\n let data = param[\"data\"];\r\n switch (param[\"action\"]) {\r\n case \"filepath\":\r\n this.setState({ importFilePath: data });\r\n break;\r\n }\r\n };\r\n\r\n moveCenter = (dx, dy) => {\r\n this.send({\r\n state: \"scan_translate\",\r\n dx: dx,\r\n dy: dy,\r\n });\r\n };\r\n\r\n sendMinimapClickPosition = (x, y) => {\r\n this.send({\r\n state: \"minimap_click\",\r\n x: x,\r\n y: y,\r\n });\r\n };\r\n\r\n sendFilePath = (filePath) => {\r\n this.setState({ filePath: filePath });\r\n this.send({\r\n state: \"file_name_change\",\r\n filePath: filePath,\r\n });\r\n };\r\n\r\n changeTab = (tabIdx) => {\r\n this.setMountedState({ activeTab: tabIdx });\r\n };\r\n\r\n exportWIP = () => {\r\n this.send({\r\n state: \"export_wip\",\r\n filePath: \"\",\r\n channels: this.channels,\r\n });\r\n this.channels = [];\r\n };\r\n\r\n importWIP = () => {\r\n this.send({\r\n state: \"import_wip\",\r\n filepath: this.state.importFilePath,\r\n });\r\n };\r\n\r\n createWSI = () => {\r\n const objectToSend = {\r\n state: \"scan_save\",\r\n filePath: this.state.filePath,\r\n channels: this.channels,\r\n lenseType: this.lenseType,\r\n adapterType: this.adapterType,\r\n };\r\n this.send(objectToSend);\r\n this.channels = [];\r\n };\r\n\r\n setWhiteBalanceState = (value) => {\r\n this.send({\r\n state: \"whiteBalance\",\r\n value: value,\r\n });\r\n };\r\n\r\n setVignetteState = (value) => {\r\n this.send({\r\n state: \"vignette\",\r\n value: value,\r\n });\r\n };\r\n\r\n setFeaturePointsState = (checked, numFeaturePoints) => {\r\n this.send({\r\n state: \"featurePoint\",\r\n checked: checked,\r\n numFeaturePoints: numFeaturePoints,\r\n });\r\n };\r\n\r\n toggleCamera = () => {\r\n const value = !this.state.cameraVisible;\r\n this.send({\r\n state: \"toggle\",\r\n target: \"camera\",\r\n value: value,\r\n });\r\n this.setMountedState({ cameraVisible: value });\r\n localStorage.setItem(\"scanCameraVisible\", value.toString());\r\n };\r\n\r\n toggleMinimap = () => {\r\n const value = !this.state.mapVisible;\r\n this.setMountedState({ mapVisible: value });\r\n localStorage.setItem(\"scanMapVisible\", value.toString());\r\n };\r\n\r\n toggleGrid = () => {\r\n const value = !this.state.gridVisible;\r\n this.send({\r\n state: \"toggle\",\r\n target: \"grid\",\r\n value: value,\r\n });\r\n this.setMountedState({ gridVisible: value });\r\n localStorage.setItem(\"scanGridVisible\", value.toString());\r\n };\r\n\r\n toggleDebugData = () => {\r\n const value = !this.state.debugDataVisible;\r\n this.setMountedState({ debugDataVisible: value });\r\n localStorage.setItem(\"scanDebugDataVisible\", value.toString());\r\n };\r\n\r\n toggleComments = () => {\r\n const value = !this.state.commentsVisible;\r\n this.setMountedState({ commentsVisible: value });\r\n localStorage.setItem(\"scanCommentsVisible\", value.toString());\r\n };\r\n\r\n toggleFluorescence = () => {\r\n let value = \"\";\r\n if (this.state.sideBarContent === \"fluorescence\") {\r\n this.setMountedState({ sideBarContent: \"microscopeSettings\" });\r\n value = \"microscopeSettings\";\r\n } else {\r\n this.setMountedState({ sideBarContent: \"fluorescence\" });\r\n value = \"fluorescence\";\r\n }\r\n localStorage.setItem(\"scanSideBarContent\", value);\r\n };\r\n\r\n updateFluorescenceParams = (paramJson) => {\r\n this.send(paramJson);\r\n };\r\n\r\n toggleAutomation = () => {\r\n const value = !this.state.automationVisible;\r\n this.setMountedState({ automationVisible: value });\r\n localStorage.setItem(\"automationVisibleValue\", value.toString());\r\n };\r\n\r\n toggleFocusPeaking = () => {\r\n if (\r\n this.state.cameraVisible == false &&\r\n this.state.focusPeakingOn == false\r\n ) {\r\n this.toggleCamera();\r\n }\r\n const value = !this.state.focusPeakingOn;\r\n this.send({\r\n state: \"toggle\",\r\n target: \"focusPeaking\",\r\n value: value,\r\n });\r\n this.setMountedState({ focusPeakingOn: value });\r\n localStorage.setItem(\"focusPeakingOnValue\", value.toString());\r\n };\r\n\r\n deleteScanArea = (deleteArea) => {\r\n console.log(\"deleteScanArea() called\", deleteArea);\r\n this.send({\r\n state: \"delete_area\",\r\n x1: deleteArea.p1.centeredX,\r\n y1: deleteArea.p1.centeredY,\r\n x2: deleteArea.p2.centeredX,\r\n y2: deleteArea.p2.centeredY,\r\n });\r\n };\r\n\r\n zoomIn = () => {\r\n this.send({\r\n state: \"zoom_in\",\r\n });\r\n };\r\n\r\n zoomOut = () => {\r\n this.send({\r\n state: \"zoom_out\",\r\n });\r\n };\r\n\r\n zoomReset = () => {\r\n this.send({\r\n state: \"zoom_reset\",\r\n });\r\n };\r\n\r\n exitScanner = () => {\r\n this.send({\r\n state: \"exit_scanner\",\r\n });\r\n this.io.disconnect();\r\n };\r\n\r\n useAutomatedMicroscope = (command, data) => {\r\n this.send({\r\n state: \"useAutomatedMicroscope\",\r\n command: command,\r\n data: data,\r\n });\r\n };\r\n\r\n render() {\r\n return (\r\n \r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nScanViewerProvider.propTypes = {\r\n children: PropTypes.element.isRequired,\r\n spinloader: PropTypes.object,\r\n history: PropTypes.object,\r\n};\r\n\r\nexport default withRouter(withSpinloader(ScanViewerProvider));\r\n","// Framework imports\r\nimport React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nclass CustomSvgIcon extends React.Component {\r\n render() {\r\n const { name, width, height, stroke, vertAlign } = this.props;\r\n switch (name) {\r\n case \"GrabCutIcon\":\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n case \"SAMIcon\":\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n case \"ResultsIcon\":\r\n return (\r\n \r\n \r\n \r\n );\r\n case \"HeatmapIcon\":\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n case \"ResetZoomIcon\":\r\n return (\r\n \r\n \r\n \r\n \r\n );\r\n case \"InferenceIcon\":\r\n return (\r\n \r\n \r\n \r\n );\r\n case \"AILearningIcon\":\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n }\r\n }\r\n}\r\n\r\nCustomSvgIcon.propTypes = {\r\n name: PropTypes.string,\r\n width: PropTypes.number,\r\n height: PropTypes.number,\r\n stroke: PropTypes.string,\r\n vertAlign: PropTypes.string,\r\n};\r\n\r\nexport default CustomSvgIcon;\r\n","// AIContext.jsx\r\n// Contains all variables for the AI Viewer page that need to be accessible throughout its entirety.\r\n\r\n// Copyright HS Analysis GmbH, 2024\r\n// Author: Viktor Eberhardt\r\n\r\n// Framework imports\r\nimport React from \"react\";\r\nimport { PropTypes } from \"prop-types\";\r\n\r\n// HSA imports\r\nimport AITrainingDataContainer from \"../common/components/AITrainingDataContainer\";\r\nimport AIModel2ProjectTypeMapping from \"./components/AIModel2ProjectTypeMapping\";\r\nimport Backend from \"../common/utils/Backend\";\r\nimport Structure from \"../common/components/Structure\";\r\nimport { ImageInferenceParameters } from \"../common/components/IAMConfig\";\r\nimport { TargetDataFormat } from \"../common/components/AITrainingSettings\";\r\n\r\nconst AIContext = React.createContext();\r\nexport default AIContext;\r\n\r\nconst AIContextProvider = ({ children }) => {\r\n //#region State variables\r\n const [hasChanges, setHasChanges] = React.useState(false);\r\n const [initError, setInitError] = React.useState(null);\r\n const [initializing, setInitializing] = React.useState(true);\r\n const [modelFilterValue, setModelFilterValue] = React.useState(\"\");\r\n const [projectTypes, setProjectTypes] = React.useState([]);\r\n const [projectTypeSettingList, setProjectTypeSettingList] = React.useState(\r\n []\r\n );\r\n const [projectTypeStructures, setProjectTypeStructures] = React.useState([]);\r\n const [selectedModel, setSelectedModel] = React.useState(null);\r\n const [selectedModelName, setSelectedModelName] = React.useState(\"\");\r\n const [selectedProjectType, setSelectedProjectType] = React.useState({});\r\n const [selectedStructuresMappingIdx, setSelectedStructuresMappingIdx] =\r\n React.useState(0);\r\n const [selectedTab, setSelectedTab] = React.useState(0);\r\n const [structuresMapping, setStructuresMapping] = React.useState([]);\r\n const [trainedModels, setTrainedModels] = React.useState([]);\r\n //#endregion\r\n\r\n //#region Effect hooks\r\n React.useEffect(() => {\r\n initialize();\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!initializing) return;\r\n initialize();\r\n }, [initializing]);\r\n\r\n React.useEffect(() => {\r\n if (selectedProjectType.name === undefined) return;\r\n setProjectTypeStructures([]);\r\n Backend.loadViewerConfig(selectedProjectType.name, (viewerConfig) => {\r\n const newProjectTypeStructures = viewerConfig.project.structures.map(\r\n (structure) => {\r\n if (structure.parentId === 0) {\r\n structure.parentId = null;\r\n }\r\n return Structure.fromObject(structure);\r\n }\r\n );\r\n setProjectTypeStructures(newProjectTypeStructures);\r\n });\r\n }, [selectedProjectType]);\r\n\r\n React.useEffect(() => {\r\n if (!selectedModel) return;\r\n Backend.loadAvailableProjectTypes(false).then((projectTypes) => {\r\n const selectedProjectType = projectTypes.find(\r\n (item) => item.name === selectedModel.settings.projectType\r\n );\r\n if (selectedProjectType) {\r\n updateSelectedProjectType(selectedProjectType);\r\n }\r\n });\r\n Backend.readProjectTypeMappingForAIModel(\r\n selectedModel.settings.metaData.name\r\n ).then((mappingArray) => {\r\n initMapping(mappingArray);\r\n });\r\n setSelectedStructuresMappingIdx(0);\r\n setHasChanges(false);\r\n }, [selectedModel]);\r\n\r\n //#endregion\r\n\r\n //#region Helper functions\r\n\r\n /**\r\n * Initializes the AI context by loading the trained models and project types from the backend.\r\n */\r\n const initialize = () => {\r\n Backend.getModelMetadata(\"hsa_models\", false)\r\n .then((res) => {\r\n setTrainedModels(res.newModels);\r\n setInitializing(false);\r\n setInitError(null);\r\n })\r\n .catch((error) => {\r\n console.error(\"Error in loading models:\\n\", error);\r\n setInitializing(false);\r\n setInitError(error);\r\n });\r\n Backend.loadAvailableProjectTypes(false).then((projectTypes) => {\r\n setProjectTypes(projectTypes);\r\n });\r\n };\r\n\r\n /**\r\n * Fetches the trained models from the backend and overwrites the current models.\r\n */\r\n const updateModels = () => {\r\n Backend.getModelMetadata(\"hsa_models\", false)\r\n .then((res) => {\r\n setTrainedModels(res.newModels);\r\n setInitError(null);\r\n })\r\n .catch((error) => {\r\n console.error(\"Error in loading models:\\n\", error);\r\n setInitError(error);\r\n });\r\n };\r\n\r\n const AIModels = [];\r\n const nTrainedModels = trainedModels.length;\r\n if (nTrainedModels > 0) {\r\n for (let i = 0; i < nTrainedModels; i++) {\r\n const model = trainedModels[i];\r\n if (model.settings.trainingParameters.epochs === 0) {\r\n console.error(\r\n \"Model has 0 epochs, skipping model\",\r\n model.settings.metaData.name\r\n );\r\n continue;\r\n }\r\n\r\n // initialize AIModelDataContainer\r\n const AIModelDataContainer = AITrainingDataContainer.fromObject(model);\r\n\r\n AIModels.push(AIModelDataContainer);\r\n }\r\n\r\n AIModels.sort((a, b) => {\r\n return (\r\n Date.parse(b.information.creationDate) -\r\n Date.parse(a.information.creationDate)\r\n );\r\n });\r\n }\r\n\r\n const createDefaultModelMapping = (model) => {\r\n const mappingObject = {\r\n projectType: model.settings.projectType,\r\n aiModel: model.settings.metaData.name,\r\n targetDataFormat: TargetDataFormat.Image,\r\n structureMappings: model.settings.structures.map((modelStructure) => {\r\n return {\r\n oldId: modelStructure.id,\r\n newId: modelStructure.id,\r\n };\r\n }),\r\n inferenceParameters: new ImageInferenceParameters(0.15),\r\n isActive: false,\r\n outerStructureId: 1,\r\n };\r\n return mappingObject;\r\n };\r\n\r\n const initMapping = (mappingArray) => {\r\n const newStructureMapping = mappingArray.map((item) => {\r\n return AIModel2ProjectTypeMapping.fromObject(item);\r\n });\r\n if (\r\n !mappingArray.find(\r\n (item) => item.aiModel === selectedModel.settings.metaData.name\r\n )\r\n ) {\r\n const mappingObject = createDefaultModelMapping(selectedModel);\r\n const modelStructureMapping =\r\n AIModel2ProjectTypeMapping.fromObject(mappingObject);\r\n newStructureMapping.push(modelStructureMapping);\r\n }\r\n setStructuresMapping(newStructureMapping);\r\n };\r\n\r\n const updateSelectedProjectType = (projectType) => {\r\n const index = structuresMapping.findIndex(\r\n (item) => projectType.name === item.projectType\r\n );\r\n if (index !== -1) {\r\n setSelectedStructuresMappingIdx(index);\r\n }\r\n setSelectedProjectType(projectType);\r\n };\r\n\r\n const saveCurrentModelSettings = () => {\r\n Backend.writeProjectTypeMappingForAIModel(\r\n selectedModel.settings.metaData.name,\r\n structuresMapping\r\n ).then((response) => {\r\n if (response.ok) {\r\n window.showSuccessSnackbar(\"Model settings saved successfully\");\r\n setHasChanges(false);\r\n } else {\r\n window.openErrorDialog(\r\n \"Error in saving model settings\" + response.error\r\n );\r\n }\r\n });\r\n };\r\n\r\n const addMapping = (projectType) => {\r\n if (\r\n structuresMapping.find((item) => item.projectType === projectType.name)\r\n ) {\r\n window.showWarningSnackbar(\r\n \"Mapping already exists for this project type\"\r\n );\r\n return;\r\n }\r\n const mappingObject = {\r\n projectType: projectType.name,\r\n aiModel: selectedModel.settings.metaData.name,\r\n targetDataFormat: TargetDataFormat.Image,\r\n inferenceParameters: new ImageInferenceParameters(0.15),\r\n structureMappings: selectedModel.settings.structures.map(\r\n (modelStructure) => {\r\n return {\r\n oldId: modelStructure.id,\r\n newId: null,\r\n };\r\n }\r\n ),\r\n outerStructureId: 1,\r\n isActive: false,\r\n };\r\n const newMapping = AIModel2ProjectTypeMapping.fromObject(mappingObject);\r\n const mappingArray = [...structuresMapping];\r\n mappingArray.push(newMapping);\r\n setStructuresMapping(mappingArray);\r\n setSelectedStructuresMappingIdx(mappingArray.length - 1);\r\n setSelectedProjectType(projectType);\r\n };\r\n\r\n const removeMapping = (index) => {\r\n let newItems = [...structuresMapping];\r\n newItems.splice(index, 1);\r\n setStructuresMapping(newItems);\r\n setHasChanges(true);\r\n if (\r\n selectedStructuresMappingIdx === index ||\r\n selectedStructuresMappingIdx > newItems.length - 1\r\n ) {\r\n handleSelectProjectTypeIdx(0);\r\n }\r\n };\r\n\r\n const handleSelectProjectTypeIdx = (index) => {\r\n setSelectedStructuresMappingIdx(index);\r\n const selectedMapping = structuresMapping[index];\r\n const projectType = projectTypes.find(\r\n (item) => item.name === selectedMapping.projectType\r\n );\r\n setSelectedProjectType(projectType);\r\n };\r\n\r\n const updateStructuresMappingWithIdx = (mappingItem, idx) => {\r\n const newStructuresMapping = [...structuresMapping];\r\n newStructuresMapping[idx] = mappingItem;\r\n setStructuresMapping(newStructuresMapping);\r\n setHasChanges(true);\r\n };\r\n //#endregion\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};\r\n\r\nAIContextProvider.propTypes = {\r\n children: PropTypes.node.isRequired,\r\n};\r\n\r\nexport { AIContextProvider };\r\n","// authenication.service.js\r\n// This is a service that is used to handle the login and logout of a user. It uses the fetch API to make requests to the server. It also uses the BehaviorSubject from the rxjs library to store the current user in the local storage and keep the user logged in between page refreshes.\r\n\r\n// Copyright HS Analysis GmbH, 2019\r\n// Author: Viktor Eberhardt\r\n\r\n// External imports\r\nimport { BehaviorSubject } from \"rxjs\";\r\n\r\n// HSA imports\r\nimport { handleResponse } from \"../utils\";\r\n\r\nconst currentUserSubject = new BehaviorSubject(\r\n JSON.parse(localStorage.getItem(\"currentUser\"))\r\n);\r\n\r\nexport const authenticationService = {\r\n login,\r\n isLoggedIn,\r\n logout,\r\n currentUser: currentUserSubject.asObservable(),\r\n get currentUserValue() {\r\n return currentUserSubject.value;\r\n },\r\n};\r\n\r\nfunction login(email, password) {\r\n const requestOptions = {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ email, password }),\r\n };\r\n\r\n return fetch(`/api/user/authenticate`, requestOptions)\r\n .then(handleResponse)\r\n .then((user) => {\r\n // store user details and jwt token in local storage to keep user logged in between page refreshes\r\n localStorage.setItem(\"currentUser\", JSON.stringify(user));\r\n currentUserSubject.next(user);\r\n return user;\r\n });\r\n}\r\n\r\n/**\r\n * Checks if the user is logged in by sending a request to the server to verify the token.\r\n * @returns {boolean} True if the user is logged in, false otherwise.\r\n */\r\nasync function isLoggedIn() {\r\n if (!currentUserSubject?.value?.token) {\r\n return false;\r\n }\r\n\r\n const canAuthenicate = await fetch(`/api/about/is_alive_auth`, {\r\n method: \"GET\",\r\n headers: {\r\n Authorization: `Bearer ${currentUserSubject.value.token}`,\r\n },\r\n })\r\n .then(\r\n (response) => {\r\n if (response.ok) {\r\n return Promise.resolve(true);\r\n } else {\r\n localStorage.removeItem(\"currentUser\");\r\n currentUserSubject.next(null);\r\n return Promise.resolve(false);\r\n }\r\n },\r\n () => {\r\n localStorage.removeItem(\"currentUser\");\r\n currentUserSubject.next(null);\r\n return Promise.resolve(false);\r\n }\r\n )\r\n .catch(() => {\r\n localStorage.removeItem(\"currentUser\");\r\n currentUserSubject.next(null);\r\n return Promise.resolve(false);\r\n });\r\n\r\n return canAuthenicate;\r\n}\r\n\r\n/**\r\n * Logs the user out and removes the user from local storage.\r\n */\r\nasync function logout() {\r\n const loggedIn = await isLoggedIn();\r\n if (!loggedIn) return;\r\n\r\n fetch(`/api/user/logout`, {\r\n method: \"POST\",\r\n headers: {\r\n Authorization: `Bearer ${currentUserSubject.value.token}`,\r\n },\r\n }).then(\r\n (response) => {\r\n if (response.ok) {\r\n // Remove user from local storage to log user out.\r\n localStorage.removeItem(\"currentUser\");\r\n currentUserSubject.next(null);\r\n window.location.reload();\r\n Promise.resolve();\r\n } else {\r\n response.text().then((text) => {\r\n const data = text && JSON.parse(text);\r\n const error = (data && data.message) || response.statusText;\r\n console.error(\"Error logging out: \" + error);\r\n return Promise.reject(error);\r\n });\r\n }\r\n },\r\n (error) => {\r\n return Promise.reject(error);\r\n }\r\n );\r\n}\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nimport withStyles from \"@mui/styles/withStyles\";\r\nimport {\r\n TextField,\r\n MenuItem,\r\n FormControl,\r\n Checkbox,\r\n RadioGroup,\r\n FormControlLabel,\r\n FormLabel,\r\n} from \"@mui/material\";\r\n\r\nconst styles = {\r\n paddingContainer: {\r\n padding: 10,\r\n },\r\n formItem: {\r\n width: \"100%\",\r\n marginBottom: 20,\r\n },\r\n numberInput: {\r\n width: 50,\r\n marginRight: 10,\r\n },\r\n applyButton: {\r\n width: \"100%\",\r\n },\r\n hidden: {\r\n display: \"none\",\r\n },\r\n};\r\n\r\nclass ProteomSettings extends Component {\r\n render() {\r\n const { classes, metaData, projectStringProperties, onChangeMetaData } =\r\n this.props;\r\n if (typeof projectStringProperties === \"undefined\") return
;\r\n return (\r\n
\r\n \r\n onChangeMetaData(\"Channel\", e.target.value)}\r\n value={metaData.Channel}\r\n >\r\n {projectStringProperties.Channel.split(\",\").map((value, index) => (\r\n \r\n {value}\r\n \r\n ))}\r\n \r\n \r\n\r\n \r\n onChangeMetaData(\"Proteome\", e.target.value)}\r\n value={metaData.Proteome}\r\n >\r\n {projectStringProperties.Proteome.split(\",\").map((value, index) => (\r\n \r\n {value}\r\n \r\n ))}\r\n \r\n \r\n\r\n \r\n Epitope type\r\n \r\n \r\n onChangeMetaData(\"Continues\", e.currentTarget.checked)\r\n }\r\n checked={Boolean(metaData.Continues)}\r\n />\r\n }\r\n label=\"Continuous\"\r\n />\r\n \r\n onChangeMetaData(\"Discontinues\", e.currentTarget.checked)\r\n }\r\n checked={Boolean(metaData.Discontinues)}\r\n />\r\n }\r\n label=\"Discontinuous\"\r\n />\r\n \r\n \r\n \r\n Epitope length\r\n
\r\n {\r\n if (e.target.value < metaData.EpitopeLengthMax) {\r\n onChangeMetaData(\"EpitopeLengthMin\", e.target.value);\r\n }\r\n }}\r\n value={metaData.EpitopeLengthMin}\r\n className={classes.numberInput}\r\n />\r\n {\r\n if (e.target.value > metaData.EpitopeLengthMin) {\r\n onChangeMetaData(\"EpitopeLengthMax\", e.target.value);\r\n }\r\n }}\r\n value={metaData.EpitopeLengthMax}\r\n className={classes.numberInput}\r\n />\r\n
\r\n
\r\n \r\n \r\n Minimum score (do not show results with lower score)\r\n \r\n
\r\n onChangeMetaData(\"MinScore\", e.target.value)}\r\n inputProps={{ step: \"0.01\" }}\r\n value={metaData.MinScore}\r\n className={classes.numberInput}\r\n />\r\n
\r\n
\r\n
\r\n );\r\n }\r\n}\r\n\r\nProteomSettings.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n metaData: PropTypes.object,\r\n projectProperties: PropTypes.object,\r\n projectStringProperties: PropTypes.object,\r\n onChangeMetaData: PropTypes.func,\r\n};\r\n\r\nexport default withStyles(styles)(ProteomSettings);\r\n","import React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport classNames from \"classnames\";\r\nimport { ImageListItem, ImageList, ImageListItemBar } from \"@mui/material\";\r\n\r\nimport { makeStyles } from \"@mui/styles\";\r\n\r\nconst useStyles = makeStyles({\r\n projectTilesList: {\r\n maxHeight: 437,\r\n maxWidth: 750,\r\n padding: 3,\r\n },\r\n\r\n projectTile: {\r\n cursor: \"pointer\",\r\n padding: 5,\r\n overflow: \"hidden\",\r\n border: \"1px solid black\",\r\n \"&:hover\": {\r\n background: \"#AAA\",\r\n },\r\n },\r\n projectTileSelected: {\r\n background: \"#1BA1E2!important\",\r\n },\r\n\r\n expiredMarker: {\r\n color: \"red\",\r\n border: \"2px solid red\",\r\n position: \"absolute\",\r\n top: 5,\r\n right: 5,\r\n zIndex: 1,\r\n background: \"rgba(255,255,255,0.9)\",\r\n padding: \"2px 5px 5px 5px\",\r\n },\r\n expiringMarker: {\r\n color: \"darkorange\",\r\n border: \"2px solid darkorange\",\r\n position: \"absolute\",\r\n top: 8,\r\n right: 8,\r\n zIndex: 1,\r\n background: \"rgba(255,255,255,0.9)\",\r\n padding: \"2px 5px 5px 5px\",\r\n lineHeight: \"16px\",\r\n },\r\n});\r\n\r\nconst ProjectTypeList = ({\r\n projectType,\r\n onProjectType,\r\n availableTypes,\r\n searchText,\r\n}) => {\r\n const classes = useStyles();\r\n return (\r\n \r\n {availableTypes\r\n .filter((row) => {\r\n let searchContent = row.label.toLowerCase();\r\n if (row.projectProperties.Hidden) return false;\r\n let toSearch = searchText.toLowerCase();\r\n return searchContent.includes(toSearch);\r\n })\r\n .map((availableType) => (\r\n onProjectType(availableType)}\r\n className={classNames(\r\n classes.projectTile,\r\n projectType === availableType.name && classes.projectTileSelected\r\n )}\r\n >\r\n {availableType.projectProperties.WIP && (\r\n
WIP
\r\n )}\r\n\r\n {availableType.isValid === false &&\r\n availableType.expirationDate && (\r\n
\r\n Expired on{\" \"}\r\n {availableType.expirationDate.replace(\"T00:00:00\", \"\")}!\r\n
\r\n )}\r\n {availableType.isValid && availableType.expiresInDays < 32 && (\r\n
\r\n Expires in {availableType.expiresInDays} days!\r\n
\r\n )}\r\n\r\n \r\n\r\n \r\n \r\n ))}\r\n \r\n );\r\n};\r\n\r\nProjectTypeList.propTypes = {\r\n projectType: PropTypes.string.isRequired,\r\n onProjectType: PropTypes.func.isRequired,\r\n availableTypes: PropTypes.array.isRequired,\r\n searchText: PropTypes.string.isRequired,\r\n};\r\n\r\nexport default ProjectTypeList;\r\n","// Framework imports\r\nimport React, { useState, useRef, useEffect } from \"react\";\r\nimport { PropTypes } from \"prop-types\";\r\n\r\n/**\r\n * Only load the visible children of a (long) list.\r\n * @param {Array} children Children to be rendered only whne in rendering area.\r\n * @param {number} maxContainerHeight The maximum allowed height of the container in pixels.\r\n * @param {number} elementHeight The height of a single element. all elements assumed to be the same height.\r\n * @param {number} offsetElements Optional. The number of elements to be preloaded outside of visible area. Defaults to 2.\r\n * @returns\r\n */\r\nconst LazyRender = React.forwardRef((props, ref) => {\r\n const {\r\n children,\r\n maxContainerHeight,\r\n elementHeight,\r\n offsetElements = 2,\r\n } = props;\r\n const containerRef = useRef();\r\n\r\n const [scrollPositionTop, setScrollPositionTop] = useState(0);\r\n const [containerHeight, setContainerHeight] = useState(100);\r\n\r\n useEffect(() => {\r\n setContainerHeight(containerRef.current.clientHeight);\r\n containerRef.current.addEventListener(\"scroll\", (e) => handleScroll(e));\r\n return containerRef.current.removeEventListener(\"scroll\", (e) =>\r\n handleScroll(e)\r\n );\r\n }, []);\r\n\r\n useEffect(() => {\r\n setContainerHeight(containerRef.current.clientHeight);\r\n }, [children.length]);\r\n\r\n /**\r\n * Update position and container properties on scroll.\r\n * @param {event} e Scrollevent.\r\n */\r\n const handleScroll = (e) => {\r\n setScrollPositionTop(e.target.scrollTop);\r\n };\r\n\r\n /**\r\n * Scrolls smoothly to the bottom of the list\r\n */\r\n const scrollBottom = () => {\r\n if (containerRef.current) {\r\n const { scrollHeight, clientHeight } = containerRef.current;\r\n containerRef.current.scrollTo({\r\n top: scrollHeight - clientHeight,\r\n });\r\n }\r\n };\r\n\r\n /**\r\n * The placeholder to put in place of a non-rendered element\r\n */\r\n const placeholder = (key) => (\r\n
  • \r\n );\r\n\r\n /**\r\n * Determine if an element should be rendered depending on its position.\r\n * @param {int} idx The index of the element in an arrray.\r\n * @returns {Boolean} Whether an element sould be rendered.\r\n */\r\n function isInView(idx) {\r\n const pos = idx * elementHeight;\r\n\r\n const minRendered = scrollPositionTop - offsetElements * elementHeight;\r\n const maxRendered =\r\n scrollPositionTop + containerHeight + offsetElements * elementHeight;\r\n\r\n const shouldBeRendered = pos >= minRendered && pos <= maxRendered;\r\n return shouldBeRendered;\r\n }\r\n\r\n // make scrollBottom() callable from parent component\r\n React.useImperativeHandle(ref, () => ({\r\n scrollBottom,\r\n }));\r\n\r\n return (\r\n \r\n {children.map((c, i) => (isInView(i) ? c : placeholder(i)))}\r\n
    \r\n );\r\n});\r\n\r\nLazyRender.propTypes = {\r\n children: PropTypes.array.isRequired,\r\n maxContainerHeight: PropTypes.number.isRequired,\r\n elementHeight: PropTypes.number.isRequired,\r\n offsetElements: PropTypes.number,\r\n};\r\n\r\nLazyRender.displayName = \"LazyRender\";\r\nexport default LazyRender;\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nimport { RegionROI } from \"../utils/ROI\";\r\n\r\nimport { withPersistentStorage } from \"./PersistentStorageContext\";\r\nimport { withProject } from \"./ProjectContext\";\r\n\r\nimport { getParentIndexLayer } from \"../utils/StructuresUtils\";\r\n\r\nconst ProjectHistoryContext = React.createContext();\r\n\r\nexport const withProjectHistory = (Component) => {\r\n const WrappedComponent = (props) => (\r\n \r\n {(context) => }\r\n \r\n );\r\n\r\n WrappedComponent.displayName = `withProjectHistory(${\r\n Component.displayName || Component.name || \"Component\"\r\n })`;\r\n\r\n return WrappedComponent;\r\n};\r\n\r\n// this is the main component, it has to be added at the root of the app.\r\n// all components that use withProject(...) will have access to it via this.props.Project...\r\n// There is not limit for steps, since it should also be used to save new Annotations to the project\r\nclass ProjectHistoryProvider extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n canUndo: false,\r\n canRedo: false,\r\n sizeLimitReached: false,\r\n };\r\n this.socket = null;\r\n this.shownSaveHintNum = 0;\r\n window.projectHistory = this;\r\n }\r\n\r\n /**\r\n * Initializes the Project provider and passes a viewer component\r\n *\r\n * @param {object} viewer - Viewer Component\r\n */\r\n init = (viewer) => {\r\n this.viewer = viewer;\r\n this.collecting = false;\r\n this.collection = [];\r\n this.past = [];\r\n this.future = [];\r\n };\r\n\r\n send = (stepType, items) => {\r\n const toSend = {\r\n state: \"anno\",\r\n stepType,\r\n };\r\n if (stepType === \"pastHistory\") {\r\n toSend.items = items.map((item) => {\r\n return item.map((itm) => {\r\n return {\r\n add: itm.add,\r\n id: itm.id,\r\n roi: itm.roi.regions,\r\n };\r\n });\r\n });\r\n } else if (typeof items !== \"undefined\") {\r\n toSend.items = items.map((item) => {\r\n return {\r\n add: item.add,\r\n id: item.id,\r\n roi: item.roi.regions,\r\n };\r\n });\r\n }\r\n\r\n // this.socket.send(JSON.stringify(toSend));\r\n };\r\n\r\n receive = (input) => {\r\n const { structures } = this.viewer.props.projectContext;\r\n if (input.state === \"init\" && this.past) {\r\n this.send(\"pastHistory\", this.past);\r\n return;\r\n }\r\n if (input.stepType === \"pastHistory\" && input.items) {\r\n for (const inputItems of input.items) {\r\n const items = inputItems.map((item) => {\r\n const roiStructure = structures.find((str) => str.id === item.id);\r\n return {\r\n add: item.add,\r\n id: item.id,\r\n roi: new RegionROI({\r\n regions: [item.roi],\r\n structureId: item.id,\r\n color: roiStructure.color,\r\n isSubtype: roiStructure.classificationSubtype,\r\n subtypeName: roiStructure.label,\r\n }),\r\n };\r\n });\r\n this.past.push(items);\r\n this.processItem(items, \"redo\");\r\n }\r\n this.future = [];\r\n this.updateState();\r\n return;\r\n }\r\n if (input.items) {\r\n const items = input.items.map((item) => {\r\n const roiStructure = structures.find((str) => str.id === item.id);\r\n return {\r\n add: item.add,\r\n id: item.id,\r\n roi: new RegionROI({\r\n regions: [item.roi],\r\n structureId: item.id,\r\n color: roiStructure.color,\r\n isSubtype: roiStructure.classificationSubtype,\r\n subtypeName: roiStructure.label,\r\n }),\r\n };\r\n });\r\n if (input.stepType === \"redo\") {\r\n this.past.push(items);\r\n this.future = [];\r\n } else if (input.stepType === \"undo\") {\r\n this.future.push(items);\r\n }\r\n this.updateState();\r\n this.processItem(items, input.stepType);\r\n } else {\r\n if (input.stepType === \"undo\") {\r\n this.undoItem();\r\n } else if (input.stepType === \"redo\") {\r\n this.redoItem();\r\n }\r\n }\r\n };\r\n\r\n add = (items) => {\r\n if (items.length > 0) {\r\n items = items.map((item) => {\r\n item.roi = item.roi.copy();\r\n item.id = item.roi.structureId;\r\n return item;\r\n });\r\n if (this.collecting) {\r\n this.collection.push(items);\r\n } else {\r\n this.send(\"redo\", items);\r\n this.past.push(items);\r\n this.future = [];\r\n }\r\n this.updateState();\r\n if (Math.floor(this.past.length / 100) > this.shownSaveHintNum) {\r\n this.shownSaveHintNum++;\r\n window.showActionSnackbar(\r\n \"Would you like to save your \" + this.past.length + \" changes?\",\r\n this.props.projectContext.viewer.onSaveClick,\r\n \"Save now\",\r\n \"Dismiss\"\r\n );\r\n }\r\n }\r\n };\r\n\r\n //intern function, adds and removes polys for one item (history step)\r\n processItem = (items, stepType) => {\r\n if (items.length === 0) return;\r\n\r\n const { fileId, structures } = this.viewer.props.projectContext;\r\n let roiLayers = this.viewer.props.projectContext.roiLayers[fileId];\r\n\r\n for (let action of items) {\r\n let parentLayerIdx = -1;\r\n try {\r\n parentLayerIdx = getParentIndexLayer(\r\n structures.find((str) => str.id === action.id),\r\n structures\r\n );\r\n } catch (ex) {\r\n console.log(stepType, \"error:\", ex);\r\n window.showErrorSnackbar(\r\n \"Something went wrong, \" + stepType + \" ignored!\"\r\n );\r\n return;\r\n }\r\n const parentRoiLayer = roiLayers[parentLayerIdx];\r\n\r\n if (\r\n (stepType === \"redo\" && action.add) ||\r\n (stepType === \"undo\" && !action.add)\r\n ) {\r\n const overlapItems = parentRoiLayer.tree.search(action.roi.treeItem);\r\n let isSame = false;\r\n for (const treeItem of overlapItems) {\r\n if (treeItem.roi.sameBoundsWith(action.roi)) {\r\n isSame = true;\r\n break;\r\n }\r\n }\r\n if (!isSame) {\r\n parentRoiLayer.tree.insert(action.roi.treeItem);\r\n }\r\n } else {\r\n parentRoiLayer.tree.remove(action.roi.treeItem, (a, b) => {\r\n return a.roi.sameBoundsWith(b.roi);\r\n });\r\n }\r\n parentRoiLayer.layer.regionRois = parentRoiLayer.tree\r\n .all()\r\n .map((treeItem) => treeItem.roi);\r\n }\r\n };\r\n\r\n undoItem = () => {\r\n if (this.past.length > 0) {\r\n let item = this.past.pop();\r\n this.processItem(item, \"undo\");\r\n this.future.push(item);\r\n this.updateState();\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n undo = () => {\r\n const actionDone = this.undoItem();\r\n if (actionDone) {\r\n this.send(\"undo\");\r\n }\r\n };\r\n\r\n redoItem = () => {\r\n if (this.future.length > 0) {\r\n let item = this.future.pop();\r\n this.processItem(item, \"redo\");\r\n this.past.push(item);\r\n this.updateState();\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n redo = () => {\r\n const actionDone = this.redoItem();\r\n if (actionDone) {\r\n this.send(\"redo\");\r\n }\r\n };\r\n\r\n clear = () => {\r\n this.past = [];\r\n this.future = [];\r\n this.shownSaveHintNum = 0;\r\n this.updateState();\r\n };\r\n\r\n updateState = () => {\r\n this.setState({\r\n canUndo: this.past.length > 0,\r\n canRedo: this.future.length > 0,\r\n });\r\n };\r\n\r\n getHistoryLength = () => {\r\n return this.past.length;\r\n };\r\n\r\n mergePastItems(n) {\r\n if (n > 1) {\r\n let newItem = [];\r\n for (let i = 0; i < n; i++) {\r\n let item = this.past.pop();\r\n newItem.push(...item);\r\n }\r\n this.past.push(newItem);\r\n this.future = [];\r\n }\r\n }\r\n\r\n startCollection() {\r\n this.collecting = true;\r\n }\r\n\r\n addCollection() {\r\n this.collecting = false;\r\n let mergedItems = [];\r\n while (this.collection.length > 0) {\r\n const items = this.collection.pop();\r\n mergedItems.push(...items);\r\n }\r\n this.collection = [];\r\n this.add(mergedItems);\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n {this.props.children}\r\n \r\n );\r\n }\r\n}\r\n\r\nProjectHistoryProvider.propTypes = {\r\n historyDepth: PropTypes.number.isRequired,\r\n projectContext: PropTypes.object,\r\n children: PropTypes.element.isRequired,\r\n};\r\n\r\nexport default withPersistentStorage(withProject(ProjectHistoryProvider));\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport { Grid, Button, TextField } from \"@mui/material\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\nconst styles = () => ({\r\n root: {},\r\n});\r\n\r\n// This is commented out since the attepts to implement an autocomplete\r\n// somehow failed. However, it took time to copy, so it stays for now.\r\n// // Product per specifications\r\n// const products = [\r\n// { label: \"Bratwurst\", abbr: \"BW\" },\r\n// { label: \"Kochpökelware\", abbr: \"KO\" },\r\n// { label: \"Rohpökelware\", abbr: \"RO\" },\r\n// { label: \"Brühwurst\", abbr: \"BR\" },\r\n// { label: \"Verarbeitugnsfleisch\", abbr: \"VA\" },\r\n// { label: \"Separatorenfleisch\", abbr: \"SP\" },\r\n// { label: \"Hackfleisch roh\", abbr: \"HA\" },\r\n// { label: \"Hackfleischerz. gegart\", abbr: \"HG\" },\r\n// { label: \"Kochwurst\", abbr: \"KO\" },\r\n// { label: \"Rohwurst\", abbr: \"RO\" },\r\n// { label: \"Aspikwaren\", abbr: \"AS\" },\r\n// { label: \"Rohfleisch\", abbr: \"RF\" },\r\n// { label: \"Gegartes Fleisch\", abbr: \"GF\" },\r\n// { label: \"Kontrollen\", abbr: \"KO\" },\r\n// { label: \"Stufenkontrollen\", abbr: \"SK\" },\r\n// { label: \"LVU\", abbr: \"LV\" },\r\n// { label: \"Zusätze\", abbr: \"ZU\" },\r\n// { label: \"Fisch\", abbr: \"FI\" },\r\n// { label: \"Vegetarische Produkte\", abbr: \"VP\" },\r\n// { label: \"Sonstiges\", abbr: \"SO\" },\r\n// ];\r\n\r\n// const products_2 = [\r\n// \"BW\",\r\n// \"KO\",\r\n// \"RO\",\r\n// \"BR\",\r\n// \"VA\",\r\n// \"SP\",\r\n// \"HA\",\r\n// \"HG\",\r\n// \"AS\",\r\n// \"RF\",\r\n// \"GF\",\r\n// \"SK\",\r\n// \"LV\",\r\n// \"ZU\",\r\n// \"FI\",\r\n// \"VP\",\r\n// \"SO\",\r\n// ];\r\n\r\nclass EmptySlideCreation extends Component {\r\n // Allow format YYYY-XXZZZZZ-FF-TT-SSS-NN\r\n allowed_formats = [\r\n /^[0-9]{4}-[0-9]{7}-[0-9_]{2}-[A-Z]{2}-[A-Z0-9_]{3}-[0-9]{2}$/,\r\n ];\r\n\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n emptyFile_name: \"\",\r\n ref_regex: React.createRef(),\r\n valid_regex: false,\r\n };\r\n }\r\n\r\n /**\r\n * Checks the input against all valid inputs and updates the status accordingly.\r\n * @param {string} input The currently typed value in the entry field.\r\n */\r\n checkFormat = (input) => {\r\n this.setState({\r\n valid_regex: this.allowed_formats.some((format) => {\r\n return format.test(input);\r\n }),\r\n });\r\n this.setState({ emptyFile_name: input });\r\n };\r\n\r\n /**\r\n * The histo classificaation module needs to work without an actual file.\r\n * Here, the interface is provided to add the relevant information to do so.\r\n * It mimics the filename structure YYYY-XXZZZZZ-FF-TT-SSS-NN\r\n * @returns empty file creation interface for histo modules\r\n */\r\n render() {\r\n return (\r\n \r\n \r\n this.checkFormat(e.target.value)}\r\n type=\"text\"\r\n variant=\"standard\"\r\n value={this.state.emptyFile_name}\r\n // Enable adding files with \"Enter\" key.\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\") {\r\n e.preventDefault();\r\n\r\n if (this.state.valid_regex) {\r\n // Add file with empty attribute to it\r\n this.props.addFile(\r\n e,\r\n this.state.emptyFile_name.concat(\" (empty)\")\r\n );\r\n // Clear entry field for next entry\r\n this.setState({ emptyFile_name: \"\" });\r\n }\r\n }\r\n }}\r\n />\r\n \r\n \r\n {/* Add Button */}\r\n \r\n {\r\n // Add file with empty attribute to it\r\n this.props.addFile(\r\n event,\r\n this.state.emptyFile_name.concat(\" (empty)\")\r\n );\r\n // Clear entry field for next entry\r\n this.setState({ emptyFile_name: \"\" });\r\n }}\r\n >\r\n Add Empty Slide\r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nEmptySlideCreation.propTypes = {\r\n addFile: PropTypes.func,\r\n};\r\n\r\nexport default withStyles(styles)(EmptySlideCreation);\r\n","/* eslint-disable */\r\nimport React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nimport withStyles from \"@mui/styles/withStyles\";\r\nimport SearchIcon from \"@mui/icons-material/Search\";\r\nimport MoreVertIcon from \"@mui/icons-material/MoreVert\";\r\nimport {\r\n DialogContent,\r\n TextField,\r\n IconButton,\r\n Grid,\r\n Checkbox,\r\n ListItem,\r\n ListItemButton,\r\n ListItemText,\r\n ListItemIcon,\r\n List,\r\n Tooltip,\r\n ListItemSecondaryAction,\r\n Menu,\r\n MenuItem,\r\n Box,\r\n Button,\r\n} from \"@mui/material\";\r\nimport Backend from \"../../../common/utils/Backend\";\r\nimport EmptySlideCreation from \"./EmptySlideCreation\";\r\nimport {\r\n Folder,\r\n ArrowUpward,\r\n ArrowDownward,\r\n Image,\r\n CheckBox,\r\n AddToPhotos,\r\n} from \"@mui/icons-material\";\r\n\r\nconst styles = () => ({\r\n root: {},\r\n freeHistoParameters: {},\r\n applyButton: {\r\n width: \"100%\",\r\n },\r\n dialogContent: {\r\n paddingTop: 0,\r\n maxWidth: 900,\r\n height: 562,\r\n },\r\n fileList: {\r\n border: \"2px solid rgb(218, 218, 218)\",\r\n height: \"100%\",\r\n overflowY: \"auto\",\r\n minHeight: \"calc(100% - 35px)\",\r\n maxHeight: \"500px\",\r\n },\r\n selButton: {\r\n color: \"black\",\r\n },\r\n item: {\r\n cursor: \"pointer\",\r\n backgroundColor: \"transparent\",\r\n \"&:hover\": {\r\n backgroundColor: \"#0000001a\",\r\n },\r\n padding: \"10px\",\r\n borderBottom: \"1px solid #ccc\",\r\n },\r\n selItem: {\r\n cursor: \"pointer\",\r\n backgroundColor: \"transparent\",\r\n \"&:hover\": {\r\n backgroundColor: \"#0000001a\",\r\n },\r\n padding: \"8px\",\r\n border: `2px solid #0673C1`,\r\n },\r\n});\r\n\r\n// The openslide reader cannot work with non-ascii symbols\r\nconst non_utf8_capable_filetypes = [\"mrxs\", \"svs\", \"ndpi\", \"svslide\"];\r\n\r\nclass StepFileSelection extends Component {\r\n constructor(props) {\r\n super(props);\r\n this._isMounted = false;\r\n this.state = {\r\n dirfiles: [],\r\n dirFilesCase: [],\r\n currentPath: \"\",\r\n lastFileName: \"\",\r\n filterText: \"\",\r\n sortMenuOpen: false,\r\n sortBy: \"name\",\r\n sortReverse: true,\r\n showFolders: true,\r\n caseItems: [],\r\n selCase: null,\r\n caseList: null,\r\n };\r\n\r\n this.updateFolderList(\"\");\r\n }\r\n\r\n componentDidMount() {\r\n this._isMounted = true;\r\n Backend.listCases().then((data) => {\r\n if (!(\"cases\" in data)) return;\r\n let items = [];\r\n data.cases.forEach((c) => {\r\n items.push({ id: c.data.Id, name: c.data.case_acc });\r\n });\r\n this.setMountedState({ caseItems: items, caseList: data });\r\n });\r\n }\r\n\r\n componentWillUnmount() {\r\n this._isMounted = false;\r\n }\r\n\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n getLastDir = (folderPath) => {\r\n let pathEnding = \"-1\";\r\n let lastSeperator = folderPath.lastIndexOf(\"/\");\r\n if (lastSeperator < 0) {\r\n lastSeperator = folderPath.lastIndexOf(String.fromCharCode(92));\r\n }\r\n if (lastSeperator > 0) {\r\n pathEnding = folderPath.substr(lastSeperator + 1, folderPath.length);\r\n }\r\n return pathEnding;\r\n };\r\n\r\n onChangeFilter(e) {\r\n let filterText = e.target.value;\r\n let { currentPath } = this.state;\r\n this.setMountedState({ filterText });\r\n this.updateFolderList(currentPath, filterText);\r\n }\r\n\r\n getFilesFromPath = async (currentPath, filterText, addAll = false) => {\r\n let supportedFileFormats = [];\r\n\r\n switch (this.props.formData.projectType) {\r\n case \"ProteomeAnalysis\":\r\n supportedFileFormats = [\"txt\"];\r\n break;\r\n\r\n case \"ESREvaluation\":\r\n case \"ESRTraining\":\r\n supportedFileFormats = [\"csv\"];\r\n break;\r\n\r\n case \"AudioAnnotator\":\r\n supportedFileFormats = [\"mp3\", \"wav\"];\r\n break;\r\n\r\n default:\r\n supportedFileFormats = [\r\n \"avi\",\r\n \"bmp\",\r\n \"czi\",\r\n \"dm3\",\r\n \"gif\",\r\n \"hsasld\",\r\n \"jpeg\",\r\n \"jpg\",\r\n \"lif\",\r\n \"mp4\",\r\n \"mrxs\",\r\n \"ndpi\",\r\n \"png\",\r\n \"scn\",\r\n \"svs\",\r\n \"svslide\",\r\n \"tif\",\r\n \"tiff\",\r\n // The following formats are not supported on linux systems\r\n \"isyntax\",\r\n \"nd2\",\r\n \"zvi\",\r\n ];\r\n }\r\n Object.freeze(supportedFileFormats);\r\n\r\n let foldersToExclude = [];\r\n\r\n switch (this.props.formData.projectType) {\r\n case \"HistoClassification\":\r\n case \"HistoPointCounting\":\r\n foldersToExclude = [\"DAT\", \"SCS\", \"ANS\"];\r\n break;\r\n // you can add more cases here in the future\r\n default:\r\n break;\r\n }\r\n\r\n // load list of available files\r\n const directoryEntries = await Backend.walkDir(currentPath, true);\r\n\r\n let filteredDirFiles = [];\r\n let subfolderFiles = []; // define 'subfolderFiles' here\r\n\r\n for (const entry of directoryEntries) {\r\n let shouldBeAdded = false;\r\n\r\n if (entry.type === \"directory\") {\r\n const lastDir = this.getLastDir(entry.path);\r\n if (!foldersToExclude.includes(lastDir)) {\r\n if (\r\n directoryEntries.some(\r\n (element) => element.path === `${entry.path}.mrxs`\r\n )\r\n ) {\r\n shouldBeAdded = false;\r\n } else if (addAll) {\r\n const subfiles = await this.getFilesFromPath(\r\n entry.path,\r\n filterText,\r\n addAll\r\n );\r\n if (subfiles === false) return false;\r\n this.addFileCount += subfiles.length;\r\n if (this.addFileCount > 500 && !this.addManyFilesConfirmed) {\r\n // Wrap your function call in a Promise\r\n try {\r\n let confirm = await new Promise((resolve, reject) => {\r\n window.openResponseDialog(\r\n \"More than 500 entries found. Continue parsing?\",\r\n (response) => {\r\n if (response) {\r\n this.addManyFilesConfirmed = true;\r\n resolve(true); // Resolve the Promise positively\r\n } else {\r\n reject(false); // Reject the Promise in case of negative response\r\n }\r\n }\r\n );\r\n });\r\n\r\n // If user replies yes, the promise gets resolved and code execution will continue.\r\n if (!confirm) {\r\n return false;\r\n }\r\n } catch (error) {\r\n // If user replies no, the promise gets rejected and control comes here.\r\n return false;\r\n }\r\n }\r\n\r\n // Now it is safe to use 'subfolderFiles'\r\n subfolderFiles = [...subfolderFiles, ...subfiles];\r\n shouldBeAdded = false;\r\n } else {\r\n shouldBeAdded = true;\r\n }\r\n }\r\n } else if (entry.type === \"file\") {\r\n const pathParts = entry.path.split(\".\");\r\n const extension = pathParts[pathParts.length - 1].toLowerCase();\r\n shouldBeAdded = true;\r\n if (!supportedFileFormats.includes(extension)) shouldBeAdded = false;\r\n if (pathParts[pathParts.length - 2] === \"empty_file\")\r\n shouldBeAdded = false;\r\n } else {\r\n shouldBeAdded = true;\r\n }\r\n\r\n if (filterText !== \"\" && shouldBeAdded) {\r\n const path = entry.path.split(\"/\")[entry.path.split(\"/\").length - 1];\r\n shouldBeAdded = path.toLowerCase().includes(filterText.toLowerCase());\r\n }\r\n\r\n if (shouldBeAdded) {\r\n filteredDirFiles.push(entry);\r\n }\r\n }\r\n\r\n let sortedDirFiles = filteredDirFiles.sort((a, b) =>\r\n a.path > b.path ? 1 : -1\r\n );\r\n\r\n // If you want to combine 'sortedDirFiles' and 'subfolderFiles', do it here. Otherwise, return them separately\r\n return [...sortedDirFiles, ...subfolderFiles];\r\n };\r\n\r\n updateFolderList = (currentPath, filterText = \"\") => {\r\n this.getFilesFromPath(currentPath, filterText).then((dirfiles) => {\r\n // write received info into state\r\n // console.log([dirfiles[0]]);\r\n this.setMountedState({\r\n currentPath: currentPath,\r\n dirfiles: dirfiles,\r\n });\r\n });\r\n };\r\n\r\n addFile = (event, fileName) => {\r\n // Ensure that only ascii-conform paths are used.\r\n if (\r\n non_utf8_capable_filetypes.includes(\r\n fileName.split(\".\").pop().toLowerCase()\r\n )\r\n ) {\r\n let hasMoreThanAscii = [...fileName].some(\r\n (char) => char.charCodeAt(0) > 127\r\n );\r\n if (hasMoreThanAscii) {\r\n window.showErrorSnackbar(\r\n \"File type does not support characters such as 'ä', 'ö', 'ü', or 'ß' in path.\"\r\n );\r\n window.openWarningDialog(\r\n \"The file \" +\r\n fileName +\r\n \" or its path contain invalid characters such as 'ä', 'ö', 'ü', or 'ß'. \\\r\n Please rename the file or its folder.\"\r\n );\r\n return;\r\n }\r\n }\r\n\r\n let { files } = this.props.formData;\r\n let { lastFileName, dirfiles } = this.state;\r\n let dirFilePaths = dirfiles.map((file) => file.path);\r\n if (event.shiftKey && lastFileName !== \"\") {\r\n let lastFileIdx = dirFilePaths.indexOf(lastFileName);\r\n if (lastFileIdx >= 0) {\r\n let fileIdx = dirFilePaths.indexOf(fileName);\r\n let firstIdx = Math.min(lastFileIdx, fileIdx);\r\n let lastIdx = Math.max(lastFileIdx, fileIdx);\r\n files = files.filter((file) => !dirFilePaths.includes(file));\r\n for (let i = firstIdx; i <= lastIdx; i++) {\r\n let fileNameToAdd = dirFilePaths[i];\r\n files.push(fileNameToAdd);\r\n }\r\n this.props.onChangeFiles(files.sort());\r\n }\r\n } else {\r\n if (files.includes(fileName)) {\r\n files = files.filter((c) => c !== fileName);\r\n } else {\r\n files.push(fileName);\r\n }\r\n this.setMountedState({ lastFileName: fileName });\r\n this.props.onChangeFiles(files.sort());\r\n }\r\n };\r\n\r\n toggleAllFiles = (currentPath) => {\r\n let { dirfiles } = this.state;\r\n let { files } = this.props.formData;\r\n if (dirfiles.filter((file) => files.includes(file.path)).length > 0) {\r\n this.removeFolder(currentPath);\r\n } else {\r\n this.addFolder(currentPath);\r\n }\r\n };\r\n\r\n addFolder = (folderPath, clickEvent = null) => {\r\n this.addFileCount = 0;\r\n this.addManyFilesConfirmed = false;\r\n this.getFilesFromPath(folderPath, \"\", true).then((dirfiles) => {\r\n if (dirfiles === false) return false;\r\n let filePaths = dirfiles.map((file) => file.path);\r\n let { files } = this.props.formData;\r\n let filteredFiles = filePaths.filter(\r\n (file) => !files.some((x) => file === x)\r\n );\r\n let filesToAdd = files.concat(filteredFiles);\r\n if (filesToAdd.length > 500) {\r\n window.openResponseDialog(\r\n \"Add \" + filesToAdd.length + \" files?\",\r\n (response) => {\r\n if (response) {\r\n this.props.onChangeFiles(filesToAdd);\r\n }\r\n }\r\n );\r\n } else {\r\n this.props.onChangeFiles(filesToAdd);\r\n }\r\n });\r\n if (clickEvent) clickEvent.stopPropagation();\r\n };\r\n\r\n removeFolder = () => {\r\n let { files } = this.props.formData;\r\n let dirFilePaths = this.state.dirfiles.map((file) => file.path);\r\n let resultFiles = files.filter((file) => dirFilePaths.indexOf(file) < 0);\r\n if (files.length !== resultFiles.length) {\r\n this.props.onChangeFiles(resultFiles.sort());\r\n }\r\n };\r\n\r\n isDisabled = (relativePath) => {\r\n let { project } = this.props;\r\n if (project && project.imageFiles) {\r\n const projectFiles = [\r\n ...new Set(project.imageFiles.map((file) => file.relativePath)),\r\n ];\r\n if (projectFiles.includes(relativePath)) return true;\r\n }\r\n return false;\r\n };\r\n\r\n toggleSortMenu = () => {\r\n this.setMountedState({ sortMenuOpen: !this.state.sortMenuOpen });\r\n };\r\n\r\n setSortBy = (value) => {\r\n let { sortBy, sortReverse } = this.state;\r\n\r\n if (value === sortBy) {\r\n sortReverse = !sortReverse;\r\n } else {\r\n sortReverse = false;\r\n }\r\n\r\n let dirfiles = [];\r\n if (value === \"name\") {\r\n dirfiles = this.state.dirfiles.sort((a, b) => {\r\n if (a.path > b.path) {\r\n return 1;\r\n }\r\n if (a.path < b.path) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n } else {\r\n dirfiles = this.state.dirfiles.sort((a, b) => {\r\n if (a.creationTime > b.creationTime) {\r\n return 1;\r\n }\r\n if (a.creationTime < b.creationTime) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n }\r\n if (!sortReverse) {\r\n dirfiles = dirfiles.reverse();\r\n }\r\n\r\n this.setMountedState({\r\n dirfiles: dirfiles,\r\n sortMenuOpen: false,\r\n sortBy: value,\r\n sortReverse: sortReverse,\r\n });\r\n };\r\n\r\n switchFolderWithCases = () => {\r\n this.setMountedState({ showFolders: !this.state.showFolders });\r\n };\r\n\r\n handleItemClick = (caseId) => {\r\n if (this.state.selCase === caseId) {\r\n this.setMountedState({ selCase: null });\r\n let { files } = this.props.formData;\r\n files = [];\r\n this.props.onChangeFiles(files.sort());\r\n this.props.onChangeCaseId(null);\r\n return;\r\n }\r\n this.setMountedState({ selCase: caseId });\r\n this.props.onChangeCaseId(caseId);\r\n\r\n let pathArray = this.getFilePathsFromCaseList(caseId);\r\n\r\n let { files } = this.props.formData;\r\n files = [];\r\n this.props.onChangeFiles(files.sort());\r\n\r\n let caseFiles = [];\r\n\r\n for (let path of pathArray) {\r\n Backend.walkCaseFiles(path, true, (e) => {\r\n caseFiles.push(e);\r\n this.addCaseFile(e);\r\n this.setMountedState({ dirFilesCase: caseFiles });\r\n });\r\n }\r\n };\r\n\r\n getFilePathsFromCaseList = (caseId) => {\r\n let cases = this.state.caseList.cases;\r\n let foundCase = cases.find((obj) => obj.data.Id === caseId);\r\n if (foundCase === undefined) return [];\r\n return foundCase.filePaths;\r\n };\r\n\r\n addCaseFile = (file) => {\r\n let fileName = file.path;\r\n if (\r\n non_utf8_capable_filetypes.includes(\r\n fileName.split(\".\").pop().toLowerCase()\r\n )\r\n ) {\r\n let hasMoreThanAscii = [...fileName].some(\r\n (char) => char.charCodeAt(0) > 127\r\n );\r\n if (hasMoreThanAscii) {\r\n window.showErrorSnackbar(\r\n \"File type does not support characters such as 'ä', 'ö', 'ü', or 'ß' in path.\"\r\n );\r\n window.openWarningDialog(\r\n \"The file \" +\r\n fileName +\r\n \" or its path contain invalid characters such as 'ä', 'ö', 'ü', or 'ß'. \\\r\n Please rename the file or its folder.\"\r\n );\r\n return;\r\n }\r\n }\r\n let { files } = this.props.formData;\r\n files.push(fileName);\r\n this.props.onChangeFiles(files.sort());\r\n };\r\n\r\n /**\r\n * Sets an image to the default error image when there is an error.\r\n * @param {field} e The field event\r\n */\r\n image_error = (e) => {\r\n e.target.src = \"/img/image_error.svg\";\r\n };\r\n\r\n render() {\r\n const { classes } = this.props;\r\n const { files } = this.props.formData;\r\n const {\r\n dirfiles,\r\n currentPath,\r\n filterText,\r\n sortMenuOpen,\r\n sortBy,\r\n sortReverse,\r\n showFolders,\r\n } = this.state;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n
    \r\n \r\n \r\n All Files (\r\n {dirfiles.filter((e) => e.type === \"file\").length}):\r\n \r\n
    \r\n {\r\n this.switchFolderWithCases();\r\n }}\r\n className={classes.selButton}\r\n style={{\r\n border: showFolders\r\n ? \"1px solid #0673C1\"\r\n : \"1px solid black\",\r\n marginRight: \"10px\",\r\n background: showFolders ? \"#0673c114\" : \"none\",\r\n }}\r\n >\r\n Files\r\n \r\n {\r\n this.switchFolderWithCases();\r\n }}\r\n className={classes.selButton}\r\n style={{\r\n border: !showFolders\r\n ? \"1px solid #0673C1\"\r\n : \"1px solid black\",\r\n background: !showFolders ? \"#0673c114\" : \"none\",\r\n }}\r\n >\r\n Cases\r\n \r\n
    \r\n \r\n \r\n {\r\n this.anchorEl = node;\r\n }}\r\n aria-controls=\"sort-menu\"\r\n aria-haspopup=\"true\"\r\n onClick={() => this.toggleSortMenu()}\r\n size=\"large\"\r\n >\r\n \r\n \r\n \r\n this.toggleSortMenu()}\r\n >\r\n this.setSortBy(\"name\")}>\r\n Sort by name{\" \"}\r\n {sortBy === \"name\" && (\r\n \r\n {sortReverse ? : }\r\n \r\n )}\r\n \r\n this.setSortBy(\"date\")}>\r\n Sort by creation date{\" \"}\r\n {sortBy === \"date\" && (\r\n \r\n {sortReverse ? : }\r\n \r\n )}\r\n \r\n \r\n \r\n \r\n
    \r\n\r\n
    \r\n \r\n this.onChangeFilter(e)}\r\n />\r\n
    \r\n\r\n \r\n {currentPath && showFolders && (\r\n \r\n \r\n files.includes(file.path))\r\n .length > 0\r\n }\r\n onChange={() => this.toggleAllFiles(currentPath)}\r\n />\r\n \r\n \r\n \r\n {\r\n this.updateFolderList(\r\n currentPath.substring(\r\n 0,\r\n currentPath.lastIndexOf(\"/\")\r\n )\r\n );\r\n }}\r\n size=\"large\"\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n )}\r\n {showFolders &&\r\n dirfiles.map((e, id) =>\r\n e.type === \"file\" ? (\r\n \r\n this.addFile(clickEvent, e.path)\r\n }\r\n >\r\n \r\n \r\n
    \r\n {\r\n \r\n }\r\n \r\n {e.path}\r\n
    \r\n \r\n \r\n }\r\n >\r\n {files.includes(e.path) ? (\r\n \r\n ) : (\r\n \r\n )}\r\n \r\n
    \r\n \r\n \r\n File Size:{\" \"}\r\n \r\n {e.fileSize}\r\n
    \r\n \r\n Creation Date:{\" \"}\r\n \r\n {e.creationTime}\r\n \r\n }\r\n >\r\n \r\n \r\n \r\n ) : (\r\n this.updateFolderList(e.path)}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n this.addFolder(e.path)}\r\n size=\"large\"\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n )}\r\n {!showFolders &&\r\n this.state.caseItems &&\r\n this.state.caseItems.map((item) => (\r\n this.handleItemClick(item.id)}\r\n className={\r\n this.state.selCase === item.id\r\n ? classes.selItem\r\n : classes.item\r\n }\r\n >\r\n {item.name}\r\n \r\n ))}\r\n
    \r\n
    \r\n \r\n \r\n {this.props.selectionTarget} Files ({files.length}):\r\n \r\n \r\n {files.map((e, i) => (\r\n \r\n \r\n this.addFile(clickEvent, e)}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ))}\r\n \r\n \r\n
    \r\n {/* Allow slide-free projects in Hist Classification Module. */}\r\n {/* Meta-Data will need to be entered manually. */}\r\n {this.props.formData.projectType === \"HistoClassification\" && (\r\n \r\n )}\r\n \r\n
    \r\n );\r\n }\r\n}\r\n\r\nStepFileSelection.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n selectionTarget: PropTypes.string.isRequired,\r\n project: PropTypes.object,\r\n formData: PropTypes.object,\r\n onChangeFiles: PropTypes.func,\r\n onChangeCaseId: PropTypes.func,\r\n};\r\n\r\nexport default withStyles(styles)(StepFileSelection);\r\n","// Utils.jsx\r\n// This file contains utility functions for various purposes.\r\n\r\n// Copyright HS Analysis GmbH, 2022\r\n// Author: Valentin Haas\r\n\r\n//#region Type checks\r\n\r\n/**\r\n * Validate that a string follows the uuid format per RFC4122.\r\n * @param {string} inputString String to validate for uuid formatting.\r\n * @param {boolean} acceptNil Whether to accept NIL type UUID or not. Defaults to false\r\n * @returns {boolean} Whether the given string is a valid UUID.\r\n */\r\nexport function isUuid(inputString, acceptNil = false) {\r\n if (typeof inputString !== \"string\") return false;\r\n validateType(\"acceptNil\", acceptNil, ValidationType.Bool);\r\n\r\n const uuid =\r\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\r\n const uuid_w_nil =\r\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\r\n\r\n // Cheap length check\r\n if (inputString.length !== 36) return false;\r\n\r\n if (acceptNil) {\r\n return uuid_w_nil.test(inputString);\r\n } else {\r\n return uuid.test(inputString);\r\n }\r\n}\r\n\r\n/**\r\n * Check if a given string is a valid 3, 6, or 8 character hex color representation.\r\n * @param {string} inputString A string to test for valid color format.\r\n * @returns {bool} The given string is a valid hex color representation.\r\n */\r\nexport function isHexColor(inputString) {\r\n if (typeof inputString !== \"string\") return false;\r\n const hexColor = /^(#[\\da-f]{3}|#[\\da-f]{6}|#[\\da-f]{8})$/i;\r\n return hexColor.test(inputString);\r\n}\r\n\r\n/**\r\n * Checks if a value is a plain object.\r\n * @param {number} input Object to test.\r\n * @returns {boolean} Whether the given value resembles an object.\r\n */\r\nexport function isObject(obj) {\r\n return obj && typeof obj === \"object\" && !Array.isArray(obj);\r\n}\r\n\r\n/**\r\n * Checks if a value is an integer value.\r\n * @param {number} input Number to test.\r\n * @returns {boolean} Whether the given value resembles an integer.\r\n */\r\nexport function isInt(input) {\r\n if (typeof input === \"bigint\") return true; // BigInts are always ints\r\n if (typeof input !== \"number\") return false;\r\n\r\n return (input | 0) === input;\r\n}\r\n\r\n/**All possible validation types for the validateType function. */\r\nexport const ValidationType = Object.freeze({\r\n String: 0,\r\n Int: 1,\r\n Number: 2,\r\n Bool: 3,\r\n Array: 4,\r\n Object: 5,\r\n Function: 6,\r\n Undefined: 7,\r\n});\r\n\r\n/**\r\n * Validates if a value has the expected type and throws an useful error if not.\r\n * @param {string} variableName Name of the variable to validate.\r\n * @param {any} value Value to validata.\r\n * @param {ValidationType} type Expected type.\r\n * @throws {TypeError} If the value is not of the expected type.\r\n * @returns {void}\r\n * @example validateType(\"myVar\", myVar, ValidationType.String)\r\n */\r\nexport function validateType(variableName, value, type) {\r\n if (typeof variableName !== \"string\")\r\n throw TypeError(\r\n `variableName must be of type string, received ${typeof value}: ${value}`\r\n );\r\n validateInEnum(\"type\", type, ValidationType);\r\n\r\n switch (type) {\r\n case ValidationType.String:\r\n if (typeof value !== \"string\")\r\n throw TypeError(\r\n `${variableName} must be of type string, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Int:\r\n if (!isInt(value))\r\n throw TypeError(\r\n `${variableName} must be of type int, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Number:\r\n if (typeof value !== \"number\")\r\n throw TypeError(\r\n `${variableName} must be of type float, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Bool:\r\n if (typeof value !== \"boolean\")\r\n throw TypeError(\r\n `${variableName} must be of type boolean, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Array:\r\n if (!Array.isArray(value))\r\n throw TypeError(\r\n `${variableName} must be of type array, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Object:\r\n if (!isObject(value))\r\n throw TypeError(\r\n `${variableName} must be of type object, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Function:\r\n if (typeof value !== \"function\")\r\n throw TypeError(\r\n `${variableName} must be of type function, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n case ValidationType.Undefined:\r\n if (typeof value !== \"undefined\")\r\n throw TypeError(\r\n `${variableName} must be of type undefined, received ${typeof value}: ${value}`\r\n );\r\n break;\r\n default:\r\n throw TypeError(`Invalid type: ${type}`);\r\n }\r\n}\r\n\r\n/**\r\n * Validates if a value is of a given instance type and throws an useful error if not.\r\n * @param {string} variableName Name of the variable to validate.\r\n * @param {*} object Object to validate.\r\n * @param {function} instanceType Expected instance type.\r\n * @throws {TypeError} If the value is not of the expected instance type.\r\n * @returns {void}\r\n * @example validateInstance(\"myVar\", myVar, MyClass)\r\n */\r\nexport function validateInstance(variableName, object, instanceType) {\r\n if (!(object instanceof instanceType))\r\n throw TypeError(\r\n `${variableName} must be of type ${\r\n instanceType.name\r\n }, received ${typeof object}: ${object}`\r\n );\r\n}\r\n\r\n/**\r\n * Validates if a value is a valid enum value and throws an useful error if not.\r\n * @param {string} variableName Name of the variable to validate.\r\n * @param {*} value Value to validate.\r\n * @param {object} enumType Enum type to validate against.\r\n * @throws {TypeError} If the value is not a valid enum value.\r\n * @returns {void}\r\n * @example validateInEnum(\"myVar\", \"value\", MyEnum)\r\n */\r\nexport function validateInEnum(variableName, value, enumType) {\r\n if (!Object.values(enumType).includes(value))\r\n throw new TypeError(\r\n `${variableName} must be one of ${Object.values(\r\n enumType\r\n )}, received: ${value}`\r\n );\r\n}\r\n\r\n//#endregion\r\n\r\n//#region Conversions\r\n/**\r\n * Rounds a floating point number to specified decimals after the comma.\r\n * @param {number} num Number to round.\r\n * @param {int} decimals Decimals after the comma to round to. Defaults to 0.\r\n * @returns {number} Input rounded to specified decimal count.\r\n */\r\nexport function roundToDecimal(num, decimals = 0) {\r\n validateType(\"num\", num, ValidationType.Number);\r\n\r\n if (!isInt(decimals) || decimals < 0) {\r\n throw TypeError(\r\n `decimals must be an integer >= 0, received ${typeof decimals}: ${decimals}`\r\n );\r\n }\r\n\r\n return (\r\n Math.round((num + Number.EPSILON) * Math.pow(10, decimals)) /\r\n Math.pow(10, decimals)\r\n );\r\n}\r\n\r\n/**\r\n * Convert a byte to its two character, hexadecimal uppercase representation.\r\n * @param {byte} input Byte (between 0 and 255) to convert to 2-letter hex value.\r\n * @returns {string} The input converted to a two-character hex string.\r\n */\r\nexport function byteToHex(input) {\r\n if (!isInt(input) || input < 0 || input > 255) {\r\n throw TypeError(\r\n `input must be an integer >= 0, <= 255, received ${typeof input}: ${input}`\r\n );\r\n }\r\n return (\"0\" + Number(input).toString(16)).slice(-2).toUpperCase();\r\n}\r\n\r\n/**\r\n * Convert 3 individual RGB values to a hex color string.\r\n * @param {int} r Red value from 0 to 255.\r\n * @param {int} g Green value from 0 to 255.\r\n * @param {int} b Blue value from 0 to 255.\r\n * @returns {string | Error} Hex color string in the format '#RRGGBB'.\r\n */\r\nexport const rgbToHex = (r, g, b) => {\r\n validateType(\"r\", r, ValidationType.Int);\r\n validateType(\"g\", g, ValidationType.Int);\r\n validateType(\"b\", b, ValidationType.Int);\r\n\r\n const toHex = (c) => c.toString(16).padStart(2, \"0\");\r\n\r\n if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {\r\n throw new RangeError(\"Invalid color component\");\r\n }\r\n\r\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();\r\n};\r\n\r\n/**\r\n * Convert a rgba string to a hex string.\r\n * @param {string} rgbaString The rgba string to convert to hex string.\r\n * @returns {string} The hex string representation of the rgba string.\r\n */\r\nexport function rgbaToHex(rgbaString) {\r\n validateType(\"rgbaString\", rgbaString, ValidationType.String);\r\n\r\n let r, g, b, alpha;\r\n const parts = rgbaString\r\n .substring(rgbaString.indexOf(\"rgba(\") + 5, rgbaString.lastIndexOf(\")\"))\r\n .split(/,\\s*/);\r\n\r\n if (parts.length === 4) {\r\n [r, g, b, alpha] = parts;\r\n } else if (parts.length === 3) {\r\n [r, g, b] = parts;\r\n alpha = \"1\";\r\n } else {\r\n throw TypeError(`Invalid rgba string: ${rgbaString}`);\r\n }\r\n\r\n // Convert alpha value to hex\r\n alpha = parseFloat(alpha);\r\n if (alpha < 0 || alpha > 1) {\r\n throw RangeError(`Alpha value must be between 0 and 1, received: ${alpha}`);\r\n }\r\n const alphaHex =\r\n alpha == 1\r\n ? \"\"\r\n : Math.round(alpha * 255)\r\n .toString(16)\r\n .padStart(2, \"0\")\r\n .toUpperCase();\r\n\r\n // Convert RGB values to hex\r\n r = parseInt(r);\r\n g = parseInt(g);\r\n b = parseInt(b);\r\n\r\n if (r < 0 || r > 255) {\r\n throw RangeError(`Red value must be between 0 and 255, received: ${r}`);\r\n }\r\n if (g < 0 || g > 255) {\r\n throw RangeError(`Green value must be between 0 and 255, received: ${g}`);\r\n }\r\n if (b < 0 || b > 255) {\r\n throw RangeError(`Blue value must be between 0 and 255, received: ${b}`);\r\n }\r\n const rgbHex = ((1 << 24) + (r << 16) + (g << 8) + b)\r\n .toString(16)\r\n .slice(1)\r\n .toUpperCase();\r\n\r\n return `#${rgbHex}${alphaHex}`;\r\n}\r\n\r\nexport function hexToRgba(hex) {\r\n const regex = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})?$/i;\r\n const result = regex.exec(hex);\r\n\r\n if (!result) {\r\n return null;\r\n }\r\n\r\n const [, r, g, b, a] = result;\r\n\r\n return {\r\n r: parseInt(r, 16),\r\n g: parseInt(g, 16),\r\n b: parseInt(b, 16),\r\n a: a ? roundToDecimal(parseInt(a, 16) / 255, 2) : 1,\r\n };\r\n}\r\n\r\n/**\r\n * Converts all PascalCase keys of an object to camelCase.\r\n * @param {object} o Arbitrary object to convert keys to camel case.\r\n * @returns {object} The object with camel case keys.\r\n */\r\nexport function convertPascalCaseKeysToCamelCase(o) {\r\n let newO, origKey, newKey, value;\r\n if (o instanceof Array) {\r\n return o.map(function (value) {\r\n if (value !== null && typeof value === \"object\") {\r\n value = convertPascalCaseKeysToCamelCase(value);\r\n }\r\n return value;\r\n });\r\n } else {\r\n newO = {};\r\n for (origKey in o) {\r\n if (Object.prototype.hasOwnProperty.call(o, origKey)) {\r\n newKey = (\r\n origKey.charAt(0).toLowerCase() + origKey.slice(1) || origKey\r\n ).toString();\r\n value = o[origKey];\r\n if (\r\n value instanceof Array ||\r\n (value !== null && value.constructor === Object)\r\n ) {\r\n value = convertPascalCaseKeysToCamelCase(value);\r\n }\r\n newO[newKey] = value;\r\n }\r\n }\r\n }\r\n return newO;\r\n}\r\n\r\n/**\r\n * Converts all snake_case keys of an object to camelCase.\r\n * @param {object} o Arbitrary object to convert keys to camel case.\r\n * @returns {object} The object with camel case keys.\r\n */\r\nexport function convertSnakeCaseKeysToCamelCase(o) {\r\n let newO, origKey, newKey, value;\r\n if (o instanceof Array) {\r\n return o.map(function (value) {\r\n if (value !== null && typeof value === \"object\") {\r\n value = convertSnakeCaseKeysToCamelCase(value);\r\n }\r\n return value;\r\n });\r\n } else {\r\n newO = {};\r\n for (origKey in o) {\r\n if (Object.prototype.hasOwnProperty.call(o, origKey)) {\r\n newKey = (\r\n origKey.replace(/([-_][a-z])/g, (group) =>\r\n group.toUpperCase().replace(\"-\", \"\").replace(\"_\", \"\")\r\n ) || origKey\r\n ).toString();\r\n value = o[origKey];\r\n if (\r\n value instanceof Array ||\r\n (value !== null && value.constructor === Object)\r\n ) {\r\n value = convertSnakeCaseKeysToCamelCase(value);\r\n }\r\n newO[newKey] = value;\r\n }\r\n }\r\n }\r\n return newO;\r\n}\r\n//#endregion\r\n\r\n//#region Mathemathics\r\n/**\r\n * Counts number of decimals of a number, up to a maximum of 16.\r\n * Will ignore trailing zeros.\r\n * @param {Number} x Number to count decimals of.\r\n * @returns {Number} Number of decimals.\r\n */\r\nexport function countDecimals(x) {\r\n validateType(\"x\", x, ValidationType.Number);\r\n if (x === Math.floor(x)) return 0;\r\n return x.toString().split(\".\")[1].length ?? 0;\r\n}\r\n\r\n/**\r\n * Given an index and the total number of entries, return the log-scaled value.\r\n * @param {int} idx Index of all numbers to take logarithm of.\r\n * @param {int} total Total number of indicies.\r\n * @param {number} base Optional. Base of logarithm. Defaults to 10.\r\n * @returns\r\n */\r\nexport function logScale(idx, total, base = 10) {\r\n const logmax = logBase(total + 1, base);\r\n const exp = (logmax * idx) / total;\r\n return Math.round(Math.pow(base, exp) - 1);\r\n}\r\n\r\n/**\r\n * Takes the logarithm of a number to a given base.\r\n * @param {number} val Value to calculate logarithm for.\r\n * @param {number} base Base to take logarithem to.\r\n * @returns {number} log_base(val)\r\n */\r\nexport function logBase(val, base) {\r\n return Math.log(val) / Math.log(base);\r\n}\r\n//#endregion\r\n\r\n//#region Strings\r\n/**\r\n * Shortens a string to a maximum length and inserts \"...\" in the middle.\r\n * Will prefer the end of a string by one character over the start.\r\n * When the maximum length is less than 4, only the first character is shown.\r\n * @param {string} str The string to shorten.\r\n * @param {int} maxLength The maximum length of the string.\r\n * @returns {string} The shortened string.\r\n */\r\nexport function shortenString(str, maxLength) {\r\n validateType(\"str\", str, ValidationType.String);\r\n validateType(\"maxLength\", maxLength, ValidationType.Int);\r\n if (maxLength < 4)\r\n throw RangeError(`maxLength must be > 3, received: ${maxLength}`);\r\n\r\n // If the string is already shorter than the maximum length, return it as is\r\n if (str.length <= maxLength) return str;\r\n\r\n // If the maximum length is less than 5, only show the first character.\r\n if (maxLength == 4) return str.slice(0, 1) + \"...\";\r\n\r\n // Shorten the string and insert \"...\" in the middle\r\n const startIdx = Math.floor((maxLength - 3) / 2);\r\n const endIdx = -Math.ceil((maxLength - 3) / 2);\r\n return str.slice(0, startIdx) + \"...\" + str.slice(endIdx);\r\n}\r\n//#endregion\r\n\r\n//#region Other\r\n/**\r\n * Get the viewer defining url path from a project type in the format \"/path/\".\r\n * @param {string} projectType Name of the project type.\r\n * @returns {string} Viewer defining path for URL.\r\n */\r\nexport function viewerType(projectType) {\r\n validateType(\"projectType\", projectType, ValidationType.String);\r\n projectType = projectType.toLowerCase();\r\n // Spectra Viewer\r\n if (\r\n projectType.includes(\"esrtraining\") ||\r\n projectType.includes(\"esrevaluation\")\r\n ) {\r\n return \"/esr_view/\";\r\n }\r\n // Proteome Viewer\r\n else if (projectType.includes(\"proteomeanalysis\")) {\r\n return \"/proteome_view/\";\r\n }\r\n // Audio Viewer\r\n else if (projectType.includes(\"audioannotator\")) {\r\n return \"/audio_view/\";\r\n }\r\n // Image Viewer\r\n else {\r\n return \"/view/\";\r\n }\r\n}\r\n\r\n/**\r\n * Download a json object as a file with a given name.\r\n * @param {JSON} jsonObject The JSON object to save.\r\n * @param {string} downloadName Optional. How the file will be called once downloaded.\r\n * Needs not end in .json. Defaults to export.json.\r\n */\r\nexport function downloadJsonObjectAsFile(\r\n jsonObject,\r\n downloadName = \"export.json\"\r\n) {\r\n validateType(\"jsonObject\", jsonObject, ValidationType.Object);\r\n validateType(\"downloadName\", downloadName, ValidationType.String);\r\n if (downloadName.length <= 0)\r\n throw RangeError(\r\n `downloadName must not be empty, received: ${downloadName}`\r\n );\r\n\r\n let dataStr =\r\n \"data:text/json;charset=utf-8,\" +\r\n encodeURIComponent(JSON.stringify(jsonObject));\r\n\r\n let dlAnchorElem = document.createElement(\"a\");\r\n dlAnchorElem.setAttribute(\"href\", dataStr);\r\n dlAnchorElem.setAttribute(\"download\", downloadName);\r\n dlAnchorElem.click();\r\n dlAnchorElem.remove();\r\n}\r\n\r\n/**\r\n * Download an array as a file with a given name.\r\n * @param {array} arrayIn The array to save.\r\n * @param {string} downloadName Optional. How the file will be called once downloaded.\r\n * Needs not end in .json. Defaults to export.json.\r\n */\r\nexport function downloadArrayAsFile(arrayIn, downloadName = \"export.json\") {\r\n validateType(\"arrayIn\", arrayIn, ValidationType.Array);\r\n validateType(\"downloadName\", downloadName, ValidationType.String);\r\n if (downloadName.length <= 0)\r\n throw RangeError(\r\n `downloadName must not be empty, received: ${downloadName}`\r\n );\r\n\r\n const dataStr =\r\n \"data:text/json;charset=utf-8,\" +\r\n encodeURIComponent(JSON.stringify(arrayIn));\r\n\r\n const dlAnchorElem = document.createElement(\"a\");\r\n dlAnchorElem.setAttribute(\"href\", dataStr);\r\n dlAnchorElem.setAttribute(\"download\", downloadName);\r\n dlAnchorElem.click();\r\n dlAnchorElem.remove();\r\n}\r\n\r\n/**\r\n * Creates pop-up window to import a file via http input field.\r\n * @param {Array} acceptedFileTypes Strings of file endings allowed to import (including the dot, e.g. .json).\r\n * @returns {Promise} The files to import.\r\n */\r\nexport async function requestFileInput(acceptedFileTypes) {\r\n if (!Array.isArray(acceptedFileTypes))\r\n throw TypeError(\r\n `acceptedFileTypes must be an Array, received ${typeof acceptedFileTypes}: ${acceptedFileTypes}`\r\n );\r\n\r\n return new Promise((resolve) => {\r\n // Import window\r\n const inputElem = document.createElement(\"INPUT\");\r\n inputElem.setAttribute(\"type\", \"file\");\r\n inputElem.setAttribute(\"onChange\", \"file\");\r\n inputElem.setAttribute(\"accept\", acceptedFileTypes);\r\n inputElem.onchange = (e) => resolve(e.target.files);\r\n inputElem.click();\r\n inputElem.remove();\r\n });\r\n}\r\n\r\n/**\r\n * Shuffles array in place using Fisher-Yates algorithm.\r\n * @param {Array} a An array containing items to be shuffled.\r\n * @returns {Array} The shuffled array\r\n */\r\nexport function shuffle(a) {\r\n validateType(\"a\", a, ValidationType.Array);\r\n\r\n for (let i = a.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1));\r\n [a[i], a[j]] = [a[j], a[i]];\r\n }\r\n return a;\r\n}\r\n\r\n/**\r\n * if there were no new calls of this function for the delay time, the newest func will be triggered\r\n * @param {function} func callback function\r\n * @param {int} delay in ms\r\n * @returns\r\n */\r\nexport function debounce(fn, delay) {\r\n let timeoutId;\r\n return function (...args) {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n timeoutId = setTimeout(() => {\r\n fn(...args);\r\n }, delay);\r\n };\r\n}\r\n\r\n/**\r\n * Determines if a given color is light or dark.\r\n * @param {string} color - The hex code of the color to check.\r\n * @returns {boolean} True if the color is light, false if it is dark.\r\n */\r\nexport function isColorLight(color) {\r\n // Convert the color to RGB\r\n const rgba = hexToRgba(color);\r\n\r\n // If the color is light because of transparence, return true imeediately\r\n if (rgba.a < 0.5) return true;\r\n\r\n // Calculate the luminance using the formula for relative luminance defined in WCAG 2.0\r\n const luminance = 0.2126 * rgba.r + 0.7152 * rgba.g + 0.0722 * rgba.b;\r\n\r\n // Set the threshold for light colors\r\n const threshold = 186;\r\n\r\n // Return true if the luminance is greater than the threshold for light colors\r\n return luminance > threshold;\r\n}\r\n//#endregion\r\n","// Copyright HS Analysis GmbH, 2023\r\n// Author: Valentin Haas\r\n\r\n// Description: Standardized Roi Types for HSA KIT.\r\n// For ROI documentation see https://hsa.atlassian.net/wiki/spaces/HSAKIT/pages/16116235173917/Annotations+Data+Structure\r\n\r\n// Keep in sync with C# and js frontend:\r\n// Source\\HSA-KIT\\Database\\Model\\RoiTypes.cs\r\n// Source\\HSA-KIT\\ClientApp\\src\\common\\components\\RoiTypes.jsx\r\n// Source\\HSA-KIT\\modules\\hsa\\core\\models\\roi_types.py\r\n\r\n// External packages\r\nimport { v4 as uuidv4 } from \"uuid\";\r\nimport { bbox, bboxPolygon } from \"@turf/turf\";\r\n\r\n// HSA imports\r\nimport Backend from \"../utils/Backend\";\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n downloadJsonObjectAsFile,\r\n isUuid,\r\n validateInEnum,\r\n validateInstance,\r\n validateType,\r\n ValidationType,\r\n} from \"../utils/Utils\";\r\nimport { convertDateToShortIsoString } from \"../../common/utils/Localization\";\r\nimport { calcBoundingBoxFullObject } from \"../../viewer/utils/PolygonUtil\";\r\nimport Structure from \"./Structure\";\r\n\r\n//#region DataType Enumerators\r\n/**\r\n * Limits and describes possible modification statuses.\r\n */\r\nexport const ModificationStatus = Object.freeze({\r\n // Must be updated together with backend\r\n Saved: 0,\r\n Added: 1,\r\n Deleted: 2,\r\n});\r\n\r\n/**\r\n * Limits and describes annotation types.\r\n */\r\nexport const RoiType = Object.freeze({\r\n // Must be updated together with backend\r\n ImageRoi: 0,\r\n AudioRoi: 1,\r\n});\r\n\r\n/**\r\n * Limits and decribes possible image annotation types statuses.\r\n */\r\nexport const ImageAnnotationType = Object.freeze({\r\n // Must be updated together with backend\r\n Area: 0,\r\n Object: 1,\r\n Comments: 2,\r\n});\r\n\r\n/**\r\n * Implemented actions concerning annotations to be executed.\r\n */\r\nexport const AnnotationAction = Object.freeze({\r\n // Must be updated together with backend\r\n Save: 0,\r\n Export: 1,\r\n Import: 2,\r\n DeleteAll: 3,\r\n});\r\n//#endregion\r\n\r\n//#region Roi Actions\r\n\r\n/**\r\n * Save all passed rois to database.\r\n * Update rois in frontend based on response from backend.\r\n * @param {uuid} projectId Project id to save annotations for.\r\n * @param {object} file File to save annotations for.\r\n * @param {Structure} structure Structure to save annotations for.\r\n * @param {RoiType} annotationType Type of rois to save.\r\n * @param {array} annotations Annotations to save.\r\n * @param {function} callback Optional: Always execute after receiving and processing save response. Receives (array: newAnnotations).\r\n * @param {function} error Optional: Execute on error. Receives (object: error, array: newAnnotations).\r\n */\r\nexport function saveAnnotations(\r\n projectId,\r\n file,\r\n structure,\r\n annotationType,\r\n annotations,\r\n callback = () => {},\r\n error = () => {}\r\n) {\r\n // Input validation\r\n if (!isUuid(projectId)) {\r\n throw TypeError(\r\n `projectId must be a valid UUID, received ${typeof projectId}: ${projectId}`\r\n );\r\n }\r\n\r\n validateType(\"file\", file, ValidationType.Object);\r\n validateInstance(\"structure\", structure, Structure);\r\n validateInEnum(\"annotationType\", annotationType, RoiType);\r\n validateType(\"annotations\", annotations, ValidationType.Array);\r\n\r\n // Stringify individual geojson regions\r\n if (annotationType === RoiType.ImageRoi) {\r\n annotations.forEach((a) => {\r\n a.coordinates = JSON.stringify(a.coordinates);\r\n });\r\n } else if (annotationType === RoiType.AudioRoi) {\r\n annotations.forEach((a) => {\r\n a.polyRep = JSON.stringify(a.polyRep);\r\n });\r\n }\r\n\r\n // Save annotations to database\r\n Backend.saveAnnotationsToDb(\r\n projectId,\r\n RoiType.AudioRoi,\r\n annotations,\r\n (data) => {\r\n // Read potentially updated roi ids.\r\n let oldIds = [];\r\n let newIds = [];\r\n\r\n data.roiUpdate.reassignedIds.forEach((idTuple) => {\r\n oldIds.push(idTuple[0]);\r\n newIds.push(idTuple[1]);\r\n });\r\n\r\n annotations = annotations.map((a) => {\r\n // Mirror potentially updated roi ids.\r\n if (oldIds.includes(a.id)) {\r\n a.id = newIds[oldIds.indexOf(a.id)];\r\n }\r\n\r\n // Everything was successfull -> Mark all annotations as saved.\r\n switch (a.modificationStatus) {\r\n case ModificationStatus.Saved:\r\n return a;\r\n\r\n case ModificationStatus.Added:\r\n a.modificationStatus = ModificationStatus.Saved;\r\n return a;\r\n\r\n case ModificationStatus.Deleted:\r\n // Exclude successfully deleted rois.\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n });\r\n\r\n // Remove undefineds\r\n annotations = annotations.filter((a) => a);\r\n console.debug(\r\n `Saved annotations for file \"${file.fileName}\", structure ${structure.label}: ${data.success}`\r\n );\r\n callback(annotations);\r\n },\r\n (err) => {\r\n // Some annotations failed to save to database.\r\n if (err.warning) {\r\n let oldIds = [];\r\n let newIds = [];\r\n\r\n // Read potentially updated roi ids.\r\n err.roiUpdate.reassignedIds.forEach((idTuple) => {\r\n oldIds.push(idTuple[0]);\r\n newIds.push(idTuple[1]);\r\n });\r\n\r\n annotations = annotations.map((a) => {\r\n // Mirror potentially updated roi ids.\r\n if (oldIds.includes(a.id)) {\r\n a.id = newIds[oldIds.indexOf(a.id)];\r\n }\r\n\r\n if (a.modificationStatus === ModificationStatus.Saved) {\r\n return a;\r\n }\r\n // Keep unsuccessfully added or unsuccessfully deleted rois unchanged\r\n else if (\r\n err.roiUpdate.failedToAdd.includes(a.id) ||\r\n err.roiUpdate.failedToDelete.includes(a.id)\r\n ) {\r\n return a;\r\n }\r\n // Set successfully added rois as saved.\r\n else if (a.modificationStatus === ModificationStatus.Added) {\r\n a.modificationStatus = ModificationStatus.Saved;\r\n return a;\r\n }\r\n // Exclude successfully deleted rois.\r\n });\r\n\r\n // Remove undefineds\r\n annotations = annotations.filter((a) => a);\r\n\r\n window.showWarningSnackbar(err.warning);\r\n console.debug(err);\r\n error(err, annotations);\r\n }\r\n // The save process went wrong somewhere\r\n else if (err.error) {\r\n window.showErrorSnackbar(\r\n `Error saving annotations of file \"${file.fileName}\", structure ${structure.label}:\\n${err.error}`\r\n );\r\n error(err);\r\n }\r\n // Good luck\r\n else {\r\n window.showErrorSnackbar(\r\n `Unkonwn error saving annotations of file \"${file.fileName}\", structure ${structure.label}\"`\r\n );\r\n error(err);\r\n }\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Export all annotations in frontend to .annhsa file.\r\n * Triggers download of the .annhsa file.\r\n * @param {string} username Name of the user exporting the annotations.\r\n * @param {object} project Origin project of the rois.\r\n * @param {object} file File corresponding to the rois.\r\n * @param {Structure} structure Structure corresponding to the rois.\r\n * @param {RoiType} annotationType Type of rois to save.\r\n * @param {array} annotations All annotations.\r\n * @return {object} Success status of export.\r\n */\r\nexport function exportAnnotations(\r\n username,\r\n project,\r\n file,\r\n structure,\r\n annotationType,\r\n annotations\r\n) {\r\n // Input validation\r\n validateType(\"username\", username, ValidationType.String);\r\n validateType(\"project\", project, ValidationType.Object);\r\n validateType(\"file\", file, ValidationType.Object);\r\n validateInstance(\"structure\", structure, Structure);\r\n validateInEnum(\"annotationType\", annotationType, RoiType);\r\n validateType(\"annotations\", annotations, ValidationType.Array);\r\n\r\n try {\r\n // Export rois with meta info\r\n const timestamp = convertDateToShortIsoString(Date.now());\r\n downloadJsonObjectAsFile(\r\n {\r\n version: 1.0,\r\n timestamp: timestamp,\r\n user: username,\r\n project: project,\r\n file: {\r\n id: file.id,\r\n label: file.fileName,\r\n },\r\n structure: {\r\n id: structure.id,\r\n label: structure.label,\r\n isStructure: structure.isStructure,\r\n },\r\n annotationType: annotationType,\r\n annotations: annotations,\r\n },\r\n `${timestamp}_${project.name}_${file.fileName}_${structure.label}_(${annotations.length})_${username}.annhsa`\r\n );\r\n\r\n return {\r\n success: true,\r\n msg: `Successfully exported ${annotations.length} annotations of structure ${structure.label}`,\r\n };\r\n } catch (err) {\r\n return {\r\n success: false,\r\n msg: `Failed to export ${annotations.length} annotations of structure ${structure.label}`,\r\n error: err,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Open a file selection window and import annotations from selected file to frontend.\r\n * Deletes all previous annotations.\r\n * @param {RoiType} annotationType The expected annotation type.\r\n * @param {array} existingAnnotations The previously exisiting annotations. Will all be set as to delete.\r\n * @param {object} file File corresponding to the rois.\r\n * @param {Structure} structure Structure corresponding to the rois.\r\n * @param {function} callback Always executes after loading and processing annotations. Receives (array: annotations).\r\n * @param {function} error Optional: Execute on error. Receives (object: error).\r\n */\r\nexport async function importAnnotations(\r\n annotationType,\r\n existingAnnotations,\r\n file,\r\n structure,\r\n callback,\r\n error = () => {}\r\n) {\r\n // Input validation\r\n validateInEnum(\"annotationType\", annotationType, RoiType);\r\n validateType(\r\n \"existingAnnotations\",\r\n existingAnnotations,\r\n ValidationType.Array\r\n );\r\n validateType(\"file\", file, ValidationType.Object);\r\n validateInstance(\"structure\", structure, Structure);\r\n\r\n // Warn about unsaved existing annotations\r\n const unsaved = existingAnnotations.filter(\r\n (a) => a.modificationStatus !== ModificationStatus.Saved\r\n ).length;\r\n if (unsaved > 0) {\r\n const continueImport = await window.openConfirmationDialog(\r\n \"Unsaved annotations\",\r\n `You have ${unsaved} unsaved modified ${\r\n unsaved === 1 ? \"annotation\" : \"annotations\"\r\n } in the structure \"${structure.label}\". \r\n An import will irreversibly remove all unsaved annotations. \r\n Import anyway?`\r\n );\r\n if (!continueImport) return;\r\n }\r\n\r\n // Import window\r\n const inputElem = document.createElement(\"INPUT\");\r\n inputElem.setAttribute(\"type\", \"file\");\r\n inputElem.setAttribute(\"onChange\", \"file\");\r\n inputElem.setAttribute(\"accept\", \".annhsa\");\r\n inputElem.onchange = (e) => {\r\n // Analyse the incoming file, abort on no file.\r\n let files = e.target.files;\r\n if (files.length <= 0) return;\r\n\r\n let fr = new FileReader();\r\n fr.onload = async (e) => {\r\n try {\r\n const data = JSON.parse(e.target.result);\r\n // Data validation checks\r\n // TODO: Refactor into some kind of async .then functions\r\n if (data.annotationType !== annotationType) {\r\n throw TypeError(\r\n `Annotation type mismatch: was expecting \"${annotationType}\", imported file is of type \"${data.annotationType}\"`\r\n );\r\n }\r\n\r\n // Warn about file change\r\n if (data.file.id !== file.id && data.file.label !== file.fileName) {\r\n const continueImport = await window.openConfirmationDialog(\r\n \"File Mismatch\",\r\n `The annotations were created for a different file:\\n\"${data.file.label}\". \r\n You are attempting to import it to the file:\\n\"${file.fileName}\". \r\n An import will remove all existing annotations. \r\n Import anyway?`\r\n );\r\n if (!continueImport) return;\r\n }\r\n\r\n // Warn about structure change\r\n if (\r\n data.structure.id !== structure.id &&\r\n data.structure.label !== structure.label\r\n ) {\r\n const continueImport = await window.openConfirmationDialog(\r\n \"Structure Mismatch\",\r\n `The annotations were created for a different structure: \"${data.structure.label}\". \r\n You are attempting to import it to the structure: \"${structure.label}\". \r\n An import will remove all existing annotations. \r\n Import anyway?`\r\n );\r\n if (!continueImport) return;\r\n }\r\n\r\n // Warn about 0-length imported annotations\r\n if (data.annotations.length === 0) {\r\n const continueImport = await window.openConfirmationDialog(\r\n \"No annotatations to import\",\r\n `There are no annotations included in uploaded file. \r\n An import will remove all existing annotations. \r\n Import anyway?`\r\n );\r\n if (!continueImport) return;\r\n }\r\n\r\n const importedAnnotations = [];\r\n switch (annotationType) {\r\n case RoiType.ImageRoi:\r\n data.annotations.forEach((a) =>\r\n importedAnnotations.push(\r\n new ImageRoi(\r\n uuidv4(),\r\n file.id,\r\n structure.id,\r\n a.isAiAnnotated,\r\n a.user,\r\n ModificationStatus.Added,\r\n a.z,\r\n a.t,\r\n a.coordinates,\r\n a.annotationType,\r\n a.minX,\r\n a.minY,\r\n a.maxX,\r\n a.maxY\r\n )\r\n )\r\n );\r\n break;\r\n\r\n case RoiType.AudioRoi:\r\n data.annotations.forEach((a) =>\r\n importedAnnotations.push(\r\n new AudioRoi(\r\n uuidv4(),\r\n file.id,\r\n structure.id,\r\n a.isAiAnnotated,\r\n a.user,\r\n ModificationStatus.Added,\r\n a.channels,\r\n a.startTime,\r\n a.endTime,\r\n a.minFreq,\r\n a.maxFreq,\r\n a.polyRep\r\n )\r\n )\r\n );\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n\r\n // Set all existing annotations as deleted\r\n existingAnnotations.forEach(\r\n (anno) => (anno.modificationStatus = ModificationStatus.Deleted)\r\n );\r\n\r\n callback([...existingAnnotations, ...importedAnnotations]);\r\n } catch (err) {\r\n const errmsg = `Failed to import the annotations of type ${annotationType} from file ${files[0].name}:\\n${err}`;\r\n console.debug(errmsg);\r\n error(errmsg);\r\n }\r\n };\r\n // Only accept the first element\r\n fr.readAsText(files.item(0));\r\n };\r\n inputElem.click();\r\n inputElem.remove();\r\n}\r\n\r\n/**\r\n * After a confirming prompt, delete all annotations of a structure in frontend.\r\n * @param {array} existingAnnotations The previously exisiting annotations. Will all be set as to delete.\r\n * @param {Structure} structure Structure corresponding to the rois.\r\n * @param {function} callback Save updated annotations after modfication. Receives (array: annotations).\r\n * @param {bool} forceDelete Optional. Delete all annotations with out asking user first. Defaults to false.\r\n */\r\nexport async function deleteAllAnnotations(\r\n existingAnnotations,\r\n structure,\r\n callback,\r\n forceDelete = false\r\n) {\r\n // Input validation\r\n validateType(\r\n \"existingAnnotations\",\r\n existingAnnotations,\r\n ValidationType.Array\r\n );\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"forceDelete\", forceDelete, ValidationType.Bool);\r\n\r\n const continueDeletion =\r\n forceDelete ||\r\n (await window.openConfirmationDialog(\r\n \"Delete all Annotations\",\r\n `This action will delete all annotations of the structure \"${structure.label}\". Proceed?`\r\n ));\r\n if (!continueDeletion) return;\r\n\r\n const updatedAnnotations = existingAnnotations.map((a) => {\r\n a.modificationStatus = ModificationStatus.Deleted;\r\n return a;\r\n });\r\n\r\n callback(updatedAnnotations);\r\n}\r\n\r\n//#endregion\r\n\r\n//#region General Roi definitions\r\n/**\r\n * Basic information every type of region of interest (ROI) must contain.\r\n */\r\nclass Roi {\r\n // Must be updated together with backend\r\n /**\r\n * Create a ROI object with all parameters.\r\n * @param {Guid} id Id of the ROI.\r\n * @param {Guid} fileId Id of the associated scene.\r\n * @param {uint} structure Id of associated structure.\r\n * @param {bool} isAiAnnotated Whether or not this annotation is AI generated.\r\n * @param {ModificationStatus} modificationStatus Status of modification of any single annotation.\r\n * @param {Guid} user User that created this annotation.\r\n */\r\n constructor(\r\n id,\r\n fileId,\r\n structure,\r\n isAiAnnotated,\r\n modificationStatus = ModificationStatus.Added,\r\n user\r\n ) {\r\n // Input validation\r\n if (!isUuid(id)) {\r\n throw TypeError(\r\n `id must be a non-nil UUID, received ${typeof id}: ${id}`\r\n );\r\n }\r\n if (!isUuid(fileId)) {\r\n throw TypeError(\r\n `fileId must be a non-nil UUID, received ${typeof fileId}: ${fileId}`\r\n );\r\n }\r\n validateType(\"structure\", structure, ValidationType.Int);\r\n if (structure < 0) {\r\n throw RangeError(\r\n `structure must be an integer >= 0, received ${typeof structure}: ${structure}`\r\n );\r\n }\r\n validateType(\"isAiAnnotated\", isAiAnnotated, ValidationType.Bool);\r\n validateInEnum(\r\n \"modificationStatus\",\r\n modificationStatus,\r\n ModificationStatus\r\n );\r\n if (!isUuid(user)) {\r\n throw TypeError(\r\n `user must be a non-nil UUID, received ${typeof user}: ${user}`\r\n );\r\n }\r\n\r\n // Value assignment\r\n this.id = id;\r\n this.fileId = fileId;\r\n this.structure = structure;\r\n this.isAiAnnotated = isAiAnnotated;\r\n this.modificationStatus = modificationStatus;\r\n this.user = user;\r\n }\r\n}\r\n//#endregion\r\n\r\n//#region ImageRois\r\n/**\r\n * A ROI in an image or video, whose coordinates comply with the GeoJSON standard.\r\n */\r\nexport class ImageRoi extends Roi {\r\n // Must be updated together with backend\r\n /**\r\n * Create an ImageRoi object with all parameters.\r\n * @param {Guid} id Id of the ROI.\r\n * @param {Guid} fileId Id of the associated scene.\r\n * @param {Structure} structure Associated strucuture.\r\n * @param {bool} isAiAnnotated Whether or not this annotation is AI generated.\r\n * @param {ModificationStatus} modificationStatus Status of modification of any single annotation. 0: Saved to DB, 1: Added or modified, 2: Deleted\r\n * @param {Guid} user User that created this annotation.\r\n * @param {number} z Z-Layer in a z-Stack image.\r\n * @param {number} t Timeframe in a video.\r\n * @param {Array | string} coordinates The coordinates of the polygon, complies with the GeoJSON format. Can be passed as string, will be converted to json.\r\n * @param {ImageAnnotationType} annotationType Defines the type of annotations.\r\n * @param {number} minX Optional. Minimum X value of the polygon bounding box.\r\n * @param {number} minY Optional. Minimum Y value of the polygon bounding box.\r\n * @param {number} maxX Optional. Maximum X value of the polygon bounding box.\r\n * @param {number} maxY Optional. Maximum Y value of the polygon bounding box.\r\n */\r\n constructor(\r\n id,\r\n fileId,\r\n structure,\r\n isAiAnnotated,\r\n user,\r\n modificationStatus,\r\n z,\r\n t,\r\n coordinates,\r\n annotationType,\r\n minX,\r\n minY,\r\n maxX,\r\n maxY\r\n ) {\r\n super(id, fileId, structure, isAiAnnotated, modificationStatus, user);\r\n\r\n // Input validation\r\n validateType(\"z\", z, ValidationType.Int);\r\n if (z < 0) {\r\n throw RangeError(`z must be an integer >= 0, received ${typeof z}: ${z}`);\r\n }\r\n\r\n validateType(\"t\", t, ValidationType.Int);\r\n if (t < 0) {\r\n throw RangeError(`t must be an integer >= 0, received ${typeof t}: ${t}`);\r\n }\r\n\r\n if (!Array.isArray(coordinates) && typeof coordinates !== \"string\") {\r\n throw TypeError(\r\n `Invalid coordinates, received ${typeof coordinates}: ${coordinates}`\r\n );\r\n }\r\n\r\n validateInEnum(\"annotationType\", annotationType, ImageAnnotationType);\r\n validateType(\"minX\", minX, ValidationType.Number);\r\n validateType(\"minY\", minY, ValidationType.Number);\r\n validateType(\"maxX\", maxX, ValidationType.Number);\r\n validateType(\"maxY\", maxY, ValidationType.Number);\r\n\r\n // Value assignment\r\n this.z = z;\r\n this.t = t;\r\n this.coordinates =\r\n typeof coordinates === \"string\" ? JSON.parse(coordinates) : coordinates;\r\n this.annotationType = annotationType;\r\n\r\n // Should the values not be passed on, they must be calculated.\r\n if (minX && minY && maxX && maxY) {\r\n this.minX = minX;\r\n this.minY = minY;\r\n this.maxX = maxX;\r\n this.maxY = maxY;\r\n } else {\r\n // Calculate bounding box\r\n let rect = calcBoundingBoxFullObject(this.coordinates);\r\n // Assuming coordinate origin in top left corner\r\n // . -- x -->\r\n // |\r\n // y\r\n // |\r\n // V\r\n this.minX = rect.left;\r\n this.minY = rect.top;\r\n this.maxX = rect.right;\r\n this.maxY = rect.bottom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an item that can be added to rTree or rBush.\r\n * Prevents the need to manually define such a tree item every time.\r\n * @returns Treeitem with bounding box and reference to roi.\r\n */\r\n getTreeItem() {\r\n return {\r\n minX: this.minX,\r\n minY: this.minY,\r\n maxX: this.maxX,\r\n maxY: this.maxY,\r\n roi: this,\r\n };\r\n }\r\n\r\n /**\r\n * Create a new ImageRoi from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per ImageRoi constructor.\r\n * @param {object} obj An object containing all necessary properties of a ImageRoi.\r\n * @returns {ImageRoi} A new ImageRoi.\r\n */\r\n static fromObject = (obj) => {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new ImageRoi(\r\n obj.id,\r\n obj.fileId,\r\n obj.structure,\r\n obj.isAiAnnotated,\r\n obj.user,\r\n obj.modificationStatus,\r\n obj.z,\r\n obj.t,\r\n obj.coordinates,\r\n obj.annotationType,\r\n obj.minX,\r\n obj.minY,\r\n obj.maxX,\r\n obj.maxY\r\n );\r\n };\r\n}\r\n//#endregion\r\n\r\n//#region AudioRois\r\nexport class AudioRoi extends Roi {\r\n // Must be updated together with backend\r\n /**\r\n * Create a AudioRoi object with all parameters.\r\n * @param {Guid} id Id of the ROI.\r\n * @param {Guid} fileId Id of the associated scene.\r\n * @param {Structure} structure Associated structure.\r\n * @param {bool} isAiAnnotated Whether or not this annotation is AI generated.\r\n * @param {Guid} user User that created this annotation.\r\n * @param {ModificationStatus} modificationStatus Status of modification of any single annotation.\r\n * @param {array} channels All channels the annotation is present in.\r\n * @param {number} startTime Timestamp of annotation beginning in seconds.\r\n * @param {number} endTime Timestamp of annotation end in seconds.\r\n * @param {number} minFreq Minimum frequency of annotation in Hertz.\r\n * @param {number} maxFreq Maximum frequency of annotation in Hertz.\r\n * @param {array} polyRep Optional. Polygon representation of the annotation. If not passed, will be calculated from startTime, endTime, minFreq and maxFreq. Defaults to null.\r\n */\r\n constructor(\r\n id,\r\n fileId,\r\n structure,\r\n isAiAnnotated,\r\n user,\r\n modificationStatus,\r\n channels,\r\n startTime,\r\n endTime,\r\n minFreq,\r\n maxFreq,\r\n polyRep = null\r\n ) {\r\n super(id, fileId, structure, isAiAnnotated, modificationStatus, user);\r\n\r\n // Input validation\r\n validateType(\"channels\", channels, ValidationType.Array);\r\n channels.forEach((c) => {\r\n validateType(\"channel\", c, ValidationType.Int);\r\n });\r\n\r\n validateType(\"startTime\", startTime, ValidationType.Number);\r\n if (startTime < 0) {\r\n throw RangeError(\r\n `startTime must be a number >= 0, received ${typeof startTime}: ${startTime}`\r\n );\r\n }\r\n\r\n validateType(\"endTime\", endTime, ValidationType.Number);\r\n if (endTime < 0) {\r\n throw RangeError(\r\n `endTime must be a number >= 0, received ${typeof endTime}: ${endTime}`\r\n );\r\n }\r\n\r\n validateType(\"minFreq\", minFreq, ValidationType.Number);\r\n if (minFreq < 0) {\r\n throw RangeError(\r\n `minFreq must be a number >= 0, received ${typeof minFreq}: ${minFreq}`\r\n );\r\n }\r\n\r\n validateType(\"maxFreq\", maxFreq, ValidationType.Number);\r\n if (maxFreq < 0) {\r\n throw RangeError(\r\n `maxFreq must be a number >= 0, received ${typeof maxFreq}: ${maxFreq}`\r\n );\r\n }\r\n\r\n // Value assignments\r\n this.channels = channels;\r\n\r\n // Parse stringified polyRep\r\n while (typeof polyRep === \"string\") {\r\n polyRep = JSON.parse(polyRep);\r\n }\r\n\r\n // If polyRep is passed, use it, otherwise calculate it from startTime, endTime, minFreq and maxFreq\r\n if (polyRep != null) {\r\n this.polyRep = polyRep;\r\n } else {\r\n if (\r\n startTime === undefined ||\r\n endTime === undefined ||\r\n minFreq === undefined ||\r\n maxFreq === undefined\r\n ) {\r\n throw RangeError(\r\n `startTime, endTime, minFreq and maxFreq must be defined if polyRep is not passed.`\r\n );\r\n }\r\n\r\n // Ensure startTime comes before endtime\r\n if (startTime < endTime) {\r\n this.startTime = startTime;\r\n this.endTime = endTime;\r\n } else if (startTime > endTime) {\r\n // Switch times\r\n this.startTime = endTime;\r\n this.endTime = startTime;\r\n } else {\r\n // startTime === endTime\r\n throw RangeError(\"startTime and endTime must not be identical.\");\r\n }\r\n\r\n // Ensure minFreq comes before maxFreq\r\n if (minFreq < maxFreq) {\r\n this.minFreq = minFreq;\r\n this.maxFreq = maxFreq;\r\n } else if (minFreq > maxFreq) {\r\n // Switch frequencies\r\n this.minFreq = maxFreq;\r\n this.maxFreq = minFreq;\r\n } else {\r\n // minFreq === maxFreq\r\n throw RangeError(\"minFreq and maxFreq must not be identical.\");\r\n }\r\n\r\n // Calculate polygon representation\r\n this.polyRep = bboxPolygon([\r\n this.startTime,\r\n this.minFreq,\r\n this.endTime,\r\n this.maxFreq,\r\n ]);\r\n }\r\n\r\n // Ensure that polyRep is used as basis for startTime and endTime, minFreq and maxFreq\r\n // Calculate bounding box\r\n const box = bbox(this.polyRep);\r\n // Assuming coordinate origin in top left corner\r\n // . -- x -->\r\n // |\r\n // y\r\n // |\r\n // V\r\n this.startTime = box[0];\r\n this.minFreq = box[1];\r\n this.endTime = box[2];\r\n this.maxFreq = box[3];\r\n }\r\n\r\n /**\r\n * Create a new AudioRoi from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per AudioRoi constructor.\r\n * @param {object} obj An object containing all necessary properties of a AudioRoi.\r\n * @returns {AudioRoi} A new AudioRoi.\r\n */\r\n static fromObject = (obj) => {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new AudioRoi(\r\n obj.id,\r\n obj.fileId,\r\n obj.structure,\r\n obj.isAiAnnotated,\r\n obj.user,\r\n obj.modificationStatus,\r\n obj.channels,\r\n obj.startTime,\r\n obj.endTime,\r\n obj.minFreq,\r\n obj.maxFreq,\r\n obj.polyRep\r\n );\r\n };\r\n}\r\n\r\n//#endregion\r\n","import React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport { Route, Redirect } from \"react-router-dom\";\r\n\r\nimport { authenticationService } from \"../services\";\r\n\r\nconst PrivateRoute = ({ component: Component, roles, ...rest }) => (\r\n {\r\n const currentUser = authenticationService.currentUserValue;\r\n if (!currentUser) {\r\n // not logged in so redirect to login page with the return url\r\n return (\r\n \r\n );\r\n }\r\n\r\n // check if route is restricted by role\r\n if (roles && roles.indexOf(currentUser.role) === -1) {\r\n // role not authorised so redirect to home page\r\n return ;\r\n }\r\n\r\n // authorised so return component\r\n return ;\r\n }}\r\n />\r\n);\r\n\r\nPrivateRoute.propTypes = {\r\n component: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),\r\n roles: PropTypes.array,\r\n location: PropTypes.string,\r\n};\r\n\r\nexport { PrivateRoute };\r\n","// CustomDialog.jsx:\r\n// Component that provides a dialog to show information, errors, warnings and confirmations.\r\n\r\n// Copyright HS Analysis GmbH, 2024\r\n// Author: Viktor Eberhardt\r\n\r\n// Framework imports\r\nimport React, { Component } from \"react\";\r\n\r\n// Material UI imports\r\nimport Button from \"@mui/material/Button\";\r\nimport Dialog from \"@mui/material/Dialog\";\r\nimport DialogActions from \"@mui/material/DialogActions\";\r\nimport DialogContent from \"@mui/material/DialogContent\";\r\nimport DialogContentText from \"@mui/material/DialogContentText\";\r\nimport DialogTitle from \"@mui/material/DialogTitle\";\r\nimport TextField from \"@mui/material/TextField\";\r\n\r\nclass CustomDialog extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this.state = {\r\n content: \"\",\r\n contentList: [],\r\n description: [],\r\n dialogState: \"confirm\",\r\n open: false,\r\n responseFunction: null,\r\n title: \"\",\r\n };\r\n\r\n window.openResponseDialog = this.handleConfirmOpen;\r\n window.openErrorDialog = this.handleErrorOpen;\r\n window.openWarningDialog = this.handleWarningOpen;\r\n window.openInformationDialog = this.handleInformationOpen;\r\n window.openConfirmationDialog = this.awaitUserConfirmation;\r\n }\r\n\r\n handleConfirmOpen = (title, responseFunction) => {\r\n this.setState({\r\n title: title,\r\n content: \"\",\r\n open: true,\r\n dialogState: \"confirm\",\r\n responseFunction: responseFunction,\r\n });\r\n };\r\n\r\n /**\r\n * Promt the user for a yes/no decision that will pause program execution until the choise is made.\r\n * @param {string} title The title of the information dialog.\r\n * @param {string|string[]} description (List of) String. Each item displayed in a new line.\r\n * @param {string|string[]} content (List of) String. Each item displayed in an unordered list with a bullet point.\r\n * @returns {Promise} A promise that returns the user choise as boolean.\r\n */\r\n awaitUserConfirmation = async (title, description, content) => {\r\n return new Promise((resolve) => {\r\n this.setState({\r\n title: title,\r\n description:\r\n typeof description === \"string\" ? [description] : description,\r\n contentList: typeof content === \"string\" ? [content] : content,\r\n dialogState: \"confirm\",\r\n open: true,\r\n responseFunction: (confirmed) => resolve(confirmed),\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Open a dialog with an error message and an optional title.\r\n * Allow the user the option to download its contents.\r\n * @param {string} content The error message to display inside the dialog.\r\n * @param {string} title Optional. The title of the dialog. Default is \"Error\".\r\n */\r\n handleErrorOpen = (content, title = \"Error\") => {\r\n this.setState({\r\n title: title,\r\n content: content,\r\n dialogState: \"error\",\r\n open: true,\r\n });\r\n };\r\n\r\n /**\r\n * Opens a dialog with a short warning message that the user can dismiss.\r\n * @param {string} title The title of the warning dialog.\r\n */\r\n handleWarningOpen = (title) => {\r\n this.setState({\r\n title: title,\r\n content: \"\",\r\n description: [],\r\n contentList: [],\r\n dialogState: \"warning\",\r\n open: true,\r\n });\r\n };\r\n\r\n /**\r\n * Opens a dialog with a short information message that the user can dismiss.\r\n * @param {string} title The title of the information dialog.\r\n * @param {string|string[]} description (List of) String. Each item displayed in a new line.\r\n * @param {string|string[]} contentList (List of) String. Each item displayed in an unordered list with a bullet point.\r\n */\r\n handleInformationOpen = (title, description, contentList) => {\r\n this.setState({\r\n title: title,\r\n description:\r\n typeof description === \"string\" ? [description] : description,\r\n contentList:\r\n typeof contentList === \"string\" ? [contentList] : contentList,\r\n dialogState: \"information\",\r\n open: true,\r\n });\r\n };\r\n\r\n /**\r\n * Closes the custom dialog and resets state.\r\n *\r\n * @param {boolean} confirmed - Indicates whether the dialog was confirmed or not.\r\n */\r\n handleClose = (confirmed) => {\r\n this.setState({\r\n open: false,\r\n title: \"\",\r\n content: \"\",\r\n description: [],\r\n contentList: [],\r\n responseFunction: null,\r\n });\r\n if (this.state.dialogState === \"confirm\" && this.state.responseFunction) {\r\n this.state.responseFunction(confirmed);\r\n }\r\n };\r\n\r\n /**\r\n * Downloads the error log as a text file.\r\n */\r\n downloadError = () => {\r\n let filename = \"hsa_error_log.txt\";\r\n let text = this.state.content;\r\n let element = document.createElement(\"a\");\r\n element.setAttribute(\r\n \"href\",\r\n \"data:text/plain;charset=utf-8,\" + encodeURIComponent(text)\r\n );\r\n element.setAttribute(\"download\", filename);\r\n\r\n element.style.display = \"none\";\r\n document.body.appendChild(element);\r\n\r\n element.click();\r\n\r\n document.body.removeChild(element);\r\n };\r\n\r\n render() {\r\n const { dialogState, open, title, content } = this.state;\r\n if (!open) {\r\n return null;\r\n }\r\n return (\r\n this.handleClose(false)}\r\n aria-labelledby=\"responsive-dialog-title\"\r\n >\r\n {typeof title === \"object\" && title.length > 1 ? (\r\n \r\n {title.map((row, idx) => {\r\n return
    {row}
    ;\r\n })}\r\n
    \r\n ) : (\r\n {title}\r\n )}\r\n\r\n \r\n {[\"confirm\", \"error\", \"information\"].includes(dialogState) && (\r\n \r\n {this.state.description && (\r\n \r\n {this.state.description.map((row, idx) => {\r\n return
    {row}
    ;\r\n })}\r\n
    \r\n )}\r\n {this.state.contentList && (\r\n \r\n
      \r\n {this.state.contentList.map((content, idx) => {\r\n return
    • {content}
    • ;\r\n })}\r\n
    \r\n
    \r\n )}\r\n\r\n {dialogState === \"confirm\" && content !== \"\" && (\r\n {content}\r\n )}\r\n {content !== \"\" && (\r\n
    \r\n \r\n
    \r\n )}\r\n
    \r\n )}\r\n
    \r\n\r\n {/* Buttons */}\r\n \r\n {dialogState === \"confirm\" && (\r\n this.handleClose(false)}\r\n color=\"primary\"\r\n >\r\n Cancel\r\n \r\n )}\r\n {dialogState === \"error\" && (\r\n \r\n )}\r\n this.handleClose(true)}\r\n color=\"primary\"\r\n autoFocus\r\n >\r\n OK\r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nexport default CustomDialog;\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\nimport ProteomSettings from \"../../../proteomViewer/components/ProteomSettings\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\nimport {\r\n DialogContent,\r\n TextField,\r\n FormHelperText,\r\n FormControlLabel,\r\n Checkbox,\r\n} from \"@mui/material\";\r\n\r\nconst styles = () => ({\r\n root: {},\r\n dialogContent: {\r\n paddingTop: 0,\r\n maxWidth: 900,\r\n height: 562,\r\n },\r\n});\r\n\r\nclass StepMetaData extends Component {\r\n render() {\r\n const {\r\n classes,\r\n formData,\r\n onChangeMetaData,\r\n projectProperties,\r\n projectStringProperties,\r\n } = this.props;\r\n const metaData = formData.metaData;\r\n return (\r\n \r\n \r\n Meta Data for Project\r\n \r\n {formData.projectType.includes(\"ProteomeAnalysis\") ? (\r\n \r\n ) : (\r\n Object.keys(metaData).map((metaField, i) => (\r\n
    \r\n {metaData[metaField] === true || metaData[metaField] === false ? (\r\n \r\n onChangeMetaData(metaField, e.currentTarget.checked)\r\n }\r\n name=\"checkedB\"\r\n color=\"primary\"\r\n />\r\n }\r\n label={metaField}\r\n />\r\n ) : (\r\n onChangeMetaData(metaField, e.target.value)}\r\n />\r\n )}\r\n {/* onChangeMetaData(metaField, null)}\r\n >\r\n \r\n */}\r\n
    \r\n ))\r\n )}\r\n
    \r\n );\r\n }\r\n}\r\n\r\nStepMetaData.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n formData: PropTypes.object.isRequired,\r\n projectProperties: PropTypes.object,\r\n projectStringProperties: PropTypes.object,\r\n onChangeMetaData: PropTypes.func,\r\n};\r\n\r\nexport default withStyles(styles)(StepMetaData);\r\n","// StepProjectModuleSelection.jsx\r\n// Allows the selection of a project type from the list of all available project types.\r\n\r\n// Copyright HS Analysis GmbH, 2021\r\n// Author: Viktor Eberhardt, Jakob Burkhardt, Valentin Haas\r\n\r\n// Framework imports\r\nimport React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// External imports\r\nimport { TextValidator } from \"react-material-ui-form-validator\";\r\n\r\n// Material-UI imports\r\nimport DialogContent from \"@mui/material/DialogContent\";\r\nimport FormHelperText from \"@mui/material/FormHelperText\";\r\nimport Grid from \"@mui/material/Grid\";\r\nimport SearchIcon from \"@mui/icons-material/Search\";\r\nimport TextField from \"@mui/material/TextField\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\n// HSA Imports\r\nimport ProjectTypeList from \"./ProjectTypeList\";\r\n\r\nconst styles = () => ({\r\n dialogContent: {\r\n paddingTop: 0,\r\n maxWidth: 900,\r\n height: 562,\r\n },\r\n tileBar: {\r\n whiteSpace: \"normal !important\",\r\n },\r\n});\r\n\r\nclass StepProjectModuleSelection extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n searchText: \"\",\r\n };\r\n this.imageListItemRefs = [];\r\n }\r\n\r\n onChangeFilter = (e) => {\r\n let searchText = e.target.value;\r\n this.setState({ searchText });\r\n this.imageListItemRefs = [];\r\n };\r\n\r\n render() {\r\n const {\r\n classes,\r\n availableTypes,\r\n projectType,\r\n onProjectType,\r\n name,\r\n onChangeName,\r\n } = this.props;\r\n\r\n // Check for selected histo modules.\r\n let isHistoModule =\r\n projectType.includes(\"HistoClassification\") ||\r\n projectType.includes(\"HistoPointCounting\");\r\n\r\n return (\r\n \r\n \r\n \r\n onChangeName(e.target.value)}\r\n style={{ marginTop: 0 }}\r\n type=\"text\"\r\n validators={isHistoModule ? [] : [\"required\"]}\r\n value={isHistoModule ? \"Will be filled in automatically\" : name}\r\n variant=\"standard\"\r\n // select all text if component is defined\r\n onFocus={(e) => e.target.select()}\r\n />\r\n \r\n \r\n
    \r\n \r\n \r\n
    \r\n
    \r\n
    \r\n\r\n \r\n Project Type\r\n \r\n \r\n
    \r\n );\r\n }\r\n}\r\n\r\nStepProjectModuleSelection.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n name: PropTypes.string,\r\n projectType: PropTypes.string,\r\n onChangeName: PropTypes.func,\r\n availableTypes: PropTypes.array,\r\n onProjectType: PropTypes.func,\r\n};\r\n\r\nexport default withStyles(styles)(StepProjectModuleSelection);\r\n","// Framework imports\r\nimport React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport { ValidatorForm } from \"react-material-ui-form-validator\";\r\n\r\n// MUI imports\r\nimport { withStyles } from \"@mui/styles\";\r\nimport Button from \"@mui/material/Button\";\r\nimport Dialog from \"@mui/material/Dialog\";\r\nimport DialogTitle from \"@mui/material/DialogTitle\";\r\nimport Divider from \"@mui/material/Divider\";\r\nimport MobileStepper from \"@mui/material/MobileStepper\";\r\n\r\n// MUI icon imports\r\nimport KeyboardArrowLeft from \"@mui/icons-material/KeyboardArrowLeft\";\r\nimport KeyboardArrowRight from \"@mui/icons-material/KeyboardArrowRight\";\r\n\r\n// HSA imports\r\nimport { authenticationService } from \"../../common/services\";\r\nimport { shortenString, viewerType } from \"../../common/utils/Utils\";\r\nimport Backend from \"../../common/utils/Backend\";\r\nimport StepFileSelection from \"./CreateProjectdialogComponents/StepFileSelection\";\r\nimport StepMetaData from \"./CreateProjectdialogComponents/StepMetaData\";\r\nimport StepProjectModuleSelection from \"./CreateProjectdialogComponents/StepProjectModuleSelection\";\r\n\r\nconst styles = {\r\n divider: {\r\n height: \"1px\", // Modify this to adjust the thickness\r\n backgroundColor: \"rgb(148,148,148)\", // You can also change the color here\r\n },\r\n};\r\nclass CreateProjectDialog extends Component {\r\n constructor(props) {\r\n super(props);\r\n this.state = {\r\n submitted: false,\r\n activeStep: 0,\r\n projectTypes: [],\r\n origFiles: [],\r\n formData: {\r\n name: props.newdefaultname,\r\n projectType: \"\",\r\n metaData: {},\r\n files: [],\r\n projectProperties: {},\r\n projectStringProperties: {},\r\n groups: [],\r\n caseId: null,\r\n },\r\n };\r\n this.user = null;\r\n\r\n Backend.loadAvailableProjectTypes(false).then((projectTypes) => {\r\n const { formData } = this.state;\r\n // order project types by order attribute\r\n projectTypes = projectTypes.sort((a, b) => a.order - b.order);\r\n Backend.getLicensingInfo((license) => {\r\n if (license.activeModules.length > 0) {\r\n if (license.licenseStatus !== \"VALID\") {\r\n authenticationService.logout();\r\n this.props.history.push(\"/licensing\");\r\n return;\r\n }\r\n\r\n projectTypes = projectTypes.map((projectType) => {\r\n if (license.activeModules.length > 0) {\r\n const activeModule = license.activeModules.find(\r\n (x) => x.name === projectType.name\r\n );\r\n if (activeModule) {\r\n projectType.expirationDate = activeModule.expirationDate;\r\n projectType.isValid = !activeModule.isExpired;\r\n projectType.expiresInDays = activeModule.expiresInDays;\r\n } else {\r\n projectType.isValid = false;\r\n }\r\n } else {\r\n projectType.isValid = true;\r\n }\r\n return projectType;\r\n });\r\n\r\n projectTypes = projectTypes.filter(\r\n (projectType) => typeof projectType.expirationDate !== \"undefined\"\r\n );\r\n if (projectTypes.length > 0) {\r\n // select default project type\r\n const firstValidProjectType = projectTypes.find((pt) => pt.isValid);\r\n if (firstValidProjectType) {\r\n formData.projectType = firstValidProjectType.name;\r\n for (let metaField of projectTypes.find(\r\n (c) => c.name === formData.projectType\r\n ).metaData) {\r\n // use existing value or init dict entry with empty string\r\n formData.metaData[metaField] =\r\n metaField === \"Datum\" || metaField === \"Date\"\r\n ? this.getDate()\r\n : formData.metaData[metaField] || \"\";\r\n }\r\n }\r\n }\r\n }\r\n // write received info into state\r\n this.setState({\r\n projectTypes: projectTypes,\r\n formData,\r\n metaData: {},\r\n files: [],\r\n });\r\n\r\n Backend.getCurrentUser((user) => (this.user = user));\r\n Backend.getCurrentUserGroups((response) => {\r\n const formData = this.state.formData;\r\n formData.groups = response;\r\n this.setState({ formData });\r\n });\r\n });\r\n });\r\n }\r\n\r\n handleKeyPress = (event) => {\r\n if (!this.props.open) return;\r\n\r\n if (event.key === \"Enter\") {\r\n this.handleNext();\r\n }\r\n };\r\n\r\n componentDidMount = () => {\r\n document.addEventListener(\"keyup\", this.handleKeyPress);\r\n };\r\n\r\n componentWillUnmount = () => {\r\n document.removeEventListener(\"keyup\", this.handleKeyPress);\r\n };\r\n\r\n componentDidUpdate = (prevProps) => {\r\n // on open dialog\r\n if (prevProps.open !== this.props.open && this.props.open) {\r\n const { formData } = this.state;\r\n if (this.props.project) {\r\n const promises = this.props.project.imageFileIds.map((fileId) => {\r\n return Backend.getFileInfo(fileId);\r\n });\r\n Promise.all(promises).then((files) => {\r\n formData.files = [...new Set(files.map((file) => file.relativePath))];\r\n formData.name = this.props.project.name;\r\n formData.projectType = this.props.project.type;\r\n this.setState({\r\n submitted: false,\r\n activeStep: 0,\r\n formData,\r\n origFiles: formData.files,\r\n });\r\n });\r\n } else {\r\n formData.files = [];\r\n formData.name = this.props.newdefaultname;\r\n this.setState({\r\n submitted: false,\r\n activeStep: 0,\r\n formData,\r\n origFiles: [],\r\n });\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Defines what happens when the next button is pressed.\r\n * When moving a step forward, checks are made to see if the next option is necessary.\r\n * When finishing the final step, project is created or updated.\r\n */\r\n handleNext = async () => {\r\n if (this.props.project && this.state.activeStep === 0) {\r\n this.setState({ activeStep: 2 });\r\n return;\r\n }\r\n const { formData } = this.state;\r\n\r\n // Go to next step\r\n if (this.state.activeStep < 2) {\r\n if (formData.projectType === \"\") {\r\n window.showWarningSnackbar(\"Please select a Project Module!\");\r\n return;\r\n }\r\n\r\n let nextStep = this.state.activeStep + 1;\r\n\r\n // Skip metadata step if no metadata is required\r\n if (nextStep === 1 && Object.keys(formData.metaData).length === 0) {\r\n nextStep++;\r\n }\r\n this.setState({ activeStep: nextStep, formData });\r\n return;\r\n }\r\n\r\n // Submit data\r\n if (this.state.formData.files.length === 0) return;\r\n\r\n // last step -> submit data\r\n this.setState({ submitted: true });\r\n\r\n // Update project\r\n if (this.props.project) {\r\n const filesRemoved = this.state.origFiles.filter(\r\n (oF) => !formData.files.includes(oF)\r\n );\r\n\r\n const filesRemovedInfo = [];\r\n const promises = filesRemoved.map(async (filePath) => {\r\n const fileAnnoCount = await Backend.getAnnotationCount(\r\n this.props.project.id,\r\n filePath\r\n );\r\n if (fileAnnoCount > 0) {\r\n filesRemovedInfo.push({\r\n filePath: filePath,\r\n annotationCount: fileAnnoCount,\r\n });\r\n }\r\n });\r\n await Promise.all(promises);\r\n\r\n const annotationsToLoose = filesRemovedInfo.reduce(\r\n (acc, file) => acc + file.annotationCount,\r\n 0\r\n );\r\n\r\n const continueImport =\r\n annotationsToLoose === 0 ||\r\n (await window.openConfirmationDialog(\r\n \"Warning: You are removing annotated files\",\r\n `The following ${filesRemoved.length} ${\r\n filesRemoved.length === 1 ? \"file\" : \"files\"\r\n } with a total of ${annotationsToLoose} annotations will be deleted from the project \"${\r\n this.props.project.name\r\n }\". Do you want to continue?`,\r\n filesRemovedInfo.map(\r\n (file) =>\r\n `${shortenString(file.filePath, 60)} (${file.annotationCount})`\r\n )\r\n ));\r\n if (!continueImport) {\r\n this.setState({ submitted: false });\r\n return;\r\n }\r\n\r\n Backend.updateProject(this.props.project.id, formData)\r\n .then(() => {\r\n this.handleClose();\r\n })\r\n .catch((error) => {\r\n this.setState({ submitted: false });\r\n console.error(\"Error updating project:\", error);\r\n window.openErrorDialog(error.toString(), \"Error updating project\");\r\n });\r\n return;\r\n }\r\n\r\n // Histology Classification and Histology Point Counting projects have a special naming convention\r\n if (\r\n formData.projectType.includes(\"HistoClassification\") ||\r\n formData.projectType.includes(\"HistoPointCounting\")\r\n ) {\r\n let name = formData.files[0];\r\n name = name.replace(/\\\\/g, \"/\");\r\n let name_array = name.split(\"/\");\r\n name = name_array[name_array.length - 1];\r\n name = name.split(\".\")[0];\r\n name_array = name.split(\"-\");\r\n let i = 0;\r\n while (i < name_array.length - 1) {\r\n if (i === 0) {\r\n name = name_array[i];\r\n } else {\r\n name = name + \"-\" + name_array[i];\r\n }\r\n i = i + 1;\r\n }\r\n\r\n formData.name = name;\r\n this.setState({ formData: formData });\r\n }\r\n\r\n // Create new project\r\n Backend.createProject(this.state.formData)\r\n .then((e) => {\r\n this.setState({ submitted: true });\r\n this.handleClose();\r\n if (formData.projectType.includes(\"ProteomeAnalysis\")) {\r\n Backend.loadProject(e.projectId).then((project) => {\r\n Backend.getCurrentUser((user) => {\r\n const projectModel = {\r\n name: project.name,\r\n user: user.fullName,\r\n id: project.id,\r\n readableId: project.readableId,\r\n metaData: JSON.parse(project.metaData),\r\n type: project.type,\r\n tools: project.viewerConfig.project.tools,\r\n job: project.viewerConfig.project.job,\r\n files: project.files,\r\n };\r\n Backend.saveProject(projectModel)\r\n .then((data) => {\r\n if (data.success) {\r\n this.props.handleActiveTabChange(0);\r\n Backend.setProjectsPending([project.id], false, () => {\r\n console.log(\"job ready to start!\");\r\n });\r\n }\r\n })\r\n .catch((error) => {\r\n window.openErrorDialog(\r\n error +\r\n \"\\n\" +\r\n \"Project couldn't be saved!\\nTry again later.\"\r\n );\r\n });\r\n });\r\n });\r\n } else {\r\n this.props.history.push(\r\n viewerType(formData.projectType) + e.projectId\r\n );\r\n }\r\n\r\n // Add project to predefined case\r\n if (this.state.formData.caseId !== null) {\r\n Backend.editCaseProjects(\r\n this.state.formData.caseId,\r\n e.projectId,\r\n \"add\"\r\n );\r\n }\r\n })\r\n .catch((error) => {\r\n this.setState({ submitted: false });\r\n console.error(\"Error creating project:\", error);\r\n window.openErrorDialog(error.toString(), \"Error creating project\");\r\n });\r\n };\r\n\r\n handleBack = () => {\r\n const { formData } = this.state;\r\n if (this.state.activeStep === 0) {\r\n this.props.onClose();\r\n return;\r\n }\r\n\r\n if (this.props.project) {\r\n this.setState({ activeStep: 0 });\r\n return;\r\n }\r\n let prevStep = this.state.activeStep - 1;\r\n\r\n // Skip metadata step if no metadata is required\r\n if (prevStep === 1 && Object.keys(formData.metaData).length === 0) {\r\n prevStep--;\r\n }\r\n\r\n // Reset files\r\n formData.files = [];\r\n this.setState({ activeStep: prevStep, formData: formData });\r\n };\r\n\r\n handleClose = () => {\r\n this.props.onClose();\r\n };\r\n\r\n onChangeName = (e) => {\r\n const { formData } = this.state;\r\n formData.name = e;\r\n this.setState({ formData });\r\n if (this.props.project) {\r\n let project = this.props.project;\r\n project.name = e;\r\n }\r\n };\r\n\r\n onChangeCaseId = (e) => {\r\n const { formData } = this.state;\r\n formData.caseId = e;\r\n this.setState({ formData });\r\n };\r\n\r\n /**\r\n * Fills in project parameters for saving.\r\n * Checks for valid expiration date and gives expiration notice.\r\n * @param {Object} e Selected module from step 0, including properties.\r\n */\r\n onProjectType = (e) => {\r\n const { formData, projectTypes } = this.state;\r\n formData.projectProperties = e.projectProperties;\r\n formData.projectStringProperties = e.ProjectStringProperties;\r\n formData.metaData = e.metaData;\r\n formData.toolsInProject = e.toolsInProject;\r\n this.setState({ formData: formData });\r\n\r\n if (!e.isValid && e.expirationDate) {\r\n window.openWarningDialog(\r\n \"This Project Module expired on \" +\r\n e.expirationDate.replace(\"T00:00:00\", \"\") +\r\n \".\\nPlease contact HS Analysis GmbH to updated the licence!\"\r\n );\r\n return;\r\n }\r\n if (this.props.project) {\r\n window.openWarningDialog(\r\n \"Project already created and the project type can't be changed afterwards.\\nPlease create a new Project instead.\"\r\n );\r\n return;\r\n }\r\n\r\n formData.projectType = e.name;\r\n formData.metaData = {};\r\n\r\n const selectedProjectType = projectTypes.find(\r\n (pt) => pt.name === formData.projectType\r\n );\r\n if (\r\n (\"selectedProjectType\",\r\n selectedProjectType &&\r\n selectedProjectType.name.includes(\"ProteomeAnalysis\"))\r\n ) {\r\n formData.projectStringProperties =\r\n selectedProjectType.projectStringProperties;\r\n formData.projectProperties = selectedProjectType.projectProperties;\r\n for (const [key, value] of Object.entries(\r\n formData.projectStringProperties\r\n )) {\r\n formData.metaData[key] = value.split(\",\")[0];\r\n }\r\n for (const [key, value] of Object.entries(formData.projectProperties)) {\r\n formData.metaData[key] = value;\r\n }\r\n }\r\n\r\n for (let metaField of projectTypes.find((c) => c.name === e.name)\r\n .metaData) {\r\n // use existing value or init dict entry with empty string\r\n formData.metaData[metaField] =\r\n metaField === \"Datum\" || metaField === \"Date\"\r\n ? this.getDate()\r\n : formData.metaData[metaField] || \"\";\r\n\r\n // check if metaField ia also key in projectStringProperties\r\n if (selectedProjectType.projectStringProperties[metaField]) {\r\n formData.metaData[metaField] =\r\n selectedProjectType.projectStringProperties[metaField];\r\n }\r\n }\r\n this.setState({ formData });\r\n };\r\n\r\n onChangeMetaData = (field, e) => {\r\n const { formData } = this.state;\r\n if (e === null) {\r\n // delete field\r\n delete formData.metaData[field];\r\n } else {\r\n // update fiel value\r\n formData.metaData[field] = e;\r\n }\r\n this.setState({ formData });\r\n };\r\n\r\n onChangeFiles = (e) => {\r\n const { formData } = this.state;\r\n formData.files = e;\r\n this.setState({ formData });\r\n };\r\n\r\n /**\r\n * Get today's date in format dd.mm.yyyy\r\n * @returns {string} today's date in format dd.mm.yyyy\r\n */\r\n getDate = () => {\r\n const today = new Date();\r\n const dd = String(today.getDate()).padStart(2, \"0\");\r\n const mm = String(today.getMonth() + 1).padStart(2, \"0\");\r\n const yyyy = today.getFullYear();\r\n return dd + \".\" + mm + \".\" + yyyy;\r\n };\r\n\r\n render() {\r\n const { classes } = this.props;\r\n const { activeStep, formData, projectTypes, submitted } = this.state;\r\n\r\n return (\r\n \r\n Create New Project\r\n \r\n
    \r\n \r\n {activeStep === 0 && (\r\n \r\n )}\r\n {activeStep === 1 && (\r\n \r\n )}\r\n {activeStep === 2 && (\r\n \r\n )}\r\n \r\n {/* Change Next Button depending on if you're editing a project\r\n or creating a new one */}\r\n {this.props.project && this.state.activeStep > 1\r\n ? \"Save\"\r\n : \"Next\"}\r\n\r\n \r\n \r\n }\r\n backButton={\r\n \r\n \r\n {\"Back\"}\r\n \r\n }\r\n />\r\n \r\n
    \r\n );\r\n }\r\n}\r\n\r\nCreateProjectDialog.propTypes = {\r\n project: PropTypes.object,\r\n onClose: PropTypes.func,\r\n selectedValue: PropTypes.string,\r\n newdefaultname: PropTypes.string,\r\n handleActiveTabChange: PropTypes.func,\r\n open: PropTypes.bool,\r\n history: PropTypes.object,\r\n classes: PropTypes.object.isRequired,\r\n};\r\n\r\nexport default withRouter(withStyles(styles)(CreateProjectDialog));\r\n","import React, { useState, useEffect } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// HSA imports\r\nimport Backend from \"../../common/utils/Backend\";\r\n\r\nconst PreviewImage = ({ fileId }) => {\r\n const [fileName, setFileName] = useState(\"\");\r\n useEffect(() => {\r\n Backend.getFileInfo(fileId).then((file) => {\r\n setFileName(file.fileName);\r\n });\r\n }, [fileId]);\r\n\r\n return (\r\n
    \r\n
    \r\n \r\n \r\n {fileName}\r\n
    \r\n
    \r\n \r\n );\r\n};\r\n\r\nPreviewImage.propTypes = {\r\n fileId: PropTypes.string.isRequired,\r\n};\r\n\r\nexport default PreviewImage;\r\n","// ProjectsTableRow.jsx\r\n\r\n// Copyright HS Analysis GmbH, 2019\r\n// Authors: Viktor Eberhardt\r\n\r\n// Framework imports\r\nimport React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// Mui imports\r\nimport Button from \"@mui/material/Button\";\r\nimport Checkbox from \"@mui/material/Checkbox\";\r\nimport EditIcon from \"@mui/icons-material/Edit\";\r\nimport FileCopyIcon from \"@mui/icons-material/FileCopy\";\r\nimport IconButton from \"@mui/material/IconButton\";\r\nimport LinearProgress from \"@mui/material/LinearProgress\";\r\nimport PlayArrowIcon from \"@mui/icons-material/PlayArrow\";\r\nimport StopIcon from \"@mui/icons-material/Stop\";\r\nimport TableCell from \"@mui/material/TableCell\";\r\nimport TableRow from \"@mui/material/TableRow\";\r\nimport TimerIcon from \"@mui/icons-material/Timer\";\r\nimport Tooltip from \"@mui/material/Tooltip\";\r\n\r\n// HSA imports\r\nimport { convertDate } from \"../../common/utils/Localization\";\r\nimport Backend from \"../../common/utils/Backend\";\r\nimport CustomSvgIcon from \"../../globalComponents/CustomSvgIcon\";\r\nimport PreviewImage from \"./PreviewImage\";\r\n\r\nconst ProjectsTableRow = (props) => {\r\n const {\r\n classes,\r\n projectTypes,\r\n isSelected,\r\n project,\r\n handleClick,\r\n handleSelectOneClick,\r\n onEditProject,\r\n history,\r\n handleActiveTabChange,\r\n user,\r\n } = props;\r\n\r\n /**\r\n * Returns Label of a project type\r\n * @param {String} type Project type string\r\n */\r\n const labelFromProjectType = () => {\r\n if (!projectTypes) return project.type;\r\n let resultObject = projectTypes.find((c) => c.name === project.type);\r\n return resultObject ? resultObject.label : project.type;\r\n };\r\n\r\n const handleContextmenu = (e) => {\r\n e.preventDefault();\r\n handleSelectOneClick(e, project);\r\n };\r\n\r\n const onCancelRowClick = (e) => {\r\n e.stopPropagation();\r\n Backend.cancelJob(project.id);\r\n };\r\n\r\n // Sets job state for project to pending, so that it can be run, when no other job is running\r\n const onRunRowClick = (e) => {\r\n e.stopPropagation();\r\n props.onRunRowClick(e, [project.id], project);\r\n };\r\n\r\n const onDuplicateSingleClick = (e) => {\r\n e.stopPropagation();\r\n Backend.duplicateProjects([project.id], () => {\r\n handleActiveTabChange(0);\r\n });\r\n };\r\n\r\n const onProjectStateClick = (e, id) => {\r\n e.stopPropagation();\r\n Backend.loadProjectMessage(id)\r\n .then((jsonResponse) => {\r\n if (jsonResponse.message) {\r\n console.log(jsonResponse.message);\r\n }\r\n })\r\n .catch((error) => {\r\n console.log(\"Error:\", error);\r\n });\r\n };\r\n\r\n const onProjectErrorStateClick = (e, id) => {\r\n e.stopPropagation();\r\n Backend.loadProjectMessage(id)\r\n .then((jsonResponse) => {\r\n if (jsonResponse.message) {\r\n window.openErrorDialog(jsonResponse.message);\r\n }\r\n })\r\n .catch((error) => {\r\n console.log(\"Error:\", error);\r\n });\r\n };\r\n\r\n /**\r\n * Set job state for project to timed\r\n * @param {MouseEvent} e\r\n */\r\n const onSetTimedClick = (e) => {\r\n e.stopPropagation();\r\n Backend.setProjectsTimed([project.id], () => {\r\n console.debug(\r\n `Project ${project.readableId}, (${project.id}) state updated: timed`\r\n );\r\n });\r\n };\r\n\r\n //Updates label style according to project state\r\n const labelFromState = () => {\r\n switch (project.state) {\r\n case \"creating\":\r\n return (\r\n \r\n onProjectStateClick(e, project.id)}\r\n >\r\n \r\n
    {project.progress}%
    \r\n \r\n
    \r\n );\r\n case \"running\":\r\n return (\r\n \r\n onProjectStateClick(e, project.id)}\r\n >\r\n \r\n
    {project.progress}%
    \r\n \r\n \r\n );\r\n case \"success\":\r\n return (\r\n onProjectStateClick(e, project.id)}\r\n >\r\n Finished\r\n \r\n );\r\n case \"error\":\r\n return (\r\n onProjectErrorStateClick(e, project.id)}\r\n >\r\n {project.state}\r\n \r\n );\r\n default:\r\n return (\r\n onProjectStateClick(e, project.id)}>\r\n {project.state}\r\n \r\n );\r\n }\r\n };\r\n\r\n return (\r\n handleClick(event, project)}\r\n role=\"checkbox\"\r\n aria-checked={isSelected}\r\n tabIndex={-1}\r\n key={project.id}\r\n selected={isSelected}\r\n onContextMenu={handleContextmenu}\r\n >\r\n \r\n \r\n \r\n handleSelectOneClick(event, project)}\r\n />\r\n \r\n \r\n \r\n {project.readableId}\r\n \r\n \r\n {project.imageFileIds\r\n .slice(0, Math.min(5, project.imageFileIds.length))\r\n .map((fileId, idx) => {\r\n return ;\r\n })}\r\n \r\n }\r\n >\r\n {\r\n (event.target.style.display = \"none\")}\r\n width=\"60\"\r\n height=\"60\"\r\n src={Backend.renderThumbnail(\r\n project.imageFileIds.length > 0 ? project.imageFileIds[0] : 0\r\n )}\r\n alt=\"\"\r\n />\r\n }\r\n \r\n \r\n \r\n \r\n {project.name}\r\n \r\n\r\n {!project.type.includes(\"HistoPointCounting\") &&\r\n !project.type.includes(\"HistoClassification\") && (\r\n \r\n \r\n {\r\n onEditProject(project);\r\n e.stopPropagation();\r\n }}\r\n size=\"large\"\r\n >\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n {project.ownerName}\r\n {labelFromProjectType()}\r\n {labelFromState()}\r\n \r\n {convertDate(project.creationDateTime).toLocaleString()}\r\n \r\n \r\n {project.state === \"success\" && project.type !== \"ProteomeAnalysis\" ? (\r\n \r\n \r\n {\r\n e.stopPropagation();\r\n history.push(\"/report/\" + project.id);\r\n }}\r\n size=\"large\"\r\n >\r\n \r\n \r\n \r\n \r\n ) : (\r\n \"\"\r\n )}\r\n {project.state === \"success\" && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n )}\r\n\r\n {!project.type.includes(\"HistoPointCounting\") &&\r\n !project.type.includes(\"HistoClassification\") && (\r\n \r\n {project.state === \"running\" ||\r\n project.state === \"timed\" ||\r\n project.state === \"pending\" ? (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n {!project.canRun ||\r\n project.state === \"running\" ||\r\n project.state === \"pending\" ? (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ) : (\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n \r\n )}\r\n \r\n \r\n );\r\n};\r\n\r\nProjectsTableRow.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n user: PropTypes.object,\r\n projectTypes: PropTypes.array.isRequired,\r\n isSelected: PropTypes.bool.isRequired,\r\n project: PropTypes.object.isRequired,\r\n handleClick: PropTypes.func.isRequired,\r\n handleSelectOneClick: PropTypes.func.isRequired,\r\n onEditProject: PropTypes.func.isRequired,\r\n history: PropTypes.object.isRequired,\r\n handleActiveTabChange: PropTypes.func.isRequired,\r\n onRunRowClick: PropTypes.func,\r\n};\r\n\r\nexport default ProjectsTableRow;\r\n","import React, { useState } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport {\r\n FormControlLabel,\r\n Dialog,\r\n DialogTitle,\r\n DialogContent,\r\n DialogActions,\r\n Button,\r\n Radio,\r\n RadioGroup,\r\n FormLabel,\r\n} from \"@mui/material\";\r\n\r\nfunction CreateConfirmationDialog({ open, setOpen, setPending }) {\r\n const [evalOnly, setEvalOnly] = useState(false); //,\r\n\r\n function handleRadioChange(event) {\r\n setEvalOnly(event.target.value);\r\n }\r\n\r\n function handleClose(runJob) {\r\n if (runJob) {\r\n setPending(evalOnly);\r\n }\r\n setOpen(false);\r\n }\r\n\r\n return (\r\n
    \r\n handleClose(false)}\r\n aria-labelledby=\"form-dialog-title\"\r\n >\r\n Analysis Mode\r\n \r\n \r\n \r\n }\r\n label=\"Full Analysis\"\r\n />\r\n }\r\n label=\"Only Update Results\"\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
    \r\n );\r\n}\r\n\r\nCreateConfirmationDialog.propTypes = {\r\n open: PropTypes.bool,\r\n setOpen: PropTypes.func,\r\n setPending: PropTypes.func,\r\n};\r\n\r\nexport default CreateConfirmationDialog;\r\n","// Copyright HS-Analysis GmbH, 2019\r\n\r\n// Framework imports\r\nimport React from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\n// External imports\r\nimport classNames from \"classnames\";\r\n\r\n// Material UI imports\r\nimport { darken, lighten } from \"@mui/material/styles\";\r\nimport Checkbox from \"@mui/material/Checkbox\";\r\nimport CloudDownload from \"@mui/icons-material/CloudDownload\";\r\nimport CloudUpload from \"@mui/icons-material/CloudUpload\";\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport FileCopy from \"@mui/icons-material/FileCopy\";\r\nimport IconButton from \"@mui/material/IconButton\";\r\nimport Merge from \"@mui/icons-material/MergeType\";\r\nimport Paper from \"@mui/material/Paper\";\r\nimport PlayArrowIcon from \"@mui/icons-material/PlayArrow\";\r\nimport SearchIcon from \"@mui/icons-material/Search\";\r\nimport Tab from \"@mui/material/Tab\";\r\nimport Table from \"@mui/material/Table\";\r\nimport TableBody from \"@mui/material/TableBody\";\r\nimport TableCell from \"@mui/material/TableCell\";\r\nimport TableContainer from \"@mui/material/TableContainer\";\r\nimport TableHead from \"@mui/material/TableHead\";\r\nimport TableRow from \"@mui/material/TableRow\";\r\nimport TableSortLabel from \"@mui/material/TableSortLabel\";\r\nimport Tabs from \"@mui/material/Tabs\";\r\nimport TextField from \"@mui/material/TextField\";\r\nimport TimelineIcon from \"@mui/icons-material/Timeline\";\r\nimport TimerIcon from \"@mui/icons-material/Timer\";\r\nimport Toolbar from \"@mui/material/Toolbar\";\r\nimport Tooltip from \"@mui/material/Tooltip\";\r\nimport Typography from \"@mui/material/Typography\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\n// font awesome imports\r\nimport { faObjectGroup } from \"@fortawesome/free-solid-svg-icons\";\r\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\r\n\r\n// HSA imports\r\nimport \"./../../css/tooltip.css\";\r\nimport { authenticationService } from \"../../common/services\";\r\nimport { viewerType } from \"../../common/utils/Utils\";\r\nimport { withSpinloader } from \"../../common/components/Spinloader\";\r\nimport Backend from \"../../common/utils/Backend\";\r\nimport FindFilesDialog, { ProjectActionMode } from \"../dialogs/FindFilesDialog\";\r\nimport ProjectsTableRow from \"./ProjectsTableRow\";\r\nimport CreateConfirmationDialog from \"../dialogs/CreateConfirmationDialog\";\r\n\r\nfunction desc(a, b, orderBy) {\r\n if (b[orderBy] < a[orderBy]) {\r\n return -1;\r\n }\r\n if (b[orderBy] > a[orderBy]) {\r\n return 1;\r\n }\r\n return 0;\r\n}\r\n\r\nfunction stableSort(array, cmp) {\r\n const stabilizedThis = array.map((el, index) => [el, index]);\r\n stabilizedThis.sort((a, b) => {\r\n const order = cmp(a[0], b[0]);\r\n if (order !== 0) return order;\r\n return a[1] - b[1];\r\n });\r\n return stabilizedThis.map((el) => el[0]);\r\n}\r\n\r\nfunction getSorting(order, orderBy) {\r\n return order === \"desc\"\r\n ? (a, b) => desc(a, b, orderBy)\r\n : (a, b) => -desc(a, b, orderBy);\r\n}\r\n\r\nconst rows = [\r\n { id: \"readableId\", numeric: false, disablePadding: false, label: \"ID\" },\r\n { id: \"thumbnail\", numeric: false, disablePadding: true, label: \"Preview\" },\r\n { id: \"name\", numeric: false, disablePadding: true, label: \"Name\" },\r\n { id: \"creator\", numeric: false, disablePadding: false, label: \"Creator\" },\r\n { id: \"type\", numeric: true, disablePadding: false, label: \"Method\" },\r\n { id: \"state\", numeric: true, disablePadding: false, label: \"State\" },\r\n {\r\n id: \"creationDateTime\",\r\n numeric: true,\r\n disablePadding: false,\r\n label: \"Created\",\r\n },\r\n { id: \"actions\", numeric: false, disablePadding: false, label: \"Actions\" },\r\n];\r\n\r\nclass EnhancedTableHead extends React.Component {\r\n createSortHandler = (property) => (event) => {\r\n this.props.onRequestSort(event, property);\r\n };\r\n\r\n render() {\r\n const { onSelectAllClick, order, orderBy, numSelected } = this.props;\r\n\r\n return (\r\n \r\n \r\n \r\n 0}\r\n onChange={onSelectAllClick}\r\n />\r\n \r\n {rows.map(\r\n (row) => (\r\n \r\n \r\n \r\n {row.label}\r\n \r\n \r\n \r\n ),\r\n this\r\n )}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nEnhancedTableHead.propTypes = {\r\n numSelected: PropTypes.number.isRequired,\r\n onRequestSort: PropTypes.func.isRequired,\r\n onSelectAllClick: PropTypes.func.isRequired,\r\n order: PropTypes.string.isRequired,\r\n orderBy: PropTypes.string.isRequired,\r\n rowCount: PropTypes.number.isRequired,\r\n};\r\n\r\nconst toolbarStyles = (theme) => ({\r\n root: {\r\n paddingRight: theme.spacing(1),\r\n display: \"grid\",\r\n gridTemplateColumns: \"auto auto 1fr auto auto auto\",\r\n },\r\n searchIcon: {\r\n fill: \"lightgray\",\r\n marginTop: 8,\r\n marginLeft: 20,\r\n },\r\n searchField: {\r\n marginLeft: 6,\r\n marginTop: 0,\r\n maxWidth: 300,\r\n },\r\n highlight:\r\n theme.palette.mode === \"light\"\r\n ? {\r\n color: theme.palette.secondary.main,\r\n backgroundColor: lighten(theme.palette.secondary.light, 0.85),\r\n }\r\n : {\r\n color: theme.palette.text.primary,\r\n backgroundColor: theme.palette.secondary.dark,\r\n },\r\n spacer: {\r\n flex: \"1 1 100%\",\r\n },\r\n actions: {\r\n color: theme.palette.text.secondary,\r\n },\r\n title: {\r\n flex: \"0 0 auto\",\r\n },\r\n});\r\n\r\n/**\r\n * Toolbar for the projects table\r\n * @param {Object} props - External properties\r\n * @param {Object} props.classes - CSS classes\r\n * @param {number} props.numSelected - Number of selected projects\r\n * @param {Function} props.onChangeFilter - Callback for filter change\r\n * @param {Function} props.onCreateTimeLineChartClick - Callback for creating a timeline chart\r\n * @param {Function} props.onDeleteClick - Callback for deleting selected projects\r\n * @param {Function} props.onDuplicateSelectedClick - Callback for duplicating selected projects\r\n * @param {Function} props.onExportClick - Callback for exporting selected projects\r\n * @param {Function} props.onImportClick - Callback for importing projects\r\n * @param {Function} props.onMergeResultsClick - Callback for merging selected project results\r\n * @param {Function} props.onMergeSelectedClick - Callback for merging selected projects\r\n * @param {Function} props.onRunSelectedClick - Callback for running selected projects\r\n * @param {Function} props.onTimedRunSelectedClick - Callback for running selected projects within time\r\n * @param {Array} props.projects - Array of all projects\r\n * @param {string} props.searchText - Search text for filtering projects\r\n * @param {Object} props.user - User object\r\n * @param {Array} props.selected - Array of selected project's ids\r\n * @param {Object} props.spinloader - Spinloader object\r\n */\r\nlet EnhancedTableToolbar = (props) => {\r\n const {\r\n classes,\r\n numSelected,\r\n onChangeFilter,\r\n onCreateTimeLineChartClick,\r\n onDeleteClick,\r\n onDuplicateSelectedClick,\r\n onExportClick,\r\n onImportClick,\r\n onMergeResultsClick,\r\n onMergeSelectedClick,\r\n onRunSelectedClick,\r\n onTimedRunSelectedClick,\r\n projects,\r\n searchText,\r\n user,\r\n selected,\r\n spinloader,\r\n } = props;\r\n const canOpenProject = true; //TODO: Fix user.group.canOpenProject\r\n\r\n const fileUploader = React.useRef(null);\r\n\r\n const onChangeFile = (event) => {\r\n spinloader.show();\r\n event.stopPropagation();\r\n event.preventDefault();\r\n onImportClick(event.target.files);\r\n event.target.value = \"\";\r\n };\r\n\r\n /**\r\n * This function initializes the merge button based on certain conditions.\r\n *\r\n * The conditions are whether more than one project is selected and whether all of them are successful.\r\n * It returns an array of two values: whether the button should be disabled and the tooltip to display.\r\n *\r\n * @param {number} numSelected - Number of selected projects\r\n * @param {Array} projects - Array of all projects\r\n * @param {Array} selected - Array of selected project's ids\r\n *\r\n * @returns {Array} An array containing information about whether the merge\r\n * button should be disabled and the tooltip to be displayed. First element is a boolean value which\r\n * tells if the button should be disabled or not and the second element is a string for the tooltip.\r\n */\r\n const initMergeButton = (numSelected, projects, selected) => {\r\n let mergeResultsButtonTooltip = \"Merge Results (2 selections required)\";\r\n let mergeResultsButtonDisabled = true;\r\n\r\n if (numSelected > 1) {\r\n const selectedProjects = projects.filter((project) =>\r\n selected.includes(project.id)\r\n );\r\n\r\n const allProjectsFinished = selectedProjects.every(\r\n (project) => project.state === \"success\"\r\n );\r\n\r\n if (!allProjectsFinished) {\r\n mergeResultsButtonTooltip =\r\n \"Merge Results (All projects must be finished)\";\r\n }\r\n\r\n mergeResultsButtonDisabled = !allProjectsFinished;\r\n }\r\n\r\n return [mergeResultsButtonDisabled, mergeResultsButtonTooltip];\r\n };\r\n\r\n /**\r\n * Initializes the timeline button based on certain conditions.\r\n *\r\n * The conditions are whether more than one project is selected, whether all projects are successful,\r\n * and if they are all of type 'Fungilyzer'. It returns an array of two values:\r\n * whether the button should be disabled and the tooltip to display.\r\n *\r\n * @param {number} numSelected - Number of selected projects\r\n * @param {Array} projects - Array of all projects\r\n * @param {Array} selected - Array of selected project's ids\r\n *\r\n * @returns {Array} An array containing information about whether the timeline\r\n * button should be disabled and the tooltip to be displayed. First element is a boolean value which\r\n * tells if the button should be disabled or not and the second element is a string for the tooltip.\r\n */\r\n const initTimelineButton = (numSelected, projects, selected) => {\r\n let timeLineButtonTooltip = \"Create Timeline Chart (2 selections required)\";\r\n let timeLineButtonDisabled = true;\r\n if (numSelected > 1) {\r\n const selectedProjects = projects.filter((project) => {\r\n return selected.includes(project.id);\r\n });\r\n const selectedProjectType = selectedProjects[0].type;\r\n let projectTypeEqual = true;\r\n let projectTypeSupported = true;\r\n let allProjectsFinished = true;\r\n let notSupportedMethod = \"\";\r\n\r\n const supportedProjectTypes = [\"Fungilyzer\"];\r\n // check if all selected projects have the same type\r\n for (let i = 1; i < selectedProjects.length; i++) {\r\n if (selectedProjects[i].type !== selectedProjectType) {\r\n projectTypeEqual = false;\r\n }\r\n if (selectedProjects[i].state !== \"success\") {\r\n allProjectsFinished = false;\r\n }\r\n // check if all selected projects are supported\r\n if (!supportedProjectTypes.includes(selectedProjects[i].type)) {\r\n notSupportedMethod = selectedProjects[i].type;\r\n projectTypeSupported = false;\r\n }\r\n }\r\n if (!allProjectsFinished) {\r\n timeLineButtonTooltip =\r\n \"Create Timeline Chart (All projects must be finished)\";\r\n } else if (!projectTypeEqual) {\r\n timeLineButtonTooltip = \"Create Timeline Chart (Method must be equal)\";\r\n } else if (!projectTypeSupported) {\r\n timeLineButtonTooltip =\r\n \"Create Timeline Chart (\" + notSupportedMethod + \" not supported)\";\r\n } else {\r\n timeLineButtonDisabled = false;\r\n timeLineButtonTooltip = \"Create Timeline Chart\";\r\n }\r\n }\r\n return [timeLineButtonDisabled, timeLineButtonTooltip];\r\n };\r\n\r\n const [timeLineButtonDisabled, timeLineButtonTooltip] = initTimelineButton(\r\n numSelected,\r\n projects,\r\n selected\r\n );\r\n\r\n const [mergeResultButtonDisabled, mergeResultButtonTooltip] = initMergeButton(\r\n numSelected,\r\n projects,\r\n selected\r\n );\r\n\r\n return (\r\n 0,\r\n })}\r\n >\r\n
    \r\n {numSelected > 0 ? (\r\n \r\n {numSelected} selected\r\n \r\n ) : (\r\n Projects\r\n )}\r\n
    \r\n \r\n \r\n\r\n
    \r\n
    \r\n {numSelected > 0 ? (\r\n
    \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
    \r\n ) : (\r\n \r\n \r\n fileUploader.current.click()}\r\n size=\"large\"\r\n >\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n
    \r\n \r\n );\r\n};\r\n\r\nEnhancedTableToolbar.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n numSelected: PropTypes.number.isRequired,\r\n onChangeFilter: PropTypes.func,\r\n onCreateTimeLineChartClick: PropTypes.func,\r\n onDeleteClick: PropTypes.func,\r\n onDuplicateSelectedClick: PropTypes.func,\r\n onExportClick: PropTypes.func,\r\n onImportClick: PropTypes.func,\r\n onMergeResultsClick: PropTypes.func,\r\n onMergeSelectedClick: PropTypes.func,\r\n onRunSelectedClick: PropTypes.func,\r\n onTimedRunSelectedClick: PropTypes.func,\r\n projects: PropTypes.arrayOf(PropTypes.object),\r\n searchText: PropTypes.string,\r\n selected: PropTypes.arrayOf(PropTypes.string),\r\n spinloader: PropTypes.object,\r\n user: PropTypes.object,\r\n};\r\n\r\nEnhancedTableToolbar = withStyles(toolbarStyles)(EnhancedTableToolbar);\r\n\r\nconst styles = () => ({\r\n root: {\r\n width: \"100%\",\r\n height: \"100%\",\r\n display: \"grid\",\r\n gridTemplateRows: \"auto auto auto 1fr\",\r\n },\r\n table: {\r\n minWidth: 1020,\r\n },\r\n tableRow: {\r\n cursor: \"pointer\",\r\n },\r\n tableWrapper: {\r\n overflowX: \"auto\",\r\n height: \"100%\",\r\n },\r\n creatingJobBar: {\r\n backgroundColor: darken(\"#216DC0\", 0.3),\r\n },\r\n input: {\r\n width: \"calc(100% - 48px)\",\r\n },\r\n progressBarContainer: {\r\n position: \"relative\",\r\n },\r\n progressBar: {\r\n position: \"absolute\",\r\n left: 0,\r\n top: 0,\r\n width: \"100%\",\r\n lineHeight: \"20px\",\r\n textAlign: \"center\",\r\n },\r\n});\r\n\r\nclass ProjectsTable extends React.Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this._isMounted = false;\r\n this.state = {\r\n order: \"desc\",\r\n orderBy: \"changeDateTime\",\r\n selected: [],\r\n page: 0,\r\n searchText: \"\",\r\n topScrollPos: 0,\r\n bottomScrollPos: 0,\r\n openConfDialog: false,\r\n clickedProjId: null,\r\n };\r\n this.tableContainerRef = React.createRef();\r\n }\r\n\r\n componentDidMount = () => {\r\n this._isMounted = true;\r\n const tableContainerEl = this.tableContainerRef.current;\r\n tableContainerEl.addEventListener(\"scroll\", this.handleScroll);\r\n this.handleScroll();\r\n Backend.loadAvailableProjectTypes(false).then((projectTypes) => {\r\n this.setState({\r\n projectTypes: projectTypes,\r\n projectTypesNames: projectTypes.map((projectType) => projectType.name),\r\n });\r\n });\r\n };\r\n\r\n componentWillUnmount = () => {\r\n const tableContainerEl = this.tableContainerRef.current;\r\n tableContainerEl.removeEventListener(\"scroll\", this.handleScroll);\r\n this._isMounted = false;\r\n };\r\n\r\n handleScroll = () => {\r\n const scrollTop = this.tableContainerRef.current.scrollTop;\r\n // const scrollHeight = this.tableContainerRef.current.scrollHeight;\r\n const clientHeight = this.tableContainerRef.current.clientHeight;\r\n\r\n this.setState({\r\n topScrollPos: scrollTop,\r\n bottomScrollPos: scrollTop + clientHeight,\r\n });\r\n };\r\n\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n onChangeFilter = (e) => {\r\n let searchText = e.target.value;\r\n this.setState({ searchText });\r\n };\r\n\r\n handleRequestSort = (event, property) => {\r\n const orderBy = property;\r\n let order = \"desc\";\r\n\r\n if (this.state.orderBy === property && this.state.order === \"desc\") {\r\n order = \"asc\";\r\n }\r\n\r\n this.setState({ order, orderBy });\r\n };\r\n\r\n handleSelectAllClick = (event) => {\r\n if (event.target.checked) {\r\n this.setState(() => ({\r\n selected: this.props.projects\r\n .filter((project) => {\r\n return this.isJobVisible(project);\r\n })\r\n .map((project) => project.id),\r\n }));\r\n } else {\r\n this.setState({ selected: [] });\r\n }\r\n };\r\n\r\n handleSelectOneClick = (e, project) => {\r\n let selectedObject = this.state.selected;\r\n let selectedIndex = selectedObject.indexOf(project.id);\r\n if (selectedIndex !== -1) selectedObject.splice(selectedIndex, 1);\r\n else selectedObject.push(project.id);\r\n this.setState(() => ({\r\n selected: selectedObject,\r\n }));\r\n e.stopPropagation();\r\n };\r\n\r\n handleClick = (event, project) => {\r\n if (!project.canOpen) {\r\n window.showWarningSnackbar(\"Opening this project forbidden by owner!\");\r\n } else if (this.props.serverIsRunning) {\r\n if (\r\n project.state === \"error\" ||\r\n project.state === \"success\" ||\r\n project.state === \"ready\" ||\r\n project.state === \"pending\" ||\r\n project.state === \"timed\" ||\r\n project.state === \"running\"\r\n ) {\r\n this.props.history.push(viewerType(project.type) + project.id);\r\n }\r\n } else {\r\n window.showWarningSnackbar(\"Local API Server not ready!\");\r\n }\r\n };\r\n\r\n handleContextmenu = (event, project) => {\r\n if (!this.isSelected(project.id)) {\r\n const { selected } = this.state;\r\n selected.push(project.id);\r\n this.setState({ selected });\r\n }\r\n event.preventDefault();\r\n return false;\r\n };\r\n\r\n isSelected = (id) => this.state.selected.indexOf(id) !== -1;\r\n\r\n onRunSelectedClick = (e, id = null, project = null) => {\r\n if (project !== null && project.state === \"success\") {\r\n this.setMountedState({ openConfDialog: true, clickedProjId: id });\r\n } else if (id !== null) {\r\n this.setMountedState({ clickedProjId: id }, () => {\r\n this.setPending(false);\r\n });\r\n } else {\r\n this.setMountedState({ openConfDialog: true });\r\n }\r\n };\r\n\r\n setPending = (evalOnly) => {\r\n if (this.state.clickedProjId) {\r\n Backend.setProjectsPending(this.state.clickedProjId, evalOnly, () => {\r\n console.log(\r\n \"project state changed to pending:\",\r\n this.state.clickedProjId\r\n );\r\n this.setMountedState({ clickedProjId: null });\r\n });\r\n } else {\r\n let projects = this.props.projects;\r\n let projectIds = [];\r\n for (let project of projects) {\r\n for (let id of this.state.selected) {\r\n if (id === project.id && project.canRun) {\r\n projectIds.push(id);\r\n }\r\n }\r\n }\r\n Backend.setProjectsPending(projectIds, evalOnly, () => {\r\n this.setState({ selected: [] });\r\n });\r\n }\r\n };\r\n\r\n onTimedRunSelectedClick = () => {\r\n let projects = this.props.projects;\r\n let projectIds = [];\r\n for (let project of projects) {\r\n for (let id of this.state.selected) {\r\n if (id === project.id && project.canRun) {\r\n projectIds.push(id);\r\n }\r\n }\r\n }\r\n Backend.setProjectsTimed(projectIds, () => {\r\n console.log(\"projects state changed to timed:\", projectIds);\r\n this.setState({ selected: [] });\r\n });\r\n };\r\n\r\n /**\r\n * Import / Export Projects\r\n */\r\n onImportClick = (files) => {\r\n Backend.importProjects(\r\n files[0],\r\n (res) => {\r\n if (res.status === 403) {\r\n window.showErrorSnackbar(\"No Permission to import projects!\");\r\n } else {\r\n this.ImportProjectsDialog.show(res);\r\n this.setState({ selected: [] });\r\n }\r\n this.props.spinloader.hide();\r\n },\r\n (err) => {\r\n this.props.spinloader.hide();\r\n window.openWarningDialog(\"Error importing projects:\\n\" + err);\r\n }\r\n );\r\n };\r\n\r\n onExportClick = () => {\r\n this.props.spinloader.show();\r\n let exportName = \"\";\r\n let numSelected = 0;\r\n for (let project of this.props.projects) {\r\n if (this.state.selected.includes(project.id)) {\r\n if (numSelected === 0) {\r\n exportName += project.name;\r\n }\r\n numSelected++;\r\n }\r\n }\r\n if (numSelected > 1) {\r\n exportName += \"+\" + (numSelected - 1);\r\n }\r\n\r\n Backend.exportProjects(\r\n this.state.selected,\r\n exportName,\r\n () => {\r\n this.props.spinloader.hide();\r\n this.setState({ selected: [] });\r\n },\r\n (error) => {\r\n this.props.spinloader.hide();\r\n window.showErrorSnackbar(\"Exporting Projects failed!\");\r\n window.openErrorDialog(error);\r\n }\r\n );\r\n };\r\n\r\n /**\r\n * Delete selected projects\r\n */\r\n onDeleteClick = () => {\r\n window.openResponseDialog(\r\n \"Do you really want to delete this project?\",\r\n (response) => {\r\n if (response) {\r\n Backend.deleteProjects(this.state.selected, () => {\r\n this.setState({ selected: [] });\r\n });\r\n // get projectnames for selected projectIDs\r\n let projects = this.props.projects.filter((project) =>\r\n this.state.selected.includes(project.id)\r\n );\r\n let projectNames = [];\r\n projects.forEach(function (element) {\r\n Backend.editCaseProjects(\" \", element.id, \"del\");\r\n projectNames.push(element.name);\r\n });\r\n Backend.deleteGalleryExport(projectNames, () => {\r\n this.setState({ selected: [] });\r\n });\r\n }\r\n }\r\n );\r\n };\r\n\r\n onDuplicateSelectedClick = () => {\r\n Backend.duplicateProjects(this.state.selected, () => {\r\n this.setState({ selected: [] });\r\n this.props.handleActiveTabChange(0);\r\n });\r\n };\r\n\r\n onMergeSelectedClick = () => {\r\n let projectType = null;\r\n let projectTypesEqual = true;\r\n for (const selectedProjectId of this.state.selected) {\r\n const selectedProject = this.props.projects.find(\r\n (project) => project.id === selectedProjectId\r\n );\r\n if (projectType === null) {\r\n projectType = selectedProject.type;\r\n } else {\r\n if (projectType !== selectedProject.type) {\r\n projectTypesEqual = false;\r\n break;\r\n }\r\n }\r\n }\r\n if (!projectTypesEqual) {\r\n window.showErrorSnackbar(\"Merge not possible. Types are not equal!\");\r\n return;\r\n }\r\n this.props.spinloader.show();\r\n Backend.mergeProjects(this.state.selected)\r\n .then((result) => {\r\n if (!result.success) {\r\n window.showErrorSnackbar(\"Merge failed!\");\r\n }\r\n if (result.droppedRoisMessages.length > 0) {\r\n window.openInformationDialog(\r\n \"Merge Losses:\",\r\n [\r\n \"Some annotations were not merged because the source projects use at least one file twice and both have annotations.\",\r\n \"The orignal annotations are still available in the original projects.\",\r\n ],\r\n result.droppedRoisMessages\r\n );\r\n }\r\n this.setState({ selected: [] });\r\n this.props.handleActiveTabChange(0);\r\n this.props.spinloader.hide();\r\n })\r\n .catch((error) => {\r\n console.error(\"Error merging projects\", error);\r\n window.openErrorDialog(\"Error merging projects: \" + error);\r\n this.props.spinloader.hide();\r\n });\r\n };\r\n\r\n handleChange = (_, value) => {\r\n if (value !== this.props.activeTab) {\r\n if (value === 1) {\r\n window.document.title = `Finished - HSA Kit ${window.version}`;\r\n } else {\r\n window.document.title = `Projects - HSA Kit ${window.version}`;\r\n }\r\n this.props.handleActiveTabChange(value);\r\n if (this.state.selected.length > 0) {\r\n this.setState({\r\n selected: [],\r\n });\r\n }\r\n }\r\n };\r\n\r\n countFinished(countOther) {\r\n let result = this.props.projects.length;\r\n if (this.props.projects.length > 0) {\r\n result = this.props.projects.reduce(\r\n (acc, cur) => acc + (cur.state === \"success\" ? 1 : 0),\r\n 0\r\n );\r\n }\r\n if (countOther) {\r\n result = this.props.projects.length - result;\r\n }\r\n return result;\r\n }\r\n\r\n isInView = (idx) => {\r\n const { topScrollPos, bottomScrollPos } = this.state;\r\n const headerSpace = 60;\r\n const rowHeight = 81; //including bottom border\r\n\r\n const idxTop = rowHeight * idx + headerSpace;\r\n const idxBottom = idxTop + rowHeight;\r\n\r\n return idxBottom >= topScrollPos && idxTop <= bottomScrollPos;\r\n };\r\n\r\n isJobVisible = (row) => {\r\n const { activeTab } = this.props;\r\n const { searchText } = this.state;\r\n let showJob = false;\r\n //filter if pending or finished\r\n if (searchText !== \"\") {\r\n if (!row.name.toLowerCase().includes(searchText.toLowerCase())) {\r\n return false;\r\n }\r\n }\r\n if (activeTab === 1) {\r\n showJob = row.state === \"success\";\r\n } else {\r\n showJob = row.state !== \"success\";\r\n }\r\n if (this.state.projectTypesNames) {\r\n //filter if job project module exists (release version)\r\n if (showJob) {\r\n return this.state.projectTypesNames.includes(row.type);\r\n } else {\r\n return false;\r\n }\r\n }\r\n return false;\r\n };\r\n\r\n openCreateTimeLineDialog = () => {\r\n this.setState({ createTimeLineChartDialogIsOpen: true });\r\n };\r\n\r\n onMergeResultsClick = () => {\r\n this.props.spinloader.show();\r\n Backend.mergeProjectResults(this.state.selected)\r\n .then((jsonResponse) => {\r\n this.props.history.push(\"/merged_report/\" + jsonResponse.projectsDirId);\r\n this.props.spinloader.hide();\r\n })\r\n .catch((error) => {\r\n console.error(\"Error merging results\", error);\r\n window.openErrorDialog(\"Error merging results\");\r\n this.props.spinloader.hide();\r\n });\r\n };\r\n\r\n closeCreateTimeLineDialog = () => {\r\n this.setState({ createTimeLineChartDialogIsOpen: false });\r\n };\r\n\r\n render() {\r\n const { classes, projects, activeTab, user } = this.props;\r\n const { order, orderBy, selected, searchText } = this.state;\r\n\r\n if (typeof this.props.user.group === \"undefined\") {\r\n authenticationService.logout();\r\n }\r\n\r\n const sortedProjects = stableSort(\r\n projects,\r\n getSorting(order, orderBy)\r\n ).filter((row) => {\r\n return this.isJobVisible(row);\r\n });\r\n\r\n return (\r\n \r\n (this.ImportProjectsDialog = c)}\r\n projectActionMode={ProjectActionMode.Import}\r\n />\r\n (this.FindMissingFiles = c)}\r\n projectActionMode={ProjectActionMode.Update}\r\n />\r\n this.setMountedState({ openConfDialog: false })}\r\n setPending={this.setPending}\r\n />\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {sortedProjects.map((project, idx) => {\r\n const isSelected = this.isSelected(project.id);\r\n if (this.isInView(idx)) {\r\n return (\r\n \r\n );\r\n } else {\r\n return ;\r\n }\r\n })}\r\n \r\n \r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nProjectsTable.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n projects: PropTypes.array,\r\n activeTab: PropTypes.number,\r\n handleActiveTabChange: PropTypes.func,\r\n onEditProject: PropTypes.func,\r\n spinloader: PropTypes.object,\r\n serverIsRunning: PropTypes.bool,\r\n history: PropTypes.object,\r\n user: PropTypes.object,\r\n};\r\n\r\nexport default withRouter(withSpinloader(withStyles(styles)(ProjectsTable)));\r\n","import React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport { withRouter } from \"react-router-dom\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\nimport { Fab, Tooltip } from \"@mui/material\";\r\nimport CircularProgress from \"@mui/material/CircularProgress\";\r\nimport Backend from \"../common/utils/Backend\";\r\nimport AddIcon from \"@mui/icons-material/Add\";\r\n\r\nimport CreateProjectDialog from \"./dialogs/CreateProjectDialog\";\r\nimport ProjectsTable from \"./components/ProjectsTable\";\r\n\r\nimport { authenticationService } from \"../common/services\";\r\n\r\n/**\r\n * Adds leading zeros to a number\r\n * @param {Number} num Number\r\n * @param {Number} size length that the number should have\r\n * @returns {String} String of number with zero padding\r\n */\r\nfunction pad(num, size) {\r\n var s = num + \"\";\r\n while (s.length < size) s = \"0\" + s;\r\n return s;\r\n}\r\n\r\n/**\r\n * Generates a default name for new Projects like \"Project 001\"\r\n * @param {Object[]} data List of Projects\r\n * @returns {String} Smart Default name for a new project\r\n */\r\nfunction incrementDefaultName(data) {\r\n let newDefaultName = \"Project 001\";\r\n let maxProjNum = 0;\r\n for (let proj of data) {\r\n if (proj.name.match(\"Project [0-9][0-9][0-9]\")) {\r\n const projNum = parseInt(proj.name.replace(\"Project \", \"\"), 10);\r\n let newMaxProjNum = Math.max(maxProjNum, projNum);\r\n if (newMaxProjNum) maxProjNum = newMaxProjNum;\r\n }\r\n }\r\n newDefaultName = `Project ${pad(maxProjNum + 1, 3)}`;\r\n return newDefaultName;\r\n}\r\n\r\nconst styles = (theme) => ({\r\n root: { height: \"100%\", overflow: \"hidden\" },\r\n fab: {\r\n position: \"absolute\",\r\n bottom: theme.spacing(2),\r\n right: theme.spacing(2),\r\n },\r\n});\r\n\r\nclass HomePage extends Component {\r\n constructor(props) {\r\n super(props);\r\n this._isMounted = false;\r\n this.state = {\r\n editableProject: null,\r\n projects: [],\r\n open: false,\r\n newDefaultName: \"Project 001\",\r\n activeTab: 0,\r\n serverIsRunning: false,\r\n user: { group: {} },\r\n };\r\n\r\n Backend.getCurrentUser((user) => {\r\n if (user.fullName === null) {\r\n authenticationService.logout();\r\n } else {\r\n this.setState({ user });\r\n }\r\n });\r\n this.checkPythonServer();\r\n }\r\n checkPythonServer = () => {\r\n Backend.isLocalServerReady((result) => {\r\n if (this.state.serverIsRunning !== result) {\r\n this.setMountedState({ serverIsRunning: result });\r\n }\r\n if (!result) {\r\n setTimeout(this.checkPythonServer, 2000);\r\n }\r\n });\r\n };\r\n\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n handleClickOpen = () => {\r\n Backend.getLicensingInfo((license) => {\r\n if (license.licenseStatus === \"VALID\") {\r\n this.setMountedState({\r\n editableProject: null,\r\n open: true,\r\n });\r\n } else {\r\n authenticationService.logout();\r\n this.props.history.push(\"/licensing\");\r\n }\r\n });\r\n };\r\n\r\n handleEditOpen = (project) => {\r\n this.setMountedState({\r\n editableProject: project,\r\n open: true,\r\n });\r\n };\r\n\r\n handleClose = () => {\r\n this.setMountedState({\r\n editableProject: null,\r\n open: false,\r\n });\r\n this.refreshProjects();\r\n };\r\n\r\n componentDidMount() {\r\n this._isMounted = true;\r\n this.refreshProjectsInterval();\r\n const activeTab = localStorage.getItem(\"activeProjectTab\");\r\n if (activeTab) this.setMountedState({ activeTab: parseInt(activeTab) });\r\n }\r\n\r\n componentWillUnmount() {\r\n this._isMounted = false;\r\n clearInterval(this.refreshInterval);\r\n }\r\n\r\n refreshProjectsInterval() {\r\n this.refreshProjects(() => {\r\n setTimeout(() => this.refreshProjectsInterval(), 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Refreshes the list of projects.\r\n * @param {function} callback Runs after projects are refreshed, withouth parameters. Default is empty function.\r\n * @returns {} Nothing.\r\n */\r\n refreshProjects(callback = () => {}) {\r\n if (!this._isMounted) return;\r\n Backend.listProjects(\r\n (data) => {\r\n let projectsChanged =\r\n JSON.stringify(this.state.projects) !== JSON.stringify(data);\r\n if (projectsChanged) {\r\n this.setMountedState({\r\n projects: data,\r\n newDefaultName: incrementDefaultName(data),\r\n });\r\n }\r\n callback();\r\n },\r\n (error) => {\r\n if (this._isMounted && callback) {\r\n console.error(\r\n \"Error loading projects, reloading page might help. Error: \" + error\r\n );\r\n callback();\r\n }\r\n }\r\n );\r\n }\r\n handleActiveTabChange = (activeTabIndex) => {\r\n if (this.state.activeTab !== activeTabIndex) {\r\n this.setMountedState({ activeTab: activeTabIndex });\r\n localStorage.setItem(\"activeProjectTab\", activeTabIndex);\r\n }\r\n };\r\n\r\n render() {\r\n const { classes } = this.props;\r\n const { serverIsRunning } = this.state;\r\n return (\r\n
    \r\n \r\n \r\n {\r\n if (serverIsRunning) {\r\n this.handleClickOpen();\r\n } else {\r\n window.showWarningSnackbar(\"Local API Server not ready!\");\r\n }\r\n }}\r\n >\r\n {serverIsRunning ? (\r\n \r\n ) : (\r\n \r\n )}\r\n \r\n \r\n \r\n
    \r\n );\r\n }\r\n}\r\n\r\nHomePage.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n history: PropTypes.object,\r\n};\r\n\r\nexport default withRouter(withStyles(styles)(HomePage));\r\n","// NavigationBar.jsx\r\n\r\n// Copyright HS Analysis GmbH, 2020\r\n// Author: Sebastian Murgul, Viktor Eberhardt\r\n\r\n// Framework imports\r\nimport React, { Component } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport { withRouter } from \"react-router-dom\";\r\n\r\n// External npm packages\r\nimport AppBar from \"@mui/material/AppBar\";\r\nimport Toolbar from \"@mui/material/Toolbar\";\r\nimport Typography from \"@mui/material/Typography\";\r\nimport Button from \"@mui/material/Button\";\r\nimport {\r\n Popper,\r\n Grow,\r\n Paper,\r\n ClickAwayListener,\r\n MenuList,\r\n MenuItem,\r\n SvgIcon,\r\n Tooltip,\r\n} from \"@mui/material\";\r\nimport {\r\n ArrowDropDown,\r\n Person,\r\n ExitToApp,\r\n CoPresent,\r\n Build,\r\n Info,\r\n History,\r\n} from \"@mui/icons-material\";\r\nimport PermMediaIcon from \"@mui/icons-material/PermMedia\";\r\nimport FolderCopyIcon from \"@mui/icons-material/FolderCopy\";\r\nimport WorkIcon from \"@mui/icons-material/Work\";\r\nimport BarChartIcon from \"@mui/icons-material/BarChart\";\r\nimport ScannerIcon from \"@mui/icons-material/Scanner\";\r\nimport ScreenShareIcon from \"@mui/icons-material/ScreenShare\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\n// HSA Packages\r\nimport Backend from \"../utils/Backend\";\r\nimport { authenticationService } from \"../services\";\r\nimport { viewerType } from \"../utils/Utils\";\r\n\r\nconst styles = (theme) => ({\r\n root: {\r\n height: \"100vh\",\r\n },\r\n grow: {\r\n flexGrow: 1,\r\n },\r\n menuButton: {\r\n marginLeft: -12,\r\n marginRight: 20,\r\n height: 50,\r\n cursor: \"pointer\",\r\n },\r\n appbarPlaceholder: theme.mixins.toolbar,\r\n headerButton: {\r\n textTransform: \"none\",\r\n height: 64,\r\n padding: \"0 20px\",\r\n borderRadius: 0,\r\n },\r\n menu: {\r\n transformOrigin: \"center top\",\r\n marginTop: 7,\r\n marginLeft: -40,\r\n minWidth: 200,\r\n },\r\n menuIcon: {\r\n marginRight: 10,\r\n color: \"#444\",\r\n },\r\n warningColor: {\r\n color: theme.palette.warning.main,\r\n },\r\n errorColor: {\r\n color: theme.palette.error.main,\r\n },\r\n});\r\n\r\nclass NavigationBar extends Component {\r\n constructor(props) {\r\n super(props);\r\n\r\n this._isMounted = false;\r\n this.state = {\r\n currentUser: null,\r\n open: false,\r\n headline: \"\",\r\n showDevButtons: false,\r\n resultsPath: \"\",\r\n isResultsButtonVisible: false,\r\n extraButtonState: \"\", //none, results, project\r\n scannerState: null,\r\n expirationMessage: \"\",\r\n canAccessLicensingPage: false,\r\n canAccessAdminPage: false,\r\n canAccessAITab: false,\r\n canAccessCases: false,\r\n canAccessScan: false,\r\n canAccessFileView: false,\r\n };\r\n\r\n window.setNavigationbarTitle = this.setNavigationbarTitle;\r\n }\r\n\r\n // check if report button should be shown\r\n // and check if report exist\r\n checkProjectButton = (pathname) => {\r\n let isResultsButtonVisible =\r\n pathname.includes(\"/view/\") || pathname.includes(\"/esr_view/\");\r\n if (this.state.isResultsButtonVisible !== isResultsButtonVisible) {\r\n this.setMountedState({ isResultsButtonVisible });\r\n }\r\n if (isResultsButtonVisible) {\r\n let uuid = pathname.split(\"view/\").slice(-1)[0];\r\n let dir_path = \"/\" + uuid;\r\n Backend.walkProjectDirFiles(dir_path, (result) => {\r\n let reportExists = false;\r\n for (let row of result) {\r\n if (\r\n row.path.endsWith(\"report.xlsx\") ||\r\n row.path.endsWith(\"report.xlsm\")\r\n ) {\r\n reportExists = true;\r\n break;\r\n }\r\n }\r\n this.setMountedState({\r\n resultsPath: reportExists ? \"/report/\" + uuid : \"\",\r\n extraButtonState: \"results\",\r\n });\r\n });\r\n } else {\r\n if (pathname.includes(\"/report/\")) {\r\n const uuid = pathname.split(\"report/\").slice(-1)[0];\r\n Backend.loadProject(uuid)\r\n .then((project) => {\r\n this.setMountedState({\r\n extraButtonState: \"project\",\r\n projectPath: viewerType(project.type) + uuid,\r\n });\r\n })\r\n .catch(() => {\r\n console.info(\r\n \"Project not found, probably a merged results project!\"\r\n );\r\n });\r\n } else {\r\n this.setMountedState({\r\n extraButtonState: \"\",\r\n projectPath: \"\",\r\n });\r\n }\r\n }\r\n };\r\n\r\n componentDidMount() {\r\n this._isMounted = true;\r\n if (this.props.location.pathname === \"/iframe.html\") return;\r\n\r\n //on first load\r\n this.checkProjectButton(location.pathname);\r\n this.setPageHeadline();\r\n\r\n //on path change\r\n this.props.history.listen((location) => {\r\n this.setPageHeadline();\r\n this.checkProjectButton(location.pathname);\r\n });\r\n\r\n authenticationService.currentUser.subscribe((x) => {\r\n if (!x) return;\r\n this.setMountedState({\r\n currentUser: x,\r\n });\r\n this.updateUserGroups();\r\n });\r\n\r\n Backend.getLicensingInfo((license) => {\r\n if (license.licenseStatus === \"VALID\") {\r\n this.setMountedState({\r\n editableProject: null,\r\n open: false,\r\n });\r\n } else {\r\n authenticationService.logout();\r\n this.props.history.push(\"/licensing\");\r\n }\r\n let scannerState = \"INVALID\";\r\n let expirationMessage = \"\";\r\n if (license.activeModules.length === 0) {\r\n scannerState = \"VALID\";\r\n } else {\r\n const scannerData = license.activeModules.find(\r\n (item) => item.name === \"HSAScanner\"\r\n );\r\n if (!scannerData) return;\r\n\r\n const expirationDays = scannerData.expiresInDays;\r\n if (expirationDays < 31) {\r\n if (expirationDays < 0) {\r\n expirationMessage =\r\n expirationDays === -1\r\n ? \"Expired for 1 day!\"\r\n : \"Expired for \" + expirationDays + \" days!\";\r\n } else {\r\n expirationMessage =\r\n expirationDays === -1\r\n ? \"Expires in 1 day!\"\r\n : \"Expires in \" + expirationDays + \" days!\";\r\n }\r\n }\r\n scannerState = scannerData.isExpired ? \"EXPIRED\" : \"VALID\";\r\n }\r\n\r\n this.setMountedState({ scannerState, expirationMessage });\r\n });\r\n }\r\n\r\n componentWillUnmount() {\r\n this._isMounted = false;\r\n }\r\n\r\n setMountedState = (stateObject, callback) => {\r\n if (this._isMounted) {\r\n this.setState(stateObject, callback);\r\n }\r\n };\r\n\r\n updateUserGroups = () => {\r\n Backend.getCurrentUser((user) => {\r\n if (!user.group) return;\r\n\r\n this.setState({\r\n canAccessLicensingPage: user.group.canAccessLicensingPage,\r\n canAccessAdminPage: user.group.canAccessAdminPage,\r\n canAccessAITab: user.group.canAccessAITab,\r\n canAccessCases: user.group.name === \"Admin\",\r\n canAccessScan: user.group.name === \"Admin\",\r\n canAccessFileView: user.group.name === \"Admin\",\r\n });\r\n });\r\n };\r\n\r\n setNavigationbarTitle = (title) => {\r\n this.setMountedState({ headline: title });\r\n };\r\n\r\n logout = () => {\r\n authenticationService.logout();\r\n this.props.history.push(\"/login\");\r\n };\r\n\r\n handleMenu() {\r\n this.setMountedState((state) => ({ open: !state.open }));\r\n }\r\n\r\n handleClose(event) {\r\n if (this.anchorEl.contains(event.target)) {\r\n return;\r\n }\r\n\r\n this.setMountedState({ open: false });\r\n }\r\n\r\n setPageHeadline() {\r\n if (this.props.location.pathname === \"/iframe.html\") return;\r\n let path = window.location.href;\r\n const titleMap = {\r\n \"/view/\": \"Viewer\",\r\n \"/report/\": \"Results\",\r\n \"/admin\": \"Admin Settings\",\r\n \"/login\": \"Login\",\r\n \"/about\": \"About\",\r\n \"/cases\": \"Cases\",\r\n \"/file_view\": \"Files\",\r\n \"/ai_view\": \"AI\",\r\n \"/classroom\": \"Classroom\",\r\n \"/prediction\": \"Prediction\",\r\n \"/licensing\": \"Licenseing\",\r\n \"/scan_view\": \"Scan Viewer\",\r\n };\r\n Backend.getVersion((data) => {\r\n let title = \"Projects\";\r\n for (const pathFragment in titleMap) {\r\n if (path.includes(pathFragment)) {\r\n title = titleMap[pathFragment];\r\n break;\r\n }\r\n }\r\n\r\n const fullVersion = data.version.split(\".\");\r\n const versionLength = fullVersion.length;\r\n const version =\r\n versionLength > 3 ? fullVersion.slice(0, 3).join(\".\") : data.version;\r\n window.document.title = `${title} - HSA Kit ${version}`;\r\n });\r\n let headline = \"Home\";\r\n for (const pathFragment in titleMap) {\r\n if (path.includes(pathFragment)) {\r\n headline = titleMap[pathFragment];\r\n break;\r\n }\r\n }\r\n if (this.state.headline !== headline) {\r\n this.setMountedState({ headline: headline });\r\n }\r\n return headline;\r\n }\r\n\r\n render() {\r\n const {\r\n currentUser,\r\n open,\r\n showDevButtons,\r\n scannerState,\r\n expirationMessage,\r\n canAccessLicensingPage,\r\n canAccessAdminPage,\r\n } = this.state;\r\n const { classes } = this.props;\r\n\r\n return (\r\n \r\n \r\n this.props.history.push(\"/\")}\r\n alt=\"hsa logo\"\r\n src=\"/img/hsa_logo.png\"\r\n />\r\n Backend.ping()}\r\n >\r\n {this.state.headline}\r\n \r\n \r\n {currentUser ? (\r\n \r\n {/* hidden log file download button */}\r\n {\r\n Backend.getAbout((result) => {\r\n if (result.logFiles && result.logFiles.length > 0) {\r\n let newestLogFile = result.logFiles[0];\r\n\r\n const a = document.createElement(\"a\");\r\n let url =\r\n \"api/about/logfile?name=\" +\r\n window.decodeURIComponent(newestLogFile);\r\n a.href = url;\r\n a.download = url.split(\"/\").pop();\r\n document.body.appendChild(a);\r\n a.click();\r\n document.body.removeChild(a);\r\n }\r\n });\r\n }}\r\n >
    \r\n {\r\n this.props.history.push(\"/\");\r\n this.setState({ headline: \"Home\" });\r\n }}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n \r\n Projects\r\n \r\n\r\n {\r\n this.props.history.push(\"/ai_view\");\r\n this.setState({ headline: \"AI Viewer\" });\r\n }}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n AI\r\n \r\n\r\n this.props.history.push(\"/cases\")}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n Cases\r\n \r\n\r\n \r\n \r\n this.props.history.push(\"/file_view\")}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n Files\r\n \r\n \r\n \r\n\r\n \r\n \r\n {\r\n this.props.history.push(\"/scan_view\");\r\n }}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n \r\n Scan\r\n \r\n \r\n \r\n \r\n\r\n {this.state.extraButtonState !== \"\" && (\r\n \r\n {this.state.extraButtonState === \"results\" ? (\r\n \r\n this.props.history.push(this.state.resultsPath)\r\n }\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n \r\n \r\n \r\n \r\n Results\r\n \r\n ) : (\r\n {\r\n this.props.history.push(this.state.projectPath);\r\n }}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n Project\r\n \r\n )}\r\n \r\n )}\r\n\r\n {showDevButtons && (\r\n \r\n this.props.history.push(\"/prediction\")}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n Prediction\r\n \r\n {\r\n if (window.location.href.includes(\"/view/\")) {\r\n window.toggleClassRoomChat();\r\n } else {\r\n window.openWarningDialog(\"Please open a Project first\");\r\n }\r\n }}\r\n className={classes.headerButton}\r\n color=\"inherit\"\r\n >\r\n \r\n Classroom\r\n \r\n \r\n )}\r\n\r\n {\r\n this.anchorEl = node;\r\n }}\r\n className={classes.headerButton}\r\n aria-owns={open ? \"menu-appbar\" : undefined}\r\n aria-haspopup=\"true\"\r\n onClick={() => this.handleMenu()}\r\n color=\"inherit\"\r\n >\r\n \r\n {currentUser.fullName}\r\n \r\n \r\n \r\n {({ TransitionProps }) => (\r\n \r\n \r\n this.handleClose(e)}\r\n >\r\n \r\n {canAccessAdminPage && (\r\n this.props.history.push(\"/admin\")}\r\n >\r\n \r\n Admin\r\n \r\n )}\r\n {canAccessLicensingPage && (\r\n {\r\n this.props.history.push(\"/licensing\");\r\n }}\r\n >\r\n \r\n Licensing Page\r\n \r\n )}\r\n \r\n this.props.history.push(\"/userhistory\")\r\n }\r\n >\r\n \r\n User Access History\r\n \r\n this.props.history.push(\"/about\")}\r\n >\r\n \r\n About / Help\r\n \r\n \r\n \r\n Logout\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n ) : (\r\n this.props.history.push(\"/login\")}\r\n >\r\n Sign In\r\n \r\n )}\r\n \r\n \r\n );\r\n }\r\n}\r\n\r\nNavigationBar.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n history: PropTypes.object,\r\n location: PropTypes.object,\r\n};\r\n\r\nexport default withRouter(withStyles(styles)(NavigationBar));\r\n","// App.jsx:\r\n// Main component of the application. Contains the routing and global snackbar functions.\r\n\r\n// Copyright HS Analysis GmbH, 2019\r\n// Author: Viktor Eberhardt\r\n\r\n// Framework imports\r\nimport \"./css/global.css\";\r\nimport React, { Component, Suspense, lazy } from \"react\";\r\nimport { Route } from \"react-router-dom\";\r\nimport PropTypes from \"prop-types\";\r\n\r\n// External packages\r\nimport { withSnackbar } from \"notistack\";\r\nimport Box from \"@mui/material/Box\";\r\nimport Button from \"@mui/material/Button\";\r\nimport CircularProgress from \"@mui/material/CircularProgress\";\r\nimport Typography from \"@mui/material/Typography\";\r\nimport withStyles from \"@mui/styles/withStyles\";\r\n\r\n// HSA packages\r\nimport { PrivateRoute } from \"./common/components\";\r\nimport { Role } from \"./common/utils\";\r\nimport { TilesProvider } from \"./viewer/contexts/TilesContext\";\r\nimport { AIContextProvider } from \"./aiViewer/AIContext\";\r\nimport CustomDialog from \"./common/components/CustomDialog\";\r\nimport HomePage from \"./home/HomePage\";\r\nimport NavigationBar from \"./common/components/NavigationBar\";\r\n\r\nimport PersistentStorageProvider from \"./viewer/contexts/PersistentStorageContext\";\r\nimport ProjectHistoryProvider from \"./viewer/contexts/ProjectHistoryContext\";\r\nimport ProjectProvider from \"./viewer/contexts/ProjectContext\";\r\nimport ResultTabProvider from \"./viewer/contexts/ResultTabContext\";\r\nimport ScanProvider from \"./scanViewer/contexts/ScanViewerContext\";\r\nimport SpectraViewerProvider from \"./spectraViewer/contexts/SpectraViewerContext\";\r\n\r\n//Components\r\nconst AboutPage = lazy(() => import(\"./about/AboutPage\"));\r\nconst AdminPage = lazy(() => import(\"./admin/AdminPage\"));\r\nconst AudioViewer = lazy(() => import(\"./audioViewer/AudioViewer\"));\r\nconst AIViewer = lazy(() => import(\"./aiViewer/AIViewer\"));\r\nconst CasesPage = lazy(() => import(\"./cases/CasesPage\"));\r\nconst FileViewer = lazy(() => import(\"./fileViewer/FileViewer\"));\r\nconst PredictionPage = lazy(() => import(\"./prediction/PredictionPage\"));\r\nconst ProteomViewer = lazy(() => import(\"./proteomViewer/ProteomViewer\"));\r\nconst Report = lazy(() => import(\"./home/Report\"));\r\nconst ScanViewer = lazy(() => import(\"./scanViewer/ScanViewer\"));\r\nconst SpectraViewer = lazy(() => import(\"./spectraViewer/SpectraViewer\"));\r\nconst Viewer = lazy(() => import(\"./viewer/Viewer\"));\r\nconst LoginPage = lazy(() => import(\"./account/LoginPage\"));\r\nconst LicensingPage = lazy(() => import(\"./licensing/LicensingPage\"));\r\nconst SettingsPage = lazy(() => import(\"./settings/SettingsPage\"));\r\nconst UserHistoryPage = lazy(() => import(\"./userhistory/UserHistoryPage\"));\r\n\r\nconst styles = (theme) => ({\r\n root: {\r\n height: \"100vh\",\r\n display: \"grid\",\r\n gridTemplateRows: \"auto 1fr\",\r\n },\r\n menuButton: {\r\n marginLeft: -12,\r\n marginRight: 20,\r\n height: 50,\r\n },\r\n appbarPlaceholder: theme.mixins.toolbar,\r\n});\r\n\r\nfunction SuspenseFallback() {\r\n return (\r\n \r\n \r\n Loading Page Data...\r\n \r\n );\r\n}\r\n\r\nclass App extends Component {\r\n static displayName = App.name;\r\n\r\n render() {\r\n const { classes } = this.props;\r\n\r\n /**\r\n * Adds a green success snackbar at bottom left of window.\r\n * @param {string} str Message to display.\r\n */\r\n window.showSuccessSnackbar = (str) => {\r\n this.props.enqueueSnackbar(str, {\r\n variant: \"success\",\r\n });\r\n };\r\n\r\n /**\r\n * Adds an orange warning snackbar at bottom left of window.\r\n * @param {string} str Message to display.\r\n */\r\n window.showWarningSnackbar = (str) => {\r\n this.props.enqueueSnackbar(str, {\r\n variant: \"warning\",\r\n });\r\n };\r\n\r\n /**\r\n * Adds a red error snackbar at bottom left of window.\r\n * @param {string} str Message to display.\r\n */\r\n window.showErrorSnackbar = (str) => {\r\n this.props.enqueueSnackbar(str, {\r\n variant: \"error\",\r\n });\r\n };\r\n\r\n /**\r\n * Adds a black info snackbar at bottom left of window.\r\n * @param {string} str Message to display.\r\n * @param {function} action Action to perform once confirmed by user.\r\n * @param {string} action_msg Message displayed on the primary button.\r\n * @param {string} hide_msg Optional. Message displayed on dismiss button. If undefined, button will be hidden.\r\n */\r\n window.showActionSnackbar = (str, action, action_msg, hide_msg) => {\r\n // Close the old snackbar before showing the new one\r\n this.props.closeSnackbar();\r\n\r\n this.props.enqueueSnackbar(str, {\r\n action: (sbId) => (\r\n <>\r\n {\r\n action();\r\n this.props.closeSnackbar(sbId);\r\n }}\r\n >\r\n {action_msg}\r\n \r\n {(hide_msg || hide_msg === 0) && hide_msg && (\r\n this.props.closeSnackbar(sbId)}\r\n >\r\n {hide_msg}\r\n \r\n )}\r\n \r\n ),\r\n persist: true,\r\n });\r\n };\r\n\r\n return (\r\n
    \r\n
    \r\n\r\n }>\r\n (\r\n \r\n )}\r\n />\r\n (\r\n \r\n \r\n \r\n )}\r\n />\r\n } />\r\n (\r\n \r\n )}\r\n />\r\n (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n />\r\n (\r\n \r\n \r\n \r\n )}\r\n />\r\n (\r\n \r\n \r\n \r\n )}\r\n />\r\n\r\n }\r\n />\r\n (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n )}\r\n />\r\n }\r\n />\r\n }\r\n />\r\n } />\r\n } />\r\n\r\n } />\r\n }\r\n />\r\n } />\r\n \r\n \r\n\r\n } />\r\n \r\n \r\n
    \r\n );\r\n }\r\n}\r\n\r\nApp.propTypes = {\r\n classes: PropTypes.object.isRequired,\r\n enqueueSnackbar: PropTypes.func.isRequired,\r\n closeSnackbar: PropTypes.func.isRequired,\r\n};\r\n\r\nexport default withSnackbar(withStyles(styles)(App));\r\n","// In production, we register a service worker to serve assets from local cache.\r\n\r\n// This lets the app load faster on subsequent visits in production, and gives\r\n// it offline capabilities. However, it also means that developers (and users)\r\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\r\n// cached resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\r\n// This link also includes instructions on opting out of this behavior.\r\n\r\nconst isLocalhost = Boolean(\r\n window.location.hostname === 'localhost' ||\r\n // [::1] is the IPv6 localhost address.\r\n window.location.hostname === '[::1]' ||\r\n // 127.0.0.1/8 is considered localhost for IPv4.\r\n window.location.hostname.match(\r\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\r\n )\r\n);\r\n\r\nexport default function register () {\r\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\r\n // The URL constructor is available in all browsers that support SW.\r\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location);\r\n if (publicUrl.origin !== window.location.origin) {\r\n // Our service worker won't work if PUBLIC_URL is on a different origin\r\n // from what our page is served on. This might happen if a CDN is used to\r\n // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374\r\n return;\r\n }\r\n\r\n window.addEventListener('load', () => {\r\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\r\n\r\n if (isLocalhost) {\r\n // This is running on localhost. Lets check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl);\r\n } else {\r\n // Is not local host. Just register service worker\r\n registerValidSW(swUrl);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW (swUrl) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then(registration => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the old content will have been purged and\r\n // the fresh content will have been added to the cache.\r\n // It's the perfect time to display a \"New content is\r\n // available; please refresh.\" message in your web app.\r\n console.log('New content is available; please refresh.');\r\n } else {\r\n // At this point, everything has been precached.\r\n // It's the perfect time to display a\r\n // \"Content is cached for offline use.\" message.\r\n console.log('Content is cached for offline use.');\r\n }\r\n }\r\n };\r\n };\r\n })\r\n .catch(error => {\r\n console.error('Error during service worker registration:', error);\r\n });\r\n}\r\n\r\nfunction checkValidServiceWorker (swUrl) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl)\r\n .then(response => {\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n if (\r\n response.status === 404 ||\r\n response.headers.get('content-type').indexOf('javascript') === -1\r\n ) {\r\n // No service worker found. Probably a different app. Reload the page.\r\n navigator.serviceWorker.ready.then(registration => {\r\n registration.unregister().then(() => {\r\n window.location.reload();\r\n });\r\n });\r\n } else {\r\n // Service worker found. Proceed as normal.\r\n registerValidSW(swUrl);\r\n }\r\n })\r\n .catch(() => {\r\n console.log(\r\n 'No internet connection found. App is running in offline mode.'\r\n );\r\n });\r\n}\r\n\r\nexport function unregister () {\r\n if ('serviceWorker' in navigator) {\r\n navigator.serviceWorker.ready.then(registration => {\r\n registration.unregister();\r\n });\r\n }\r\n}\r\n","import \"bootstrap/dist/css/bootstrap.css\";\r\nimport React from \"react\";\r\nimport ReactDOM from \"react-dom\";\r\nimport { BrowserRouter } from \"react-router-dom\";\r\nimport App from \"./App\";\r\nimport { unregister as unregisterServiceWorker } from \"./registerServiceWorker\";\r\nimport SpinloaderProvider from \"./common/components/Spinloader\";\r\n\r\nimport {\r\n ThemeProvider,\r\n StyledEngineProvider,\r\n createTheme,\r\n} from \"@mui/material/styles\";\r\nimport { SnackbarProvider } from \"notistack\";\r\n\r\nconst baseUrl = document.getElementsByTagName(\"base\")[0].getAttribute(\"href\");\r\nconst rootElement = document.getElementById(\"root\");\r\nexport const theme = createTheme({\r\n palette: {\r\n selected: {\r\n main: \"rgba(0, 0, 0, 0.2)\",\r\n },\r\n primary: {\r\n // light: will be calculated from palette.primary.main,\r\n main: \"#0673C1\",\r\n inactive: \"rgba(0, 0, 0, 0.54)\",\r\n // dark: will be calculated from palette.primary.main,\r\n // contrastText: will be calculated to contrast with palette.primary.main\r\n },\r\n secondary: {\r\n // light: will be calculated from palette.primary.main,\r\n main: \"#182A42\",\r\n // dark: will be calculated from palette.primary.main,\r\n // contrastText: will be calculated to contrast with palette.primary.main\r\n },\r\n icon: {\r\n main: \"rgba(0, 0, 0, 0.54)\",\r\n },\r\n default: {\r\n main: \"#ffffff\",\r\n },\r\n error: {\r\n main: \"#d84646\",\r\n },\r\n success: {\r\n main: \"#4e9a51\",\r\n },\r\n warning: {\r\n main: \"#f68a1c\",\r\n },\r\n },\r\n typography: {\r\n useNextVariants: true,\r\n },\r\n});\r\n\r\nReactDOM.render(\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ,\r\n rootElement\r\n);\r\n\r\nunregisterServiceWorker();\r\n","// Copyright HS Analysis GmbH, 2023\r\n// Author: Valentin Haas\r\n\r\n// Description: Structure model for annotation categorization.\r\n\r\n// Keep in sync with C# and js frontend:\r\n// Source\\HSA-KIT\\Database\\Model\\Structure.cs\r\n// Source\\HSA-KIT\\ClientApp\\src\\common\\components\\Structure.jsx\r\n// Source\\HSA-KIT\\modules\\hsa\\core\\models\\structure.py\r\n\r\n// HSA imports\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n downloadJsonObjectAsFile,\r\n isHexColor,\r\n requestFileInput,\r\n validateInstance,\r\n validateType,\r\n ValidationType,\r\n} from \"../utils/Utils\";\r\nimport { convertDateToShortIsoString } from \"../utils/Localization\";\r\nimport InstantAnalysisModule from \"./InstantAnalysisModule\";\r\n\r\n/**\r\n * Structure class used for annotation categorization.\r\n * For structure documentation see https://hsa.atlassian.net/wiki/spaces/HSAKIT/pages/16116235173917/Annotations+Data+Structure\r\n */\r\nexport default class Structure {\r\n /**\r\n * Maximum id used, to avoid duplicate ids.\r\n */\r\n static maxId = 0;\r\n static __setMaxId = (val) => (Structure.maxId = val);\r\n\r\n /**\r\n * Create a Structure object with all parameters.\r\n * @param {uint} id Unique identifier for the structure.\r\n * @param {string} label Visible name of structure.\r\n * @param {boolean} isStructure Distinction between class (formaly subtype) and (sub-)structure. Defaults to true.\r\n * @param {string} color Color of the structure. Defaults to #FFFFFF.\r\n * @param {boolean} isDynamic Whether or not the user is allowed to delete/add substructures/classes to this structure. Defaults to true.\r\n * @param {uint} parentId Parent key, should the structure be a substructure. Defaults to null.\r\n * @param {uint} sameLevelRank Defines te order in which multiple strucutures on the same level with the same parent are displayed. Defaults to 0.\r\n * @param {boolean} isInversed Whether or not the structure is inversed. i.e. everything not annotated appears as annotated.\r\n * @param {boolean} isUnfolded Whether or not the children of a structure are visible. Defaults to false.\r\n * @param {boolean} annotationsAreVisible Whether or not the annotations of the structure are shown. Defaults to true.\r\n * @param {boolean} hasChildren Whether or not a structure has children. Defaults to false.\r\n * @param {uint} nestingDepth How deep a structure is nested inside other structures. Defaults to 0.\r\n * @param {ulong} totalObjectCount Annotation count over all contained r-Trees. Defaults to 0.\r\n * @param {boolean} canBeChosen Optional. Whether or not the structure can be chosen. Defaults to true.\r\n * @param {boolean} isChosen Optional. Whether or not the structure is chosen. Defaults to false.\r\n * @param {string | InstantAnalysisModule[]} toolSettings Optional. IAMs for this structure and their parameters. Strings will bne parsed to InstantAnalysisModule[]. Defaults to [].\r\n * @param {List[object]} optionalParams Optional. Project-specific optional parameters not covered by the attributes above. Defaults to null.\r\n */\r\n constructor(\r\n id,\r\n label,\r\n isStructure = true,\r\n color = \"#FFFFFF\",\r\n isDynamic = true,\r\n parentId = null,\r\n sameLevelRank = 0,\r\n isInversed = false,\r\n isUnfolded = false,\r\n annotationsAreVisible = true,\r\n hasChildren = false,\r\n nestingDepth = 0,\r\n totalObjectCount = 0,\r\n canBeChosen = true,\r\n isChosen = false,\r\n toolSettings = [],\r\n optionalParams = null\r\n ) {\r\n // Input validation\r\n validateType(\"id\", id, ValidationType.Int);\r\n if (id <= 0)\r\n throw RangeError(\r\n `id must be of type integer > 0, received ${typeof id}: ${id}`\r\n );\r\n\r\n validateType(\"label\", label, ValidationType.String);\r\n validateType(\"isStructure\", isStructure, ValidationType.Bool);\r\n if (\r\n !isHexColor(color) &&\r\n label !== \"Base ROI\" &&\r\n color !== \"rgba(0, 0, 0, 0.0)\"\r\n )\r\n throw TypeError(\r\n `color must be a valid hexColor, received ${typeof color}: ${color}`\r\n );\r\n validateType(\"isDynamic\", isDynamic, ValidationType.Bool);\r\n\r\n if (parentId !== null)\r\n validateType(\"parentId\", parentId, ValidationType.Int);\r\n if (parentId !== null && parentId <= 0)\r\n throw RangeError(\r\n `parentId must be of type integer > 0, received ${typeof parentId}: ${parentId}`\r\n );\r\n\r\n validateType(\"sameLevelRank\", sameLevelRank, ValidationType.Int);\r\n if (sameLevelRank < 0) {\r\n throw RangeError(\r\n `sameLevelRank must be of type integer >= 0, received ${typeof sameLevelRank}: ${sameLevelRank}`\r\n );\r\n }\r\n validateType(\"isInversed\", isInversed, ValidationType.Bool);\r\n validateType(\"isUnfolded\", isUnfolded, ValidationType.Bool);\r\n validateType(\r\n \"annotationsAreVisible\",\r\n annotationsAreVisible,\r\n ValidationType.Bool\r\n );\r\n validateType(\"hasChildren\", hasChildren, ValidationType.Bool);\r\n validateType(\"nestingDepth\", nestingDepth, ValidationType.Int);\r\n if (nestingDepth < 0)\r\n throw RangeError(\r\n `nestingDepth must be of type integer >= 0, received ${typeof nestingDepth}: ${nestingDepth}`\r\n );\r\n\r\n validateType(\"totalObjectCount\", totalObjectCount, ValidationType.Int);\r\n if (totalObjectCount < 0)\r\n throw RangeError(\r\n `totalObjectCount must be of type integer >= 0, received ${typeof totalObjectCount}: ${totalObjectCount}`\r\n );\r\n if (canBeChosen !== null)\r\n validateType(\"canBeChosen\", canBeChosen, ValidationType.Bool);\r\n validateType(\"isChosen\", isChosen, ValidationType.Bool);\r\n\r\n validateType(\"toolSettings\", toolSettings, ValidationType.Array);\r\n toolSettings.forEach((iam) => {\r\n validateInstance(\"toolSettings\", iam, InstantAnalysisModule);\r\n });\r\n\r\n // Value assignments\r\n this.id = id;\r\n this.label = label;\r\n this.isStructure = isStructure;\r\n this.color = color;\r\n this.isDynamic = isDynamic;\r\n this.parentId = parentId;\r\n this.sameLevelRank = sameLevelRank;\r\n this.isInversed = isInversed;\r\n this.isUnfolded = isUnfolded;\r\n this.annotationsAreVisible = annotationsAreVisible;\r\n this.hasChildren = hasChildren;\r\n this.nestingDepth = nestingDepth;\r\n this.totalObjectCount = totalObjectCount;\r\n this.canBeChosen = canBeChosen;\r\n this.isChosen = isChosen;\r\n this.toolSettings = toolSettings;\r\n this.optionalParams = optionalParams;\r\n\r\n if (id > Structure.maxId) Structure.__setMaxId(id);\r\n }\r\n\r\n /**\r\n * Create a new structure from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per Structure constructor.\r\n * @param {object} obj An object containing all necessary properties of a structure.\r\n * @returns {Structure} A new structure\r\n */\r\n static fromObject = (obj) => {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n if (!obj.toolSettings) {\r\n obj.toolSettings = [];\r\n } else if (typeof obj.toolSettings === \"string\") {\r\n obj.toolSettings = JSON.parse(obj.toolSettings);\r\n }\r\n\r\n validateType(\"obj.toolSettings\", obj.toolSettings, ValidationType.Array);\r\n\r\n return new Structure(\r\n obj.id,\r\n obj.label,\r\n obj.isStructure,\r\n obj.color,\r\n obj.isDynamic,\r\n obj.parentId,\r\n obj.sameLevelRank,\r\n obj.isInversed,\r\n obj.isUnfolded,\r\n obj.annotationsAreVisible,\r\n obj.hasChildren,\r\n obj.nestingDepth,\r\n obj.totalObjectCount,\r\n obj.canBeChosen,\r\n obj.isChosen,\r\n obj.toolSettings.map((iam) => InstantAnalysisModule.fromObject(iam)),\r\n obj.optionalParams\r\n );\r\n };\r\n\r\n /**\r\n * Create an independent (deep) copy of a structure.\r\n * @param {Structure} structure Structure to copy.\r\n * @returns {Structure} Copy of structure.\r\n */\r\n static copy = (structure) => {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n\r\n return new Structure(\r\n structure.id,\r\n structure.label,\r\n structure.isStructure,\r\n structure.color,\r\n structure.isDynamic,\r\n structure.parentId,\r\n structure.sameLevelRank,\r\n structure.isInversed,\r\n structure.isUnfolded,\r\n structure.annotationsAreVisible,\r\n structure.hasChildren,\r\n structure.nestingDepth,\r\n structure.totalObjectCount,\r\n structure.canBeChosen,\r\n structure.isChosen,\r\n structure.toolSettings,\r\n structure.optionalParams\r\n );\r\n };\r\n}\r\n\r\n//#region Structure properties\r\n/**\r\n * Gets a new, free structureId that is one larger than the largest id already present.\r\n * @param {Array} structures All existing structures.\r\n * @returns {uint} New, free structure id.\r\n */\r\nexport function newStructureId(structures) {\r\n // Input validation\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n const highestIdInStructures = Math.floor(\r\n structures\r\n .map((s) => s.id)\r\n .reduce((a, b) => Math.max(Math.abs(a), Math.abs(b)), 0)\r\n );\r\n return Math.max(Structure.maxId, highestIdInStructures) + 1;\r\n}\r\n\r\n/**\r\n * Perform a check whether a structure can move in a certain direction.\r\n * @param {Structure} structure The structure to move.\r\n * @param {int} direction Number of steps to move, postive numbers lower the structure, negative numbers raise it.\r\n * @param {Array} structures The existing structures.\r\n * @returns {bool} Whether the intended move is allowed.\r\n */\r\nexport function structureCanMove(structure, direction, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"direction\", direction, ValidationType.Int);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n // No movement requested\r\n if (direction === 0) return true;\r\n\r\n // Sort siblings by rank\r\n let siblings = structures\r\n .filter((s) => s.parentId === structure.parentId)\r\n .sort((a, b) => a.sameLevelRank - b.sameLevelRank);\r\n\r\n // Structure not in structures\r\n if (\r\n siblings.length === 0 ||\r\n !siblings.some((s) => s.id === structure.id && s.label === structure.label)\r\n ) {\r\n throw Error(`Structure ${structure.label} not found in structures`);\r\n }\r\n\r\n let sameLevelIndex = siblings.findIndex((s) => s.id === structure.id);\r\n\r\n // Check if new position would be in bounds of array\r\n if (\r\n sameLevelIndex + direction < 0 ||\r\n sameLevelIndex + direction > siblings.length - 1\r\n ) {\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Finds all parents of a structure.\r\n * Returns them in the order beginning from top and ending at given structure.\r\n * @param {Structure} structure The structure to find all parents for.\r\n * @param {Array} structures Existing structures.\r\n * @returns {Array} All parent structures, including the structure itself.\r\n */\r\nexport function parentStructures(structure, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n const parentStructs = [];\r\n\r\n // Recursively traverse structure tree upwards\r\n if (structure.parentId !== null) {\r\n parentStructs.push(\r\n ...parentStructures(\r\n structures.find((s) => s.id === structure.parentId),\r\n structures\r\n ),\r\n structure\r\n );\r\n return parentStructs;\r\n } else {\r\n return [structure];\r\n }\r\n}\r\n\r\n/**\r\n * Finds all children of a structure, beginning at the given structure and\r\n * ending with child-free structures.\r\n * @param {Structure} structure The structure to find all children for.\r\n * @param {Array} structures Existing structures.\r\n * @returns {Array} All child structures, including the structure itself.\r\n */\r\nexport function childStructures(structure, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n // Bottom end of structure tree\r\n if (!structure.hasChildren) {\r\n return [structure];\r\n } else {\r\n let childStructs = [structure];\r\n\r\n structures\r\n .filter((s) => s.parentId === structure.id)\r\n .forEach((s) => childStructs.push(...childStructures(s, structures)));\r\n\r\n return childStructs;\r\n }\r\n}\r\n\r\n/**\r\n * Get the same level rank of a structure within a list of structures.\r\n * @param {Structure} structure The structure to find the same level rank for.\r\n * @param {Array[Structure]} structures All structures of the project.\r\n * @returns {int} The same level rank of the structure.\r\n */\r\nexport function getSameLevelRank(structure, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n return structures\r\n .filter((s) => s.parentId === structure.parentId)\r\n .findIndex((s) => s.id === structure.id);\r\n}\r\n\r\n//#endregion\r\n//#region Structure actions\r\n/**\r\n * Sorts structures by their hierarchy.\r\n * @param {array} structures All structures imported from a project as list.\r\n * @param {Structure} parentStructure The topmost parent structure under which all structures will be sorted.\r\n * Defaults to null to begin at the topmost level.\r\n * @returns {array} The structures sorted based on their hierarchy.\r\n */\r\nexport function sortStructures(structures, parentStructure = null) {\r\n // Input validation\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n if (parentStructure !== null)\r\n validateInstance(\"parentStructure\", parentStructure, Structure);\r\n\r\n // Find all children of parentstructure\r\n const children = structures.filter((s) =>\r\n parentStructure === null\r\n ? s.parentId === null\r\n : s.parentId === parentStructure.id\r\n );\r\n\r\n // Sort by sameLevelRank\r\n children.sort((a, b) => a.sameLevelRank - b.sameLevelRank);\r\n\r\n // Check if they have children of their own and sort recursively.\r\n let sorted = [];\r\n children.forEach((child) => {\r\n if (child.hasChildren) {\r\n sorted = [...sorted, ...sortStructures(structures, child)];\r\n } else {\r\n sorted = [...sorted, child];\r\n }\r\n });\r\n\r\n // Combine with parent and return as array\r\n if (parentStructure !== null) {\r\n return [parentStructure, ...sorted];\r\n } else {\r\n return sorted;\r\n }\r\n}\r\n\r\n/**\r\n * Move an existing structure in a defined direction.\r\n * Invalid moves return original array.\r\n * @param {Structure} structure The structure to move.\r\n * @param {int} direction Number of steps to move, postive numbers lower the structure, negative numbers raise it.\r\n * @param {Array} structures The existing structures.\r\n * @returns {Array} The modified structures.\r\n */\r\nexport function moveStructure(structure, direction, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"direction\", direction, ValidationType.Int);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n // No move requested, return original\r\n if (direction === 0) return structures;\r\n\r\n // Sort siblings by rank\r\n const siblings = structures\r\n .filter((s) => s.parentId === structure.parentId)\r\n .sort((a, b) => a.sameLevelRank - b.sameLevelRank);\r\n\r\n // Move not possible, return original structures\r\n if (!structureCanMove(structure, direction, siblings)) return structures;\r\n\r\n const sameLevelIndex = siblings.findIndex((s) => s.id === structure.id);\r\n const newSameLevelRank = siblings[sameLevelIndex + direction].sameLevelRank;\r\n\r\n // All items between old and new rank must be updated\r\n const sibsToModify = siblings.filter((s) => {\r\n if (direction > 0) {\r\n return (\r\n s.sameLevelRank >= structure.sameLevelRank &&\r\n s.sameLevelRank <= newSameLevelRank\r\n );\r\n } else {\r\n return (\r\n s.sameLevelRank <= structure.sameLevelRank &&\r\n s.sameLevelRank >= newSameLevelRank\r\n );\r\n }\r\n });\r\n // Rotate ranking values of all affected siblings\r\n const prevRanks = sibsToModify.map((s) => s.sameLevelRank);\r\n sibsToModify.forEach((s, idx) => {\r\n s.sameLevelRank =\r\n prevRanks[(idx + sibsToModify.length + direction) % sibsToModify.length];\r\n });\r\n\r\n // Structures are already edited by reference\r\n return sortStructures(structures);\r\n}\r\n\r\n/**\r\n * Insert a new structure into the list of existing structures, update structures as necessary.\r\n * @param {Structure} structure A structure to insert into existing structures.\r\n * @param {Array} structures List of all existing structures.\r\n * @returns {Array} Updated structure list.\r\n */\r\nexport function insertStructure(structure, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n // Do not allow duplicate ids.\r\n if (structures.map((s) => s.id).some((id) => id === structure.id)) {\r\n throw Error(\r\n `id \"${structure.id}\" already present in structures. \r\n Please use the newStructureId() method to generate a unique id.`\r\n );\r\n }\r\n\r\n // Find all same level-children and sort as lowest\r\n structure.sameLevelRank =\r\n structures\r\n .filter((s) => s.parentId === structure.parentId)\r\n .map((s) => s.id)\r\n .reduce((a, b) => Math.max(a, b), -1) + 1;\r\n\r\n // Update parent\r\n if (structure.parentId !== null) {\r\n const parent = structures.find((s) => s.id === structure.parentId);\r\n parent.hasChildren = true;\r\n parent.isUnfolded = true;\r\n }\r\n\r\n // Add adapted structure to all structures\r\n structures.push(structure);\r\n\r\n return sortStructures(structures);\r\n}\r\n\r\n/**\r\n * Delete a structure from the list of existing structures, update structures as necessary.\r\n * @param {Structure} structure The structure to delete from existing structures.\r\n * @param {Array} structures List of all existing structures.\r\n * @param {function} deleteAnnotations Optional. Delete rois of structure given to function. Receives (Structure: structureToDelete).\r\n * @returns {Array} Updated structure list.\r\n */\r\nexport function deleteStructure(\r\n structure,\r\n structures,\r\n deleteAnnotations = () => {}\r\n) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n // Delete all rois of structure and its children\r\n // Find all children and delete them\r\n childStructures(structure, structures).forEach((s) => {\r\n deleteAnnotations(s);\r\n structures.splice(\r\n structures.findIndex((struct) => struct.id === s.id),\r\n 1\r\n );\r\n });\r\n\r\n // Find all siblings\r\n const siblings = structures\r\n .filter((s) => s.parentId === structure.parentId)\r\n .sort((a, b) => a.sameLevelRank - b.sameLevelRank);\r\n\r\n // Should parent no longer have children\r\n if (siblings.length === 0 && structure.parentId !== null) {\r\n structures.find((s) => s.id === structure.parentId).hasChildren = false;\r\n return sortStructures(structures);\r\n }\r\n\r\n // Update sameLevelRank of all siblings\r\n siblings.forEach((s, idx) => (s.sameLevelRank = idx));\r\n\r\n return sortStructures(structures);\r\n}\r\n\r\n/**\r\n * Duplicates a structure including all its decendents and\r\n * Inserts the duplicate as lowest sibling in same hierarchical rank.\r\n * @param {Structure} structure The structure to duplicate.\r\n * @param {Array} structures Existing structures.\r\n * @returns {Array} The updated structures.\r\n */\r\nexport function duplicateStructure(structure, structures) {\r\n // Input validation\r\n validateInstance(\"structure\", structure, Structure);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n\r\n // Find all children of structure to duplicate, including the structure\r\n const childStructs = childStructures(structure, structures);\r\n\r\n // Reserve new Ids\r\n const firstNewId = newStructureId(structures);\r\n const newIds = Array(childStructs.length);\r\n for (let i = 0; i < childStructs.length; i++) {\r\n newIds[i] = firstNewId + i;\r\n }\r\n\r\n // Create new structures based on children\r\n const newStructs = childStructs.map((s) => Structure.copy(s));\r\n\r\n // Adapt parent-Ids\r\n newStructs.forEach((s, idx) => {\r\n s.id = newIds[idx];\r\n s.label = `Copy: ${s.label}`;\r\n const parentIdx = childStructs.findIndex((cs) => cs.id === s.parentId);\r\n\r\n // If parent is one of the newly added structures, adapt to the new id.\r\n if (parentIdx >= 0) s.parentId = newIds[parentIdx];\r\n });\r\n\r\n structures = insertStructure(newStructs.shift(), structures);\r\n structures.push(...newStructs);\r\n const tmp = sortStructures(structures);\r\n return tmp;\r\n}\r\n\r\n/**\r\n * Export structuretree in frontend to .strhsa file.\r\n * @param {array} structures Structuretree to export.\r\n * @param {string} username Optional. Full username of exporting user. Defaults to \"\".\r\n * @param {object} project Optional. Project the structures referr to. Defaults to null.\r\n * @returns {object} Success status of export.\r\n */\r\nexport function exportStructures(structures, username = \"\", project = null) {\r\n // Input validation\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((s) => {\r\n validateInstance(\"structures\", s, Structure);\r\n });\r\n validateType(\"username\", username, ValidationType.String);\r\n if (project != null) validateType(\"project\", project, ValidationType.Object);\r\n\r\n try {\r\n // Export rois with meta info\r\n const timestamp = convertDateToShortIsoString(Date.now());\r\n downloadJsonObjectAsFile(\r\n {\r\n version: 1.0,\r\n timestamp: timestamp,\r\n user: username === \"\" ? \"Unknown\" : username,\r\n project: project ?? { name: \"Unknown\" },\r\n structures,\r\n },\r\n `${timestamp}_${project?.name ?? \"Unkown-Project\"}_StructureTree_(${\r\n structures.length\r\n }_Structures).strhsa`\r\n );\r\n\r\n return {\r\n success: true,\r\n msg: `Successfully exported ${structures.length} structures.`,\r\n };\r\n } catch (err) {\r\n return {\r\n success: false,\r\n msg: `Failed to export ${structures.length} structures.`,\r\n error: err,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Import structures from .strhsa file. Replaces all current structures and deletes all current frontend annotations.\r\n * @param {uint} firstNewId First new id for new structures.\r\n * @param {function} callback Function to execute with the new structures. Receives (array: newStructures).\r\n * @param {function} error Optional. Function to execute on error. Receives (string: errorMessage).\r\n * @returns\r\n */\r\nexport async function importStructures(firstNewId, callback, error = () => {}) {\r\n // Input validation\r\n validateType(\"firstNewId\", firstNewId, ValidationType.Int);\r\n if (firstNewId < 0)\r\n throw RangeError(\r\n `firstNewId must be an integer >= 0, received ${typeof firstNewId}: ${firstNewId}`\r\n );\r\n validateType(\"callback\", callback, ValidationType.Function);\r\n validateType(\"error\", error, ValidationType.Function);\r\n\r\n // Structure replacement warning\r\n const continueImport = await window.openConfirmationDialog(\r\n \"Import Structures\",\r\n `All structures and annotations will be deleted and replaced with the imported structures.\r\n Import anyway?`\r\n );\r\n if (!continueImport) return;\r\n\r\n const files = await requestFileInput([\".strhsa\"]);\r\n if (files.length === 0) return;\r\n const file = files[0];\r\n\r\n const fr = new FileReader();\r\n fr.onload = async (e) => {\r\n try {\r\n const data = JSON.parse(e.target.result);\r\n if (!Array.isArray(data.structures)) {\r\n window.showErrorSnackbar(`No valid structures found in ${file.name}.`);\r\n return;\r\n }\r\n\r\n // Empty structure import warning\r\n if (data.structures.length == 0) {\r\n const continueImport = await window.openConfirmationDialog(\r\n \"No structures to import\",\r\n `There are no structures included in uploaded file. \r\n An import will remove all existing structures, including their annotations. \r\n Import anyway?`\r\n );\r\n if (!continueImport) return;\r\n }\r\n\r\n let newStructures = [];\r\n\r\n // Replace full structure tree\r\n data.structures.forEach((s) => {\r\n const newStruct = Structure.fromObject(s);\r\n newStructures = insertStructure(newStruct, newStructures);\r\n });\r\n\r\n // Reserve new Ids\r\n const newIds = Array(data.structures.length);\r\n for (let i = 0; i < data.structures.length; i++) {\r\n newIds[i] = firstNewId + i;\r\n }\r\n\r\n // Update parent-child relationships\r\n newStructures.forEach((s) => {\r\n if (!s.parentId) return;\r\n const parentIndex = newStructures.findIndex(\r\n (struct) => struct.id === s.parentId\r\n );\r\n s.parentId = newIds[parentIndex];\r\n });\r\n\r\n // Update ids\r\n newStructures.forEach((s, i) => (s.id = newIds[i]));\r\n\r\n // Set new structures\r\n callback(sortStructures(newStructures));\r\n } catch (err) {\r\n const errmsg = `Failed to import the structures from file ${file.name}:\\n${err}`;\r\n console.debug(errmsg);\r\n error(errmsg);\r\n }\r\n };\r\n // Only accept the first element\r\n fr.readAsText(file);\r\n}\r\n//#endregion\r\n","// Copyright HS Analysis GmbH, 2023\r\n// Author: Valentin Haas\r\n\r\n// HSA imports\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n isUuid,\r\n validateInEnum,\r\n validateInstance,\r\n validateType,\r\n ValidationType,\r\n} from \"../utils/Utils\";\r\nimport Structure from \"./Structure\";\r\n\r\n// #region Option sets for the AI training\r\n\r\n// Shared data structures for the AI training\r\n// Keep in sync with:\r\n// Source\\HSA-KIT\\Models\\AITrainingSettings.cs\r\n// Source\\HSA-KIT\\modules\\hsa\\core\\ai\\models.py\r\n// Source\\HSA-KIT\\ClientApp\\src\\common\\components\\AITrainingSettings.jsx\r\n\r\n/**\r\n * All principle dataset creation approaches.\r\n */\r\nexport const DatasetApproach = Object.freeze({\r\n ImageFileBased: 0,\r\n ImageObjectBased: 1,\r\n ImageSlidingWindow: 2,\r\n AudioFileBased: 10,\r\n AudioSlidingWindow: 11,\r\n});\r\n\r\n/**\r\n * Readable names for the principle dataset creation approaches.\r\n */\r\nexport const DatasetApproachNames = Object.freeze({\r\n [DatasetApproach.ImageFileBased]: \"File Based\",\r\n [DatasetApproach.ImageObjectBased]: \"Object Based\",\r\n [DatasetApproach.ImageSlidingWindow]: \"Sliding Window\",\r\n [DatasetApproach.AudioFileBased]: \"File Based\",\r\n [DatasetApproach.AudioSlidingWindow]: \"Sliding Window\",\r\n});\r\n\r\n/**\r\n * Abbreviations for the principle dataset creation approaches.\r\n */\r\nexport const DatasetApproachShort = Object.freeze({\r\n [DatasetApproach.ImageFileBased]: \"i-fb\",\r\n [DatasetApproach.ImageObjectBased]: \"i-ob\",\r\n [DatasetApproach.ImageSlidingWindow]: \"i-sw\",\r\n [DatasetApproach.AudioFileBased]: \"a-fb\",\r\n [DatasetApproach.AudioSlidingWindow]: \"a-sw\",\r\n});\r\n\r\n/**\r\n * All training model types.\r\n */\r\nexport const DatasetType = Object.freeze({\r\n ImageClassification: 0,\r\n ImageObjectDetection: 1,\r\n ImageSegmentation: 2,\r\n ImageInstanceSegmentation: 3,\r\n AudioClassification: 10,\r\n AudioSequenceDetection: 11,\r\n AudioSequenceSegmentation: 12,\r\n AudioSequenceInstanceSegmentation: 13,\r\n});\r\n\r\n/**\r\n * Readable names for the training model types.\r\n */\r\nexport const DatasetTypeNames = Object.freeze({\r\n [DatasetType.ImageClassification]: \"Image Classification\",\r\n [DatasetType.ImageObjectDetection]: \"Image Object Detection\",\r\n [DatasetType.ImageSegmentation]: \"Image Segmentation\",\r\n [DatasetType.ImageInstanceSegmentation]: \"Image Instance Segmentation\",\r\n [DatasetType.AudioClassification]: \"Audio Classification\",\r\n [DatasetType.AudioSequenceDetection]: \"Audio Sequence Detection\",\r\n [DatasetType.AudioSequenceSegmentation]: \"Audio Sequence Segmentation\",\r\n [DatasetType.AudioSequenceInstanceSegmentation]:\r\n \"Audio Sequence Instance Segmentation\",\r\n});\r\n\r\n/**\r\n * Abbreviations for the training model types.\r\n */\r\nexport const DatasetTypeShort = Object.freeze({\r\n [DatasetType.ImageClassification]: \"i-cl\",\r\n [DatasetType.ImageObjectDetection]: \"i-od\",\r\n [DatasetType.ImageSegmentation]: \"i-seg\",\r\n [DatasetType.ImageInstanceSegmentation]: \"i-iseg\",\r\n [DatasetType.AudioClassification]: \"a-cl\",\r\n [DatasetType.AudioSequenceDetection]: \"a-sd\",\r\n [DatasetType.AudioSequenceSegmentation]: \"a-seg\",\r\n [DatasetType.AudioSequenceInstanceSegmentation]: \"a-iseg\",\r\n});\r\n\r\n/**\r\n * A collection of all image dataset types.\r\n */\r\nexport const ImageDatasetTypes = [\r\n DatasetType.ImageClassification,\r\n DatasetType.ImageObjectDetection,\r\n DatasetType.ImageSegmentation,\r\n DatasetType.ImageInstanceSegmentation,\r\n];\r\n\r\n/**\r\n * A collection of all audio dataset types.\r\n */\r\nexport const AudioDatasetTypes = [\r\n DatasetType.AudioClassification,\r\n DatasetType.AudioSequenceDetection,\r\n DatasetType.AudioSequenceSegmentation,\r\n DatasetType.AudioSequenceInstanceSegmentation,\r\n];\r\n\r\n/**\r\n * A collection of all image dataset approaches.\r\n */\r\nexport const ImageDatasetApproaches = [\r\n DatasetApproach.ImageFileBased,\r\n DatasetApproach.ImageObjectBased,\r\n DatasetApproach.ImageSlidingWindow,\r\n];\r\n\r\n/**\r\n * A collection of all audio dataset approaches.\r\n */\r\nexport const AudioDatasetApproaches = [\r\n DatasetApproach.AudioFileBased,\r\n DatasetApproach.AudioSlidingWindow,\r\n];\r\n\r\n/**\r\n * All available target data formats for AI models.\r\n */\r\nexport const TargetDataFormat = Object.freeze({\r\n Image: 0,\r\n Audio: 1,\r\n});\r\n\r\n/**\r\n * Mapping of training data types to project types.\r\n */\r\nconst _targetDataFormatbyModuleName = Object.freeze({\r\n AudioAnnotator: TargetDataFormat.Audio,\r\n});\r\n\r\n/**\r\n * Returns the training data type for a given module.\r\n * @param {string} projectType The name of the module currently loaded to get the training data type for.\r\n * @returns {TargetDataFormat} The training data type for the given module. Defaults to TargetDataFormats.Image.\r\n */\r\nexport const targetDataFormatbyModuleName = (projectType = \"\") => {\r\n return _targetDataFormatbyModuleName[projectType] ?? TargetDataFormat.Image;\r\n};\r\n\r\n/**\r\n * All available metrics for training.\r\n */\r\nexport const Metrics = Object.freeze({\r\n Accuracy: 0,\r\n});\r\nexport const MetricsNames = Object.freeze({\r\n [Metrics.Accuracy]: \"Accuracy\",\r\n});\r\n\r\n/**\r\n * All available loss functions for training.\r\n */\r\nexport const LossFunction = Object.freeze({\r\n CrossEntropy: 0,\r\n Dice: 1,\r\n CrossEntropyDice: 2,\r\n});\r\nexport const LossFunctionNames = Object.freeze({\r\n [LossFunction.CrossEntropy]: \"Cross Entropy\",\r\n [LossFunction.Dice]: \"Dice\",\r\n [LossFunction.CrossEntropyDice]: \"Cross Entropy + Dice\",\r\n});\r\n\r\n/**\r\n * All available optimizers for training.\r\n */\r\nexport const Optimizer = Object.freeze({\r\n Adam: 0,\r\n AdamW: 1,\r\n SGD: 2,\r\n});\r\nexport const OptimizerNames = Object.freeze({\r\n [Optimizer.Adam]: \"Adam\",\r\n [Optimizer.AdamW]: \"AdamW\",\r\n [Optimizer.SGD]: \"SGD\",\r\n});\r\n\r\n// #endregion\r\n\r\n// region Default values\r\nconst _DefaultDatasetTypeMappings = Object.freeze({\r\n AudioAnnotator: DatasetType.AudioSequenceDetection,\r\n});\r\n\r\n/**\r\n * Get a default model type for a given project type.\r\n * @param {string} projectType The type of the project to get the default model type for.\r\n * @returns {DatasetType} The default model type for the given project type.\r\n */\r\nexport const DefaultDatasetType = (projectType = \"\") => {\r\n return (\r\n _DefaultDatasetTypeMappings[projectType] ??\r\n DatasetType.ImageInstanceSegmentation\r\n );\r\n};\r\n\r\nconst _DefaultDatasetApproachMappings = Object.freeze({\r\n AudioAnnotator: DatasetApproach.AudioFileBased,\r\n});\r\n\r\n/**\r\n * Get a default dataset approach for a given project type.\r\n * @param {string} projectType The type of the project to get the default dataset approach for.\r\n * @returns {DatasetApproach} The default dataset approach for the given project type.\r\n */\r\nexport const DefaultDatasetApproach = (projectType = \"\") => {\r\n return (\r\n _DefaultDatasetApproachMappings[projectType] ??\r\n DatasetApproach.ImageSlidingWindow\r\n );\r\n};\r\n\r\n// #endregion\r\n\r\n// #region Data structures for each individual settings page\r\n/**\r\n * All parameters of AI Training that are not model specific.\r\n * @param {number} epochs Number of epochs to train.\r\n * @param {number} earlyStopping Number of epochs to wait for early stopping.\r\n * @param {number} batchSize Batch size for training.\r\n * @param {number[]} metrics Metrics to use for training.\r\n * @param {string[]} lossFunctions Loss functions to use for training.\r\n * @param {string} optimizer Optimizer to use for training.\r\n * @param {number} learningRate Learning rate to use for training.\r\n */\r\nexport class TrainingParameters {\r\n constructor(\r\n epochs = 1,\r\n earlyStopping = 500,\r\n batchSize = 2,\r\n metrics = [Metrics.Accuracy],\r\n lossFunctions = [LossFunction.CrossEntropy, LossFunction.Dice],\r\n optimizer = Optimizer.AdamW,\r\n learningRate = 1e-4\r\n ) {\r\n // Input validation\r\n validateType(\"epochs\", epochs, ValidationType.Int);\r\n if (epochs <= 0)\r\n throw RangeError(\r\n `epochs must be of type integer > 0, received ${typeof epochs}: ${epochs}`\r\n );\r\n\r\n validateType(\"earlyStopping\", earlyStopping, ValidationType.Int);\r\n if (earlyStopping < 0)\r\n throw RangeError(\r\n `earlyStopping must be of type integer >= 0, received ${typeof earlyStopping}: ${earlyStopping}`\r\n );\r\n\r\n validateType(\"batchSize\", batchSize, ValidationType.Int);\r\n if (batchSize < 1)\r\n throw RangeError(\r\n `batchSize must be of type integer >= 1, received ${typeof batchSize}: ${batchSize}`\r\n );\r\n validateType(\"metrics\", metrics, ValidationType.Array);\r\n if (metrics.length === 0)\r\n throw RangeError(\r\n `metrics must be of type array with at least one element, received ${typeof metrics}: ${metrics}`\r\n );\r\n metrics.forEach((metric) => {\r\n validateInEnum(\"metric\", metric, Metrics);\r\n });\r\n\r\n validateType(\"lossFunctions\", lossFunctions, ValidationType.Array);\r\n if (lossFunctions.length === 0)\r\n throw RangeError(\r\n `lossFunctions must be of type array with at least one element, received ${typeof lossFunctions}: ${lossFunctions}`\r\n );\r\n lossFunctions.forEach((lossFunction) => {\r\n validateInEnum(\"lossFunction\", lossFunction, LossFunction);\r\n });\r\n\r\n validateInEnum(\"optimizer\", optimizer, Optimizer);\r\n\r\n validateType(\"learningRate\", learningRate, ValidationType.Number);\r\n if (learningRate <= 0)\r\n throw RangeError(\r\n `learningRate must be of type number > 0, received ${typeof learningRate}: ${learningRate}`\r\n );\r\n\r\n this.epochs = epochs;\r\n this.earlyStopping = earlyStopping;\r\n this.batchSize = batchSize;\r\n this.metrics = metrics;\r\n this.lossFunctions = lossFunctions;\r\n this.optimizer = optimizer;\r\n this.learningRate = learningRate;\r\n }\r\n\r\n /**\r\n * Create new TrainingParameters from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per TrainingParameters constructor.\r\n * @param {object} obj An object containing all necessary properties of TrainingParameters.\r\n * @returns {TrainingParameters} New TrainingParameters.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n return new TrainingParameters(\r\n obj.epochs,\r\n obj.earlyStopping,\r\n obj.batchSize,\r\n obj.metrics,\r\n obj.lossFunctions,\r\n obj.optimizer,\r\n obj.learningRate\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * All meta data of an AI Training.\r\n * @param {string} name Name of the AI Model.\r\n * @param {string} version Version of the AI Model.\r\n * @param {string} description Description of the AI Model.\r\n * @param {boolean} isNewModel Whether the model is new or not.\r\n */\r\nexport class ModelMetaData {\r\n constructor(name = \"\", version = \"\", description = \"\", isNewModel = true) {\r\n // Input validation\r\n validateType(\"name\", name, ValidationType.String);\r\n validateType(\"version\", version, ValidationType.String);\r\n validateType(\"description\", description, ValidationType.String);\r\n validateType(\"isNewModel\", isNewModel, ValidationType.Bool);\r\n\r\n this.name = name;\r\n this.version = version;\r\n this.description = description;\r\n this.isNewModel = isNewModel;\r\n }\r\n\r\n /**\r\n * Create new ModelMetaData from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per ModelMetaData contructor.\r\n * @param {object} obj An object containing all necessary properties of ModelMetaData.\r\n * @returns {ModelMetaData} New ModelMetaData.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new ModelMetaData(\r\n obj.name,\r\n obj.version,\r\n obj.description,\r\n obj.isNewModel\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * All dataset specific parameters of an AI Training.\r\n * @param {DatasetApproach} datasetApproach Approach to create the dataset. Must be one of the values of DatasetApproach. Default: ImageFileBased.\r\n * @param {DatasetType} datasetType Type of the dataset used. Must be one of the values of DatasetType. Default: ImageClassification.\r\n * @param {boolean} datasetOnly Whether only the dataset should be created or not, without training. Default: false.\r\n * @param {boolean} useExistingDataset Whether an existing dataset should be used or not for training. Default: false.\r\n * @param {boolean} removeBackground Whether the background should be removed from the dataset images or not. Default: true.\r\n * @param {number} removeBorderThreshold Threshold for the border removal. Default: 75.\r\n */\r\nexport class DatasetParameters {\r\n constructor(\r\n datasetApproach = DatasetApproach.ImageSlidingWindow,\r\n datasetType = DatasetType.ImageClassification,\r\n datasetOnly = false,\r\n useExistingDataset = false,\r\n removeBackground = true,\r\n removeBorderThreshold = 75\r\n ) {\r\n // Input validation\r\n validateInEnum(\"datasetApproach\", datasetApproach, DatasetApproach);\r\n validateInEnum(\"datasetType\", datasetType, DatasetType);\r\n validateType(\"datasetOnly\", datasetOnly, ValidationType.Bool);\r\n validateType(\"useExistingDataset\", useExistingDataset, ValidationType.Bool);\r\n validateType(\"removeBackground\", removeBackground, ValidationType.Bool);\r\n validateType(\r\n \"removeBorderThreshold\",\r\n removeBorderThreshold,\r\n ValidationType.Number\r\n );\r\n\r\n this.datasetApproach = datasetApproach;\r\n this.datasetType = datasetType;\r\n this.datasetOnly = datasetOnly;\r\n this.useExistingDataset = useExistingDataset;\r\n this.removeBackground = removeBackground;\r\n this.removeBorderThreshold = removeBorderThreshold;\r\n }\r\n\r\n /**\r\n * Create new DatasetParameters from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per DatasetParameters constructor.\r\n * @param {object} obj An object containing all necessary properties of DatasetParameters.\r\n * @returns {DatasetParameters} New DatasetParameters.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new DatasetParameters(\r\n obj.datasetApproach,\r\n obj.datasetType,\r\n obj.datasetOnly,\r\n obj.useExistingDataset,\r\n obj.removeBackground,\r\n obj.removeBorderThreshold\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * General class for all dataset specific parameters of an AI Training.\r\n */\r\nexport class DatasetMeta {\r\n constructor() {}\r\n}\r\n\r\n/**\r\n * All model specific parameters of an image model AI Training.\r\n * @param {DatasetType} datasetType Type of the dataset used. Must be one of the values of DatasetType. Default: ImageClassification.\r\n * @param {number} inputChannels Number of input channels. Can be 1 for grayscale images, 3 for RGB images, or more for multispectral images.\r\n * @param {Array[string]} fluorescenceChannels List of fluorescence channel names. Default: [].\r\n * @param {number} spatialDims Number of spatial dimensions. Can be 2 for 2D images or 3 for 3D images.\r\n * @param {number} imageWidth Width of an dataset image.\r\n * @param {number} imageHeight Height of an dataset image.\r\n * @param {number} numberOfClasses Number of classes to predict.\r\n * @param {number} pyramidLevel Pyramid level of the dataset images. Default: -1.\r\n * @param {number} pixelSize Pixel size of the dataset images. Default: -1.\r\n */\r\nexport class ImageDatasetMeta extends DatasetMeta {\r\n constructor(\r\n datasetType = DatasetType.ImageClassification,\r\n inputChannels = 3,\r\n fluorescenceChannels = [],\r\n spatialDims = 2,\r\n imageWidth = 512,\r\n imageHeight = 512,\r\n numberOfClasses = 1,\r\n pyramidLevel = -1,\r\n pixelSize = -1\r\n ) {\r\n super();\r\n\r\n // Input validation\r\n validateInEnum(\"datasetType\", datasetType, DatasetType);\r\n validateType(\"inputChannels\", inputChannels, ValidationType.Int);\r\n if (inputChannels < 1)\r\n throw TypeError(\r\n `inputChannels must be of type integer >= 1, received ${typeof inputChannels}: ${inputChannels}`\r\n );\r\n\r\n validateType(\r\n \"fluorescenceChannels\",\r\n fluorescenceChannels,\r\n ValidationType.Array\r\n );\r\n fluorescenceChannels.forEach((fluorescenceChannel) => {\r\n validateType(\r\n \"fluorescenceChannel\",\r\n fluorescenceChannel,\r\n ValidationType.String\r\n );\r\n });\r\n\r\n validateType(\"spatialDims\", spatialDims, ValidationType.Int);\r\n if (spatialDims < 2 || spatialDims > 3)\r\n throw RangeError(\r\n `spatialDims must be of type integer >= 2 and <= 3, received ${typeof spatialDims}: ${spatialDims}`\r\n );\r\n\r\n validateType(\"imageWidth\", imageWidth, ValidationType.Int);\r\n if (imageWidth < 1)\r\n throw RangeError(\r\n `imageWidth must be of type integer >= 1, received ${typeof imageWidth}: ${imageWidth}`\r\n );\r\n\r\n validateType(\"imageHeight\", imageHeight, ValidationType.Int);\r\n if (imageHeight < 1)\r\n throw RangeError(\r\n `imageHeight must be of type integer >= 1, received ${typeof imageHeight}: ${imageHeight}`\r\n );\r\n\r\n validateType(\"numberOfClasses\", numberOfClasses, ValidationType.Int);\r\n if (numberOfClasses < 1)\r\n throw RangeError(\r\n `numberOfClasses must be of type integer >= 1, received ${typeof numberOfClasses}: ${numberOfClasses}`\r\n );\r\n\r\n validateType(\"pyramidLevel\", pyramidLevel, ValidationType.Int);\r\n if (pyramidLevel < -1)\r\n throw RangeError(\r\n `pyramidLevel must be of type integer >= -1, received ${typeof pyramidLevel}: ${pyramidLevel}`\r\n );\r\n\r\n validateType(\"pixelSize\", pixelSize, ValidationType.Number);\r\n\r\n // Set parameters\r\n this.datasetType = datasetType;\r\n this.inputChannels = inputChannels;\r\n this.fluorescenceChannels = fluorescenceChannels;\r\n this.spatialDims = spatialDims;\r\n this.imageWidth = imageWidth;\r\n this.imageHeight = imageHeight;\r\n this.numberOfClasses = numberOfClasses;\r\n this.pyramidLevel = pyramidLevel;\r\n this.pixelSize = pixelSize;\r\n }\r\n\r\n /**\r\n * Create new ImageDatasetMeta from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per ImageDatasetMeta constructor.\r\n * @param {object} obj An object containing all necessary properties of ImageDatasetMeta.\r\n * @returns {ImageDatasetMeta} New ImageDatasetMeta.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new ImageDatasetMeta(\r\n obj.datasetType,\r\n obj.inputChannels,\r\n obj.fluorescenceChannels,\r\n obj.spatialDims,\r\n obj.imageWidth,\r\n obj.imageHeight,\r\n obj.numberOfClasses,\r\n obj.pyramidLevel,\r\n obj.pixelSize\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * All model specific parameters of an audio model AI Training.\r\n * @param {DatasetType} datasetType Type of the dataset used. Must be one of the values of DatasetType. Default: AudioClassification.\r\n * @param {number} sequenceLengthSeconds Length of an audio sequence in seconds. 0 for full length. Default: 0.\r\n * @param {number} sequenceOverlapSeconds Overlap of audio sequences in seconds. Negative values for gaps between sequences. Default: 0.\r\n * @param {number} numberOfClasses Number of classes to predict. Default: 1.\r\n */\r\nexport class AudioDatasetMeta extends DatasetMeta {\r\n constructor(\r\n datasetType = DatasetType.AudioClassification,\r\n sequenceLengthSeconds = 0,\r\n sequenceOverlapSeconds = 0,\r\n numberOfClasses = 1\r\n ) {\r\n super();\r\n\r\n // Input validation\r\n validateInEnum(\"datasetType\", datasetType, DatasetType);\r\n\r\n validateType(\r\n \"sequenceLengthSeconds\",\r\n sequenceLengthSeconds,\r\n ValidationType.Number\r\n );\r\n if (sequenceLengthSeconds < 0)\r\n throw RangeError(\r\n `sequenceLengthSeconds must be of type number >= 0, received ${typeof sequenceLengthSeconds}: ${sequenceLengthSeconds}`\r\n );\r\n\r\n validateType(\r\n \"sequenceOverlapSeconds\",\r\n sequenceOverlapSeconds,\r\n ValidationType.Number\r\n );\r\n\r\n validateType(\"numberOfClasses\", numberOfClasses, ValidationType.Int);\r\n if (numberOfClasses < 1)\r\n throw RangeError(\r\n `numberOfClasses must be of type integer >= 1, received ${typeof numberOfClasses}: ${numberOfClasses}`\r\n );\r\n\r\n // Set parameters\r\n this.datasetType = datasetType;\r\n this.sequenceLengthSeconds = sequenceLengthSeconds;\r\n this.sequenceOverlapSeconds = sequenceOverlapSeconds;\r\n this.numberOfClasses = numberOfClasses;\r\n }\r\n\r\n /**\r\n * Create new AudioDatasetMeta from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per AudioDatasetMeta contructor.\r\n * @param {object} obj An object containing all necessary properties of AudioDatasetMeta.\r\n * @returns {AudioDatasetMeta} New AudioDatasetMeta.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new AudioDatasetMeta(\r\n obj.datasetType,\r\n obj.sequenceLengthSeconds,\r\n obj.sequenceOverlapSeconds,\r\n obj.numberOfClasses\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Mapping of model parameters to dataset types.\r\n */\r\nconst _ModelParameterMappping = Object.freeze({\r\n [DatasetType.ImageClassification]: new ImageDatasetMeta(\r\n DatasetType.ImageClassification\r\n ),\r\n [DatasetType.ImageObjectDetection]: new ImageDatasetMeta(\r\n DatasetType.ImageObjectDetection\r\n ),\r\n [DatasetType.ImageSegmentation]: new ImageDatasetMeta(\r\n DatasetType.ImageSegmentation\r\n ),\r\n [DatasetType.ImageInstanceSegmentation]: new ImageDatasetMeta(\r\n DatasetType.ImageInstanceSegmentation\r\n ),\r\n [DatasetType.AudioClassification]: new AudioDatasetMeta(\r\n DatasetType.AudioClassification\r\n ),\r\n [DatasetType.AudioSequenceDetection]: new AudioDatasetMeta(\r\n DatasetType.AudioSequenceDetection\r\n ),\r\n [DatasetType.AudioSequenceSegmentation]: new AudioDatasetMeta(\r\n DatasetType.AudioSequenceSegmentation\r\n ),\r\n [DatasetType.AudioSequenceInstanceSegmentation]: new AudioDatasetMeta(\r\n DatasetType.AudioSequenceInstanceSegmentation\r\n ),\r\n});\r\n\r\n/**\r\n * Returns the model parameters for a given dataset type.\r\n * @param {DatasetType} datasetType The type of the dataset to get the model parameters for.\r\n * @returns {DatasetMeta}\r\n */\r\nexport const getModelParameters = (datasetType) => {\r\n return _ModelParameterMappping[datasetType] ?? new DatasetMeta();\r\n};\r\n\r\n// #endregion\r\n\r\n/**\r\n * All settings of an AI Training.\r\n * @param {Uuid} projectId ID of the project to train on.\r\n * @param {string} projectType Type of the project to train on.\r\n * @param {ModelMetaData} metaData Meta data of the AI Model.\r\n * @param {DatasetParameters} datasetParameters Dataset specific parameters of the AI Training.\r\n * @param {TrainingParameters} trainingParameters Training specific parameters of the AI Training.\r\n * @param {DatasetMeta} modelParameters Model specific parameters of the AI Training.\r\n * @param {Structure[]} structures Structures to train on.\r\n */\r\nexport default class AITrainingSettings {\r\n constructor(\r\n projectId,\r\n projectType,\r\n metaData = new ModelMetaData(),\r\n datasetParameters = new DatasetParameters(),\r\n trainingParameters = new TrainingParameters(),\r\n modelParameters = new DatasetMeta(),\r\n structures = []\r\n ) {\r\n // Input validation\r\n if (!isUuid(projectId, true))\r\n throw TypeError(\r\n `projectId must be of type uuid, received ${typeof projectId}: ${projectId}`\r\n );\r\n\r\n validateType(\"projectType\", projectType, ValidationType.String);\r\n validateInstance(\"metaData\", metaData, ModelMetaData);\r\n validateInstance(\"datasetParameters\", datasetParameters, DatasetParameters);\r\n validateInstance(\r\n \"trainingParameters\",\r\n trainingParameters,\r\n TrainingParameters\r\n );\r\n validateInstance(\"modelParameters\", modelParameters, DatasetMeta);\r\n validateType(\"structures\", structures, ValidationType.Array);\r\n structures.forEach((structure) => {\r\n validateInstance(\"structure\", structure, Structure);\r\n });\r\n\r\n // Set parameters\r\n this.projectId = projectId;\r\n this.projectType = projectType;\r\n this.metaData = metaData;\r\n this.datasetParameters = datasetParameters;\r\n this.trainingParameters = trainingParameters;\r\n this.modelParameters = modelParameters;\r\n this.structures = structures;\r\n }\r\n\r\n /**\r\n * Create new AITrainingSettings from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per AITrainingSettings constructor.\r\n * @param {object} obj An object containing all necessary properties of AITrainingSettings.\r\n * @returns {AITrainingSettings} New AITrainingSettings.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n validateType(\"obj.structures\", obj.structures, ValidationType.Array);\r\n\r\n obj.structures = obj.structures.map((structure) =>\r\n Structure.fromObject(structure)\r\n );\r\n\r\n obj.datasetParameters = DatasetParameters.fromObject(obj.datasetParameters);\r\n\r\n if (ImageDatasetTypes.includes(obj.datasetParameters.datasetType)) {\r\n obj.modelParameters = ImageDatasetMeta.fromObject(obj.modelParameters);\r\n } else if (AudioDatasetTypes.includes(obj.datasetParameters.datasetType)) {\r\n obj.modelParameters = AudioDatasetMeta.fromObject(obj.modelParameters);\r\n }\r\n\r\n return new AITrainingSettings(\r\n obj.projectId,\r\n obj.projectType,\r\n ModelMetaData.fromObject(obj.metaData),\r\n obj.datasetParameters,\r\n TrainingParameters.fromObject(obj.trainingParameters),\r\n obj.modelParameters,\r\n obj.structures\r\n );\r\n }\r\n}\r\n","function padTo2Digits(num) {\r\n return num.toString().padStart(2, \"0\");\r\n}\r\n\r\n/**\r\n * Adjusts a UTC date to local timezone.\r\n * @param {Date} date A date object to convert.\r\n * @returns {Date} A date adjusted to the local timezone.\r\n */\r\nexport function convertUTCDateToLocalDate(date) {\r\n var newDate = new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000);\r\n\r\n var offset = date.getTimezoneOffset() / 60;\r\n var hours = date.getHours();\r\n\r\n newDate.setHours(hours - offset);\r\n\r\n return newDate;\r\n}\r\n\r\n/**\r\n * Turn a json date into a standard Date object.\r\n * @param {object} jsonDate An date formatted as a json object.\r\n * @returns {Date} A Date object.\r\n */\r\nexport function convertDate(jsonDate) {\r\n return new Date(jsonDate);\r\n}\r\n\r\nexport function convertDateToDayString(date) {\r\n return [\r\n date.getFullYear(),\r\n padTo2Digits(date.getMonth() + 1),\r\n padTo2Digits(date.getDate()),\r\n ].join(\"-\");\r\n}\r\n\r\n/**\r\n * Converts a given local date to a short ISO 8601 formatted string.\r\n * @param {Date} date Date object.\r\n * @returns {String} Date as ISO 8601 formatted string.\r\n */\r\nexport function convertDateToShortIsoString(date) {\r\n let d = new Date(date);\r\n let isoString =\r\n d.getFullYear() +\r\n \"-\" +\r\n padTo2Digits(d.getMonth() + 1) +\r\n \"-\" +\r\n padTo2Digits(d.getDate()) +\r\n \"_\" +\r\n padTo2Digits(d.getHours()) +\r\n \"-\" +\r\n padTo2Digits(d.getMinutes()) +\r\n \"-\" +\r\n padTo2Digits(d.getSeconds());\r\n return isoString;\r\n}\r\n","// HSA imports\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n validateInstance,\r\n validateType,\r\n ValidationType,\r\n} from \"../utils/Utils\";\r\n\r\n// UIComponent sub-data class for Parameter\r\nclass UIComponent {\r\n /**\r\n * Create a new UIComponent of a InstantAnalysisModule Parameter.\r\n * @param {string} component The type of the UI component.\r\n * @param {string} label The label of the UI component.\r\n * @param {*} min Minimum value. For Sliders.\r\n * @param {*} max Maximum value. For Sliders.\r\n * @param {*} step Step size. For Sliders.\r\n * @param {*} default Initial value.\r\n * @param {*} value Optional. Current value. Default null.\r\n * @param {boolean | null} optional Optional. If ui should be inside an accordion. Default false.\r\n * @param {boolean} hidden Optional. If ui element should be hidden. Default false.\r\n * @param {array[int] | null} hiddenStructures Optional. Structure Ids where UI element should be hidden. -1 for all. Default [].\r\n * @param {array[object]} options Optional. Available options for e.g. select component. Default [].\r\n */\r\n constructor(\r\n component,\r\n label,\r\n min,\r\n max,\r\n step,\r\n defaultValue,\r\n value = null,\r\n optional = false,\r\n hidden = false,\r\n hiddenStructures = [],\r\n options = []\r\n ) {\r\n // Input validation\r\n validateType(\"component\", component, ValidationType.String);\r\n validateType(\"label\", label, ValidationType.String);\r\n validateType(\"optional\", optional, ValidationType.Bool);\r\n validateType(\"hidden\", hidden, ValidationType.Bool);\r\n validateType(\"hiddenStructures\", hiddenStructures, ValidationType.Array);\r\n hiddenStructures.forEach((structure) => {\r\n validateType(\"hiddenStructures\", structure, ValidationType.Int);\r\n });\r\n validateType(\"options\", options, ValidationType.Array);\r\n\r\n this.component = component;\r\n this.label = label;\r\n this.min = min;\r\n this.max = max;\r\n this.step = step;\r\n this.default = defaultValue;\r\n this.value = value ?? null;\r\n this.optional = optional ?? false;\r\n this.hidden = hidden ?? false;\r\n this.hiddenStructures = hiddenStructures ?? [];\r\n this.options = options ?? [];\r\n }\r\n\r\n /**\r\n * Create a new UIComponent from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per UIComponent constructor.\r\n * @param {object} obj An object containing all necessary properties of a UIComponent.\r\n * @returns {UIComponent} A new UIComponent\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new UIComponent(\r\n obj.component,\r\n obj.label,\r\n obj.min,\r\n obj.max,\r\n obj.step,\r\n obj.default,\r\n obj.value,\r\n obj.optional,\r\n obj.hidden,\r\n obj.hiddenStructures ?? undefined,\r\n obj.options\r\n );\r\n }\r\n}\r\n\r\n// Parameter sub-data class for InstantAnalysisModule\r\nexport class Parameter {\r\n /**\r\n * Create a new Parameter of a InstantAnalysisModule.\r\n * @param {string} name The name of the parameter.\r\n * @param {string | null} description Optional. The description of the parameter. Defaults to \"\".\r\n * @param {string} type The type of the parameter.\r\n * @param {UIComponent} ui The UI component of the parameter.\r\n */\r\n constructor(name, description = \"\", type, ui) {\r\n validateType(\"name\", name, ValidationType.String);\r\n validateType(\"description\", description, ValidationType.String);\r\n validateType(\"type\", type, ValidationType.String);\r\n validateInstance(\"ui\", ui, UIComponent);\r\n\r\n this.name = name;\r\n this.description = description ?? \"\";\r\n this.type = type;\r\n this.ui = ui;\r\n }\r\n\r\n /**\r\n * Create a new Parameter from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per Parameter constructor.\r\n * @param {object} obj An object containing all necessary properties of a Parameter.\r\n * @returns {Parameter} A new Parameter\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n return new Parameter(\r\n obj.name,\r\n obj.description,\r\n obj.type,\r\n UIComponent.fromObject(obj.ui)\r\n );\r\n }\r\n}\r\n\r\n// InstantAnalysisModule data class\r\nexport default class InstantAnalysisModule {\r\n /**\r\n * Create a new InstantAnalysisModule.\r\n * @param {string} name The name of the module.\r\n * @param {string} tooltip The tooltip of the module.\r\n * @param {string} description Optional. The description of the module. Defaults to \"\".\r\n * @param {boolean} preview Optional. Whether the module is a preview module. Defaults to false.\r\n * @param {boolean} shared Optional. Whether the module is a shared module. Defaults to false.\r\n * @param {string} icon The icon of the module.\r\n * @param {Parameter[]} toolParams The tool parameters of the module.\r\n * @param {object} parameters Optional. Further parameters of the module. Defaults to {}.\r\n */\r\n constructor(\r\n name,\r\n tooltip,\r\n description = \"\",\r\n preview = false,\r\n shared = false,\r\n icon,\r\n toolParams,\r\n parameters = {}\r\n ) {\r\n // Input validation\r\n validateType(\"name\", name, ValidationType.String);\r\n validateType(\"tooltip\", tooltip, ValidationType.String);\r\n validateType(\"description\", description, ValidationType.String);\r\n validateType(\"preview\", preview, ValidationType.Bool);\r\n validateType(\"shared\", shared, ValidationType.Bool);\r\n validateType(\"icon\", icon, ValidationType.String);\r\n validateType(\"toolParams\", toolParams, ValidationType.Array);\r\n toolParams.forEach((parameter) => {\r\n validateInstance(\"toolParams\", parameter, Parameter);\r\n });\r\n validateType(\"parameters\", parameters, ValidationType.Object);\r\n\r\n this.name = name;\r\n this.tooltip = tooltip;\r\n this.description = description ?? \"\";\r\n this.preview = preview ?? false;\r\n this.shared = shared ?? false;\r\n this.icon = icon;\r\n this.toolParams = toolParams;\r\n this.parameters = parameters ?? {};\r\n }\r\n\r\n /**\r\n * Create a new InstantAnalysisModule from an object without needing to define all parameters individually.\r\n * Accepts camelCase, PascalCase, and snake_case properties, with camelCase being the default.\r\n * Additional properties will be ignored,\r\n * missing properties will use defaults or throw error per InstantAnalysisModule contructor.\r\n * @param {object} obj An object containing all necessary properties of a InstantAnalysisModule.\r\n * @returns {InstantAnalysisModule} A new InstantAnalysisModule\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n\r\n validateType(\"obj.toolParams\", obj.toolParams, ValidationType.Array);\r\n\r\n return new InstantAnalysisModule(\r\n obj.name,\r\n obj.tooltip,\r\n obj.description,\r\n obj.preview,\r\n obj.shared,\r\n obj.icon,\r\n obj.toolParams.map((p) => Parameter.fromObject(p)),\r\n obj.parameters\r\n );\r\n }\r\n}\r\n","import { authenticationService } from '../services';\r\n\r\nexport function authHeader() {\r\n // return authorization header with jwt token\r\n const currentUser = authenticationService.currentUserValue;\r\n if (currentUser && currentUser.token) {\r\n return { Authorization: `Bearer ${currentUser.token}` };\r\n } else {\r\n return {};\r\n }\r\n}","import { authenticationService } from '../services';\r\n\r\nexport function handleResponse(response) {\r\n return response.text().then(text => {\r\n const data = text && JSON.parse(text);\r\n if (!response.ok) {\r\n if ([401, 403].indexOf(response.status) !== -1) {\r\n // auto logout if 401 Unauthorized or 403 Forbidden response returned from api\r\n authenticationService.logout();\r\n window.location.reload(true);\r\n }\r\n else if ([409].indexOf(response.status) !== -1) {\r\n authenticationService.logout();\r\n window.location = \"/licensing\";\r\n }\r\n\r\n const error = (data && data.message) || response.statusText;\r\n return Promise.reject(error);\r\n }\r\n\r\n return data;\r\n });\r\n}","import { createBrowserHistory } from 'history';\r\n\r\nexport const history = createBrowserHistory();","export const Role = {\r\n\tAdmin: 'Admin',\r\n\tUser: 'User' \r\n}","// ROI.jsx\r\n// Copyright HS Analysis GmbH, 2019\r\n// Author: Viktor Eberhardt, Sebastian Murgul\r\n\r\n// External imports\r\nimport * as turf from \"@turf/turf\";\r\n\r\n// HSA Imports\r\nimport { calcBoundingBox, simplifyRegions } from \"../utils/PolygonUtil\";\r\nimport { v4 as uuidv4 } from \"uuid\";\r\nimport { ImageRoi, ModificationStatus } from \"../../common/components/RoiTypes\";\r\n\r\n// Base class of a roi\r\n// Depreciated?\r\nexport class BaseROI {\r\n constructor() {\r\n this.strokeColor = \"green\";\r\n this.fillColor = null;\r\n }\r\n}\r\n\r\nexport class CommentROI {\r\n constructor(regions, color, type, commentValue, computedValue) {\r\n this.inverted = false;\r\n this.fontScaleFactor = 1;\r\n this.regions = regions;\r\n this.color = color;\r\n this.type = type;\r\n this.commentValue = commentValue;\r\n this.computedValue = computedValue;\r\n this.updateBounds();\r\n }\r\n\r\n updateBounds() {\r\n this.bounds = calcBoundingBox([this.regions]);\r\n this.width = this.bounds.right - this.bounds.left;\r\n this.height = this.bounds.bottom - this.bounds.top;\r\n }\r\n\r\n containsPoint(p) {\r\n return !(\r\n p.x < this.bounds.left ||\r\n p.x > this.bounds.right ||\r\n p.y < this.bounds.top ||\r\n p.y > this.bounds.bottom\r\n );\r\n }\r\n}\r\n\r\n// polygon roi\r\nexport class RegionROI {\r\n isObject = false;\r\n constructor(inputObj) {\r\n //this.regions = bufferSimplifyRegions(this.regions); //simplify old regions with small gap\r\n this.uuid = inputObj.uuid ? inputObj.uuid : uuidv4();\r\n this.inverted = false;\r\n\r\n let obj = {};\r\n if (inputObj instanceof ImageRoi) {\r\n obj.regions = inputObj.coordinates;\r\n obj.ai = inputObj.aiAnnotated;\r\n obj.z = inputObj.z;\r\n obj.t = inputObj.t;\r\n obj.structureId = inputObj.structure;\r\n obj.modificationStatus = inputObj.modificationStatus;\r\n } else {\r\n obj = inputObj;\r\n obj.modificationStatus = ModificationStatus.Added;\r\n }\r\n this.setRegions(obj.regions ? obj.regions : obj);\r\n\r\n this.center = {\r\n x: this.bounds.left + (this.bounds.right - this.bounds.left) / 2,\r\n y: this.bounds.top + (this.bounds.bottom - this.bounds.top) / 2,\r\n };\r\n this.borderColor = \"4px solid white\";\r\n\r\n this.isSubtype = obj.subtype\r\n ? obj.subtype\r\n : obj.isSubtype\r\n ? obj.isSubtype\r\n : false;\r\n this.color = obj.color1 ? obj.color1 : obj.color ? obj.color : \"#FFFFFF\";\r\n this.subtypeName = obj.name\r\n ? obj.name\r\n : obj.subtypeName\r\n ? obj.subtypeName\r\n : \"\";\r\n this.aiAnnotated = obj.ai\r\n ? obj.ai\r\n : obj.aiAnnotated\r\n ? obj.aiAnnotated\r\n : false;\r\n this.isAnnotated = obj.annotated\r\n ? obj.annotated\r\n : obj.isAnnotated\r\n ? obj.isAnnotated\r\n : false;\r\n this.isLabeled = obj.labeled\r\n ? obj.labeled\r\n : obj.isLabeled\r\n ? obj.isLabeled\r\n : false;\r\n this.isSelObj = obj.isSel ? obj.isSel : obj.isSelObj ? obj.isSelObj : false;\r\n this.isSaved = obj.saved ? obj.saved : obj.isSaved ? obj.isSaved : false;\r\n this.z = obj.z ? obj.z : 0;\r\n this.fullyLoaded = obj.fullyLoaded ? obj.fullyLoaded : false;\r\n this.comment = obj.comment ? obj.comment : \"\";\r\n this.tileName = obj.tileName ? obj.tileName : \"\";\r\n this.structureId = obj.structureId ? obj.structureId : 0;\r\n this.selected = obj.selected ? obj.selected : false;\r\n this.selectedWithKey = obj.selectedWithKey ? obj.selectedWithKey : false;\r\n this.frequencyClass = obj.frequencyClass ? obj.frequencyClass : -1;\r\n this.isObject = obj.isObject ? obj.isObject : false;\r\n if (this.regions[0].length > 5) this.isObject = false; //can not be object\r\n\r\n this.isStartData = false;\r\n this.aiIdx = 0;\r\n this.galleryIndex = null;\r\n this.firstTimeGallery = true;\r\n\r\n this.treeItem = {\r\n minX: this.bounds.left,\r\n minY: this.bounds.top,\r\n maxX: this.bounds.right,\r\n maxY: this.bounds.bottom,\r\n roi: this,\r\n };\r\n }\r\n\r\n /**\r\n * Converts the current RegionROI format to the ImageRoi format.\r\n * @param {uuid} fileId Database file id.\r\n * @param {uuid} userId Database user id.\r\n * @returns {ImageRoi} An ImageRoi object.\r\n */\r\n convertToImageROI = (fileId, userId) => {\r\n return ImageRoi.fromObject({\r\n modificationStatus: 0,\r\n structure: this.structureId,\r\n z: this.z,\r\n t: 0,\r\n coordinates: this.regions,\r\n minX: Math.floor(this.bounds.left),\r\n minY: Math.floor(this.bounds.top),\r\n maxX: Math.ceil(this.bounds.right),\r\n maxY: Math.ceil(this.bounds.bottom),\r\n annotationType: 0,\r\n id: this.uuid,\r\n fileId: fileId,\r\n isAiAnnotated: this.aiAnnotated,\r\n user: userId,\r\n });\r\n };\r\n\r\n copy = () => {\r\n let roiCopy = new RegionROI(this);\r\n roiCopy.regions = JSON.parse(JSON.stringify(this.regions)); // [...this.regions];\r\n roiCopy.uuid = this.uuid;\r\n roiCopy.color = this.color;\r\n roiCopy.isSubtype = this.isSubtype;\r\n roiCopy.isAnnotated = this.isAnnotated;\r\n roiCopy.subtypeName = this.subtypeName;\r\n roiCopy.structureId = this.structureId;\r\n roiCopy.isLabeled = this.isLabeled;\r\n roiCopy.isSelObj = this.isSelObj;\r\n roiCopy.aiAnnotated = this.aiAnnotated;\r\n return roiCopy;\r\n };\r\n\r\n getBoundsColorId = () => {\r\n return (\r\n this.bounds.left +\r\n \"_\" +\r\n this.bounds.top +\r\n \"_\" +\r\n this.bounds.right +\r\n \"_\" +\r\n this.bounds.bottom +\r\n \"_\" +\r\n this.color\r\n );\r\n };\r\n\r\n getPointOnPoly() {\r\n let poly = turf.polygon(this.regions);\r\n var pointOnPolygon = turf.centerOfMass(poly);\r\n return {\r\n x: pointOnPolygon.geometry.coordinates[0],\r\n y: pointOnPolygon.geometry.coordinates[1],\r\n };\r\n }\r\n\r\n /** Create turf region for coordinate set.\r\n *\r\n * @param {Array} regions Regions to be edited. Must have format [[[x,y], ..., [x,y]]]\r\n */\r\n setRegions(regions) {\r\n try {\r\n // Allow redundant styles of nesting\r\n if (typeof regions[0][0] === \"number\") {\r\n regions = [regions];\r\n } else if (typeof regions[0][0][0] === \"number\") {\r\n // regions = regions; -> Do nothing\r\n } else {\r\n regions = regions[0];\r\n }\r\n\r\n // use less float digits\r\n for (let region of regions) {\r\n for (let point of region) {\r\n point[0] = +point[0].toFixed(2);\r\n point[1] = +point[1].toFixed(2);\r\n }\r\n }\r\n\r\n for (let region of regions) {\r\n if (\r\n region[0][0] !== region[region.length - 1][0] ||\r\n region[0][1] !== region[region.length - 1][1]\r\n ) {\r\n region.push(region[0]);\r\n }\r\n }\r\n this.bounds = calcBoundingBox(regions);\r\n try {\r\n let poly = turf.polygon(regions);\r\n let converted = turf.toWgs84(poly);\r\n this.area = turf.area(converted);\r\n } catch (e) {\r\n this.area = -1;\r\n }\r\n if (this.area < 0) {\r\n this.area =\r\n (this.bounds.right - this.bounds.left) *\r\n (this.bounds.bottom - this.bounds.top);\r\n }\r\n\r\n this.regions = regions; // simplifyRegions(regions, 0.01);\r\n } catch {\r\n console.log(\"Error, regions could not be set:\", regions);\r\n }\r\n }\r\n\r\n removeDuplicates(inputRegions) {\r\n for (let regions of inputRegions) {\r\n let resultRegions = [];\r\n if (regions.length > 2) {\r\n regions.push(regions[0]);\r\n let resultRegions = [regions[0]];\r\n for (let i = 1; i < regions.length; i++) {\r\n let p1 = regions[i - 1];\r\n let p2 = regions[i];\r\n let isEqual = p1[0] === p2[0] && p1[1] === p2[1];\r\n if (!isEqual) {\r\n resultRegions.push(p2);\r\n }\r\n }\r\n }\r\n inputRegions = resultRegions;\r\n }\r\n return inputRegions;\r\n }\r\n\r\n getRectRegions() {\r\n return [\r\n [\r\n [this.bounds.left, this.bounds.top],\r\n [this.bounds.right, this.bounds.top],\r\n [this.bounds.right, this.bounds.bottom],\r\n [this.bounds.left, this.bounds.bottom],\r\n [this.bounds.left, this.bounds.top],\r\n ],\r\n ];\r\n }\r\n\r\n getSimplifiedRectRegions() {\r\n return [\r\n [\r\n [parseInt(this.bounds.left, 10), parseInt(this.bounds.top, 10)],\r\n [parseInt(this.bounds.right, 10), parseInt(this.bounds.top, 10)],\r\n [parseInt(this.bounds.right, 10), parseInt(this.bounds.bottom, 10)],\r\n [parseInt(this.bounds.left, 10), parseInt(this.bounds.bottom, 10)],\r\n [parseInt(this.bounds.left, 10), parseInt(this.bounds.top, 10)],\r\n ],\r\n ];\r\n }\r\n\r\n //return regions, so that rendering is still fast\r\n getDynamicRegions(comp, numObjects) {\r\n if (comp > 0.001 || numObjects < 100) {\r\n //if big, return original\r\n return this.regions;\r\n }\r\n\r\n if (comp < 0.00005) {\r\n //if very small return rectangles (bounding box)\r\n return this.getSimplifiedRectRegions();\r\n } else if (typeof this.intRegions === \"undefined\") {\r\n //else return rounded polygon\r\n this.intRegions = this.regions.map((regions) => {\r\n return regions.map((p) => [parseInt(p[0], 10), parseInt(p[1], 10)]);\r\n });\r\n }\r\n\r\n if (comp < 0.0005) {\r\n if (typeof this.simplifyedRegions === \"undefined\") {\r\n this.simplifyedRegions = simplifyRegions(this.intRegions, 1);\r\n }\r\n return this.simplifyedRegions;\r\n }\r\n return this.intRegions;\r\n }\r\n\r\n intersects(p1, p2) {\r\n return !(\r\n p2.x < this.bounds.left ||\r\n p1.x > this.bounds.right ||\r\n p2.y < this.bounds.top ||\r\n p1.y > this.bounds.bottom\r\n );\r\n }\r\n\r\n boundsAreaCompare(p1, p2) {\r\n let pArea = Math.abs(p2.x - p1.x) * Math.abs(p2.y - p1.y);\r\n let b = this.bounds;\r\n let area = Math.abs(b.right - b.left) * Math.abs(b.bottom - b.top);\r\n return area / pArea;\r\n }\r\n\r\n sameBoundsWith(roi) {\r\n return (\r\n this.bounds.left === roi.bounds.left &&\r\n this.bounds.right === roi.bounds.right &&\r\n this.bounds.top === roi.bounds.top &&\r\n this.bounds.bottom === roi.bounds.bottom\r\n );\r\n }\r\n\r\n /**\r\n * Converts the current ImageRoi format to the legacy RegionROI format.\r\n * @param {ImageRoi | Obj} inputObj An ImageRoi object or an object with the same properties as an ImageRoi.\r\n * @returns {RegionROI} A RegionROI object.\r\n */\r\n static legacyRegionRoifromDatabase(inputObj) {\r\n if (!(inputObj instanceof ImageRoi)) {\r\n inputObj = new ImageRoi.fromObject(inputObj);\r\n }\r\n const newRegionRoi = {};\r\n newRegionRoi.aiAnnotated = inputObj.isAiAnnotated;\r\n newRegionRoi.modificationStatus = inputObj.modificationStatus;\r\n newRegionRoi.regions = inputObj.coordinates;\r\n newRegionRoi.structureId = inputObj.structure;\r\n newRegionRoi.t = inputObj.t;\r\n newRegionRoi.uuid = inputObj.id;\r\n newRegionRoi.z = inputObj.z;\r\n newRegionRoi.isAnnotated = false;\r\n newRegionRoi.isLabeled = false;\r\n newRegionRoi.isSelObj = false;\r\n newRegionRoi.isSaved = false;\r\n newRegionRoi.fullyLoaded = false;\r\n newRegionRoi.comment = \"\";\r\n newRegionRoi.tileName = \"\";\r\n newRegionRoi.selected = false;\r\n newRegionRoi.selectedWithKey = false;\r\n newRegionRoi.frequencyClass = -1;\r\n newRegionRoi.isObject = false;\r\n\r\n return new RegionROI(newRegionRoi);\r\n }\r\n}\r\n\r\n// simple recatangle roi\r\n// Depreciated?\r\nexport class RectROI extends BaseROI {\r\n constructor(ctx, x, y, w, h, drawingMode = false) {\r\n super();\r\n this.x = x;\r\n this.y = y;\r\n this.w = w;\r\n this.h = h;\r\n this.ctx = ctx;\r\n if (drawingMode) {\r\n this.resizePoint = 3;\r\n }\r\n }\r\n\r\n summary() {\r\n return (\r\n \"Rect (\" +\r\n Math.round(this.x) +\r\n \",\" +\r\n Math.round(this.y) +\r\n \",\" +\r\n Math.round(this.w) +\r\n \",\" +\r\n Math.round(this.h) +\r\n \")\"\r\n );\r\n }\r\n\r\n handleMouseDown(p1) {\r\n let cornerRadius = 5 / this.ctx.getTransform().a;\r\n if (\r\n p1.x >= this.x - cornerRadius &&\r\n p1.x <= this.x + cornerRadius &&\r\n p1.y >= this.y - cornerRadius &&\r\n p1.y <= this.y + cornerRadius\r\n ) {\r\n this.resizePoint = 0;\r\n return 2;\r\n } else if (\r\n p1.x >= this.x + this.w - cornerRadius &&\r\n p1.x <= this.x + this.w + cornerRadius &&\r\n p1.y >= this.y - cornerRadius &&\r\n p1.y <= this.y + cornerRadius\r\n ) {\r\n this.resizePoint = 1;\r\n return 2;\r\n } else if (\r\n p1.x >= this.x - cornerRadius &&\r\n p1.x <= this.x + cornerRadius &&\r\n p1.y >= this.y + this.h - cornerRadius &&\r\n p1.y <= this.y + this.h + cornerRadius\r\n ) {\r\n this.resizePoint = 2;\r\n return 2;\r\n } else if (\r\n p1.x >= this.x + this.w - cornerRadius &&\r\n p1.x <= this.x + this.w + cornerRadius &&\r\n p1.y >= this.y + this.h - cornerRadius &&\r\n p1.y <= this.y + this.h + cornerRadius\r\n ) {\r\n this.resizePoint = 3;\r\n return 2;\r\n } else if (\r\n p1.x >= this.x &&\r\n p1.x <= this.x + this.w &&\r\n p1.y >= this.y &&\r\n p1.y <= this.y + this.h\r\n ) {\r\n this.dragStart = p1;\r\n return 1;\r\n }\r\n }\r\n\r\n handleMouseMove(p1) {\r\n let cornerRadius = 5 / this.ctx.getTransform().a;\r\n if (\r\n p1.x >= this.x - cornerRadius &&\r\n p1.x <= this.x + cornerRadius &&\r\n p1.y >= this.y - cornerRadius &&\r\n p1.y <= this.y + cornerRadius\r\n ) {\r\n this.ctx.canvas.style.cursor = \"se-resize\";\r\n this.hovered = true;\r\n } else if (\r\n p1.x >= this.x + this.w - cornerRadius &&\r\n p1.x <= this.x + this.w + cornerRadius &&\r\n p1.y >= this.y - cornerRadius &&\r\n p1.y <= this.y + cornerRadius\r\n ) {\r\n this.ctx.canvas.style.cursor = \"ne-resize\";\r\n this.hovered = true;\r\n } else if (\r\n p1.x >= this.x - cornerRadius &&\r\n p1.x <= this.x + cornerRadius &&\r\n p1.y >= this.y + this.h - cornerRadius &&\r\n p1.y <= this.y + this.h + cornerRadius\r\n ) {\r\n this.ctx.canvas.style.cursor = \"ne-resize\";\r\n this.hovered = true;\r\n } else if (\r\n p1.x >= this.x + this.w - cornerRadius &&\r\n p1.x <= this.x + this.w + cornerRadius &&\r\n p1.y >= this.y + this.h - cornerRadius &&\r\n p1.y <= this.y + this.h + cornerRadius\r\n ) {\r\n this.ctx.canvas.style.cursor = \"se-resize\";\r\n this.hovered = true;\r\n } else if (\r\n p1.x >= this.x &&\r\n p1.x <= this.x + this.w &&\r\n p1.y >= this.y &&\r\n p1.y <= this.y + this.h\r\n ) {\r\n if (this.ctx.canvas.style.cursor === \"default\") {\r\n this.ctx.canvas.style.cursor = \"pointer\";\r\n }\r\n this.hovered = true;\r\n } else {\r\n this.hovered = false;\r\n }\r\n }\r\n\r\n handleMouseUp() {\r\n // heal rois (fix negative width and height)\r\n if (this.w < 0) {\r\n this.x += this.w;\r\n this.w = -this.w;\r\n }\r\n if (this.h < 0) {\r\n this.y += this.h;\r\n this.h = -this.h;\r\n }\r\n }\r\n\r\n drag(p1, vw, vh) {\r\n // apply relative movement\r\n this.x += p1.x - this.dragStart.x;\r\n this.y += p1.y - this.dragStart.y;\r\n\r\n // check if out of image bounds\r\n this.x = Math.max(Math.min(vw - this.w, this.x), 0);\r\n this.y = Math.max(Math.min(vh - this.h, this.y), 0);\r\n\r\n // save cursor position\r\n this.dragStart = p1;\r\n }\r\n\r\n resize(p1, vw, vh) {\r\n // check if out of image bounds\r\n p1.x = Math.max(Math.min(vw, p1.x), 0);\r\n p1.y = Math.max(Math.min(vh, p1.y), 0);\r\n\r\n if (this.resizePoint === 0) {\r\n this.w -= p1.x - this.x;\r\n this.x = p1.x;\r\n this.h -= p1.y - this.y;\r\n this.y = p1.y;\r\n\r\n if ((this.w > 0 && this.h > 0) || (this.w < 0 && this.h < 0)) {\r\n this.ctx.canvas.style.cursor = \"se-resize\";\r\n } else {\r\n this.ctx.canvas.style.cursor = \"ne-resize\";\r\n }\r\n } else if (this.resizePoint === 1) {\r\n this.w += p1.x - this.w - this.x;\r\n this.h -= p1.y - this.y;\r\n this.y = p1.y;\r\n\r\n if ((this.w > 0 && this.h > 0) || (this.w < 0 && this.h < 0)) {\r\n this.ctx.canvas.style.cursor = \"ne-resize\";\r\n } else {\r\n this.ctx.canvas.style.cursor = \"se-resize\";\r\n }\r\n } else if (this.resizePoint === 2) {\r\n this.w -= p1.x - this.x;\r\n this.x = p1.x;\r\n this.h += p1.y - this.h - this.y;\r\n\r\n if ((this.w > 0 && this.h > 0) || (this.w < 0 && this.h < 0)) {\r\n this.ctx.canvas.style.cursor = \"ne-resize\";\r\n } else {\r\n this.ctx.canvas.style.cursor = \"se-resize\";\r\n }\r\n } else if (this.resizePoint === 3) {\r\n this.w += p1.x - this.w - this.x;\r\n this.h += p1.y - this.h - this.y;\r\n\r\n if ((this.w > 0 && this.h > 0) || (this.w < 0 && this.h < 0)) {\r\n this.ctx.canvas.style.cursor = \"se-resize\";\r\n } else {\r\n this.ctx.canvas.style.cursor = \"ne-resize\";\r\n }\r\n }\r\n }\r\n\r\n draw() {\r\n this.ctx.strokeStyle = this.strokeColor;\r\n\r\n if (this.hovered) this.ctx.strokeStyle = \"yellow\";\r\n\r\n // fixed line width\r\n this.ctx.lineWidth = 2 / this.ctx.getTransform().a;\r\n\r\n // custom drawing\r\n this.ctx.beginPath();\r\n this.ctx.rect(this.x, this.y, this.w, this.h);\r\n this.ctx.stroke();\r\n this.ctx.closePath();\r\n\r\n if (this.hovered) {\r\n this.ctx.lineWidth = 1 / this.ctx.getTransform().a;\r\n let cornerDiameter = 10 / this.ctx.getTransform().a;\r\n let cornerRadius = 5 / this.ctx.getTransform().a;\r\n\r\n this.ctx.fillStyle = \"white\";\r\n this.ctx.strokeStyle = \"black\";\r\n\r\n // draw corner haptic\r\n this.ctx.beginPath();\r\n this.ctx.rect(\r\n this.x - cornerRadius,\r\n this.y - cornerRadius,\r\n cornerDiameter,\r\n cornerDiameter\r\n );\r\n this.ctx.rect(\r\n this.x + this.w - cornerRadius,\r\n this.y - cornerRadius,\r\n cornerDiameter,\r\n cornerDiameter\r\n );\r\n this.ctx.rect(\r\n this.x - cornerRadius,\r\n this.y + this.h - cornerRadius,\r\n cornerDiameter,\r\n cornerDiameter\r\n );\r\n this.ctx.rect(\r\n this.x + this.w - cornerRadius,\r\n this.y + this.h - cornerRadius,\r\n cornerDiameter,\r\n cornerDiameter\r\n );\r\n this.ctx.fill();\r\n this.ctx.stroke();\r\n this.ctx.closePath();\r\n }\r\n }\r\n}\r\n\r\nfunction getFirstValidatedIndexValue(item, index) {\r\n if (item && item[index] && item[index].length > 0) {\r\n return item[index][0];\r\n } else {\r\n return item;\r\n }\r\n}\r\n\r\nfunction getOnlyValidatedSimpleIndexValue(item, index) {\r\n if (item && item[index] && item[index].length > 0) {\r\n return item[index];\r\n } else {\r\n return null;\r\n }\r\n}\r\n\r\nexport function createRoisFromAnno(anno, structureId = null) {\r\n if (structureId == null && typeof anno.geoJSON.structureId === \"undefined\") {\r\n console.error(\r\n \"StructureId is not defined in annotation and not passed as parameter\",\r\n { structureId, anno }\r\n );\r\n }\r\n return anno.geoJSON.coordinates\r\n .filter((c) => c.length > 0)\r\n .map((c, index) => {\r\n const r = new RegionROI({\r\n uuid: getOnlyValidatedSimpleIndexValue(anno.geoJSON.uuid, index),\r\n regions: c,\r\n color1: getFirstValidatedIndexValue(anno.geoJSON.color1, index),\r\n subtype: getFirstValidatedIndexValue(anno.geoJSON.subtype, index),\r\n name: getFirstValidatedIndexValue(anno.geoJSON.name, index),\r\n ai: getFirstValidatedIndexValue(anno.geoJSON.aiAnnotated, index),\r\n annotated: getFirstValidatedIndexValue(anno.geoJSON.isAnnotated, index),\r\n labeled: getFirstValidatedIndexValue(anno.geoJSON.isLabeled, index),\r\n isSel: getFirstValidatedIndexValue(anno.geoJSON.isSelObj, index),\r\n saved: getFirstValidatedIndexValue(anno.geoJSON.isSaved, index),\r\n z: getFirstValidatedIndexValue(anno.geoJSON.z, index),\r\n comment: getFirstValidatedIndexValue(anno.geoJSON.comment, index),\r\n tileName: getFirstValidatedIndexValue(anno.geoJSON.tileName, index),\r\n structureId:\r\n structureId ??\r\n getFirstValidatedIndexValue(anno.geoJSON.structureId, index),\r\n isObject: getFirstValidatedIndexValue(anno.geoJSON.isObject, index),\r\n frequencyCl: getFirstValidatedIndexValue(anno.geoJSON.frequencyClass),\r\n });\r\n return r;\r\n });\r\n}\r\n","// Copyright: HS Analysis GmbH, 2023\r\n// Author: Valentin Haas\r\n\r\n// HSA imports\r\nimport { isInt, isUuid, validateInstance } from \"../utils/Utils\";\r\nimport { Parameter } from \"./InstantAnalysisModule\";\r\nimport {\r\n convertPascalCaseKeysToCamelCase,\r\n convertSnakeCaseKeysToCamelCase,\r\n validateType,\r\n ValidationType,\r\n} from \"../utils/Utils\";\r\n\r\n//#region AI Inference Parameters\r\n\r\n/**\r\n * General class for all dataset specific parameters of an AI Training.\r\n */\r\nexport class InferenceParameters {\r\n constructor(confidenceThreshold = 0.15) {\r\n // Input validation\r\n validateType(\r\n \"confidenceThreshold\",\r\n confidenceThreshold,\r\n ValidationType.Number\r\n );\r\n\r\n // Set parameters\r\n this.confidenceThreshold = confidenceThreshold;\r\n }\r\n\r\n /**\r\n * Converts an object to an InferenceParameters.\r\n * @param {Object} obj An object with the properties of the InferenceParameters.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n return new InferenceParameters(obj.confidenceThreshold);\r\n }\r\n}\r\n\r\n/**\r\n * All model specific parameters of an image model AI Training.\r\n * @param {number} confidenceThreshold Confidence threshold for the inference.\r\n * @param {number} minObjectSize Optional. Minimum object size as area for the inference. Default: null\r\n * @param {number} maxObjectSize Optional. Maximum object size as area for the inference. Default: null\r\n * @param {number} minIntensity Optional. Minimum intensity of the object for the inference. Default: null\r\n * @param {number} maxIntensity Optional. Maximum intensity of the object for the inference. Default: null\r\n */\r\nexport class ImageInferenceParameters extends InferenceParameters {\r\n constructor({\r\n confidenceThreshold,\r\n minObjectSize = null,\r\n maxObjectSize = null,\r\n minIntensity = null,\r\n maxIntensity = null,\r\n } = {}) {\r\n super(confidenceThreshold);\r\n\r\n // Input validation\r\n if (minObjectSize !== null)\r\n validateType(\"minObjectSize\", minObjectSize, ValidationType.Number);\r\n if (maxObjectSize !== null)\r\n validateType(\"maxObjectSize\", maxObjectSize, ValidationType.Number);\r\n if (minIntensity !== null)\r\n validateType(\"minIntensity\", minIntensity, ValidationType.Number);\r\n if (maxIntensity !== null)\r\n validateType(\"maxIntensity\", maxIntensity, ValidationType.Number);\r\n\r\n this.minObjectSize = minObjectSize;\r\n this.maxObjectSize = maxObjectSize;\r\n this.minIntensity = minIntensity;\r\n this.maxIntensity = maxIntensity;\r\n }\r\n\r\n /**\r\n * Converts an object to an ImageInferenceParameters.\r\n * @param {Object} obj An object with the properties of the ImageInferenceParameters.\r\n * @returns {ImageInferenceParameters} The converted ImageInferenceParameters.\r\n **/\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n return new ImageInferenceParameters({\r\n confidence: obj.confidence,\r\n minimumObjectSize: obj.minimumObjectSize,\r\n maximumObjectSize: obj.maximumObjectSize,\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * All model specific parameters of an audio model AI Training.\r\n * @param {number} confidence Confidence threshold for the inference.\r\n * @param {number} minTimeSeconds Optional. Minimum time in seconds for the inference. Default: null\r\n * @param {number} maxTimeSeconds Optional. Maximum time in seconds for the inference. Default: null\r\n * @param {number} minFrequencyHz Optional. Minimum frequency in Hz for the inference. Default: null\r\n * @param {number} maxFrequencyHz Optional. Maximum frequency in Hz for the inference. Default: null\r\n */\r\nexport class AudioInferenceParameters extends InferenceParameters {\r\n constructor(\r\n confidence,\r\n minTimeSeconds = null,\r\n maxTimeSeconds = null,\r\n minFrequencyHz = null,\r\n maxFrequencyHz = null\r\n ) {\r\n super(confidence);\r\n\r\n // Input validation\r\n if (minTimeSeconds !== null)\r\n validateType(\"minTimeSeconds\", minTimeSeconds, ValidationType.Number);\r\n if (maxTimeSeconds !== null)\r\n validateType(\"maxTimeSeconds\", maxTimeSeconds, ValidationType.Number);\r\n if (minFrequencyHz !== null)\r\n validateType(\"minFrequencyHz\", minFrequencyHz, ValidationType.Number);\r\n if (maxFrequencyHz !== null)\r\n validateType(\"maxFrequencyHz\", maxFrequencyHz, ValidationType.Number);\r\n\r\n // Set parameters\r\n this.minTimeSeconds = minTimeSeconds;\r\n this.maxTimeSeconds = maxTimeSeconds;\r\n this.minFrequencyHz = minFrequencyHz;\r\n this.maxFrequencyHz = maxFrequencyHz;\r\n }\r\n\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n return new AudioInferenceParameters(\r\n obj.confidence,\r\n obj.minTimeSeconds,\r\n obj.maxTimeSeconds,\r\n obj.minFrequencyHz,\r\n obj.maxFrequencyHz\r\n );\r\n }\r\n}\r\n\r\n//#endregion\r\n\r\n//#region Search Areas\r\n\r\n/**\r\n * Parent class for search areas.\r\n * Abstract class, should not be used directly.\r\n */\r\nclass SearchArea {}\r\n\r\n/**\r\n * Search area for image-based analysis.\r\n * @param {number} x Origin of a rectangle in x direction of image coordinates. Must be a positive integer.\r\n * @param {number} y Origin of a rectangle in y direction of image coordinates. Must be a positive integer.\r\n * @param {number} z First z-Layer in a z-Stack image. Must be a positive integer. Default: 0\r\n * @param {number} t First timepoint in a time series image. Must be a positive integer. Default: 0\r\n * @param {number} w Width of the search area in x direction of image coordinates. Must be a positive integer.\r\n * @param {number} h Height of the search area in y direction of image coordinates. Must be a positive integer.\r\n * @param {number} d Depth of the search area in z direction of image coordinates. Must be a positive integer. Default: 1\r\n * @param {number} l Length of the search area in amount of frames of a time series image. Must be a positive integer. Default: 1\r\n */\r\nexport class ImageSearchArea extends SearchArea {\r\n constructor(x, y, z = 0, t = 0, w, h, d = 1, l = 1) {\r\n super();\r\n\r\n validateType(\"x\", x, ValidationType.Int);\r\n validateType(\"y\", y, ValidationType.Int);\r\n validateType(\"z\", z, ValidationType.Int);\r\n validateType(\"t\", t, ValidationType.Int);\r\n validateType(\"w\", w, ValidationType.Int);\r\n validateType(\"h\", h, ValidationType.Int);\r\n validateType(\"d\", d, ValidationType.Int);\r\n validateType(\"l\", l, ValidationType.Int);\r\n\r\n this.x = x;\r\n this.y = y;\r\n this.z = z;\r\n this.t = t;\r\n this.w = w;\r\n this.h = h;\r\n this.d = d;\r\n this.l = l;\r\n }\r\n}\r\n\r\n/**\r\n * Search area for audio-based analysis.\r\n * @param {number} startTime Start time of the search area in seconds.\r\n * @param {number} endTime End time of the search area in seconds.\r\n * @param {number} minFreq Minimum frequency of search area in Hertz.\r\n * @param {number} maxFreq Maximum frequency of search area in Hertz.\r\n * @param {array[int]} channels Channels within search area.\r\n */\r\nexport class AudioSearchArea extends SearchArea {\r\n constructor(startTime, endTime, minFreq, maxFreq, channels) {\r\n super();\r\n\r\n // Input validation\r\n validateType(\"startTime\", startTime, ValidationType.Number);\r\n validateType(\"endTime\", endTime, ValidationType.Number);\r\n validateType(\"minFreq\", minFreq, ValidationType.Number);\r\n validateType(\"maxFreq\", maxFreq, ValidationType.Number);\r\n validateType(\"channels\", channels, ValidationType.Array);\r\n channels.forEach((channel) => {\r\n validateType(\"channel\", channel, ValidationType.Int);\r\n });\r\n\r\n this.startTime = startTime;\r\n this.endTime = endTime;\r\n this.minFreq = minFreq;\r\n this.maxFreq = maxFreq;\r\n this.channels = channels;\r\n }\r\n\r\n /**\r\n * Converts an object to an AudioSearchArea.\r\n * @param {Object} obj An object with the properties of the AudioSearchArea.\r\n * @returns {AudioSearchArea} The converted AudioSearchArea.\r\n * */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n return new AudioSearchArea(\r\n obj.startTime,\r\n obj.endTime,\r\n obj.minFreq,\r\n obj.maxFreq,\r\n obj.channels\r\n );\r\n }\r\n}\r\n\r\n//#endregion\r\n\r\n/**\r\n * Instant Analysis Module Config.\r\n * Used to transmit the settings for applying a model to files within a project in the set structures.\r\n * @param {string} iamName Name of the instant analysis module (IAM) to be used.\r\n * @param {UUID} projectId Project Id of the project the IAM is applied to.\r\n * @param {Parameter[]} parameters Tool parameters of the IAM.\r\n * @param {UUID[]} fileIds File Ids of the files the IAM is applied to. Will be processed in the order of the array.\r\n * @param {int[]} structureIds Structure Ids of the structures the IAM is applied to. IAMs will be applied to structures in the order of the array.\r\n * @param {boolean} previewOnly If true, the IAM results will not be saved, but only a preview will be generated. Default: false.\r\n * @param {SearchArea} searchArea Search area of the IAM. If null, the whole file will be processed. Default: null\r\n */\r\nexport default class IAMConfig {\r\n constructor(\r\n iamName,\r\n projectId,\r\n parameters,\r\n fileIds,\r\n structureIds,\r\n previewOnly = false,\r\n searchArea = null\r\n ) {\r\n validateType(\"iamName\", iamName, ValidationType.String);\r\n\r\n if (!isUuid(projectId)) {\r\n throw TypeError(\r\n `projectId must be of type UUID, received ${typeof projectId}: ${projectId}`\r\n );\r\n }\r\n\r\n validateType(\"parameters\", parameters, ValidationType.Array);\r\n parameters.forEach((parameter) => {\r\n validateInstance(\"parameter\", parameter, Parameter);\r\n });\r\n\r\n validateType(\"fileIds\", fileIds, ValidationType.Array);\r\n fileIds.forEach((fileId) => {\r\n if (!isUuid(fileId)) {\r\n throw TypeError(\r\n `fileIds must be of type array of UUID, received ${typeof fileId}: ${fileId}`\r\n );\r\n }\r\n });\r\n\r\n validateType(\"structureIds\", structureIds, ValidationType.Array);\r\n structureIds.forEach((structureId) => {\r\n if (!isInt(structureId) || structureId < 0) {\r\n throw TypeError(\r\n `structureIds must be of type array of positive integers, received ${typeof structureId}: ${structureId}`\r\n );\r\n }\r\n });\r\n\r\n validateType(\"previewOnly\", previewOnly, ValidationType.Bool);\r\n if (searchArea !== null)\r\n validateInstance(\"searchArea\", searchArea, SearchArea);\r\n\r\n this.iamName = iamName;\r\n this.projectId = projectId;\r\n this.parameters = parameters;\r\n this.fileIds = fileIds;\r\n this.structureIds = structureIds;\r\n this.previewOnly = previewOnly;\r\n this.searchArea = searchArea;\r\n }\r\n\r\n /**\r\n * Converts an object to an IAMConfig.\r\n * @param {Object} obj An object with the properties of the IAMConfig.\r\n * @returns {IAMConfig} The converted IAMConfig.\r\n */\r\n static fromObject(obj) {\r\n obj = convertPascalCaseKeysToCamelCase(obj);\r\n obj = convertSnakeCaseKeysToCamelCase(obj);\r\n return new IAMConfig(\r\n obj.iamName,\r\n obj.projectId,\r\n obj.parameters.map((param) => Parameter.fromObject(param)),\r\n obj.fileIds,\r\n obj.structureIds,\r\n obj.previewOnly,\r\n obj.searchArea\r\n );\r\n }\r\n}\r\n","// Structure Utils.jsx\r\n// A collection of utils to use for the legacy structure format.\r\n\r\n// Copyright HS Analysis Gmbh, 2021\r\n// Author: Valentin Haas\r\n\r\n// HSA imports\r\nimport Structure, { getSameLevelRank } from \"../../common/components/Structure\";\r\nimport { isHexColor, rgbaToHex } from \"../../common/utils/Utils\";\r\n\r\n/**\r\n * Generates an array which references all contained structures to their parent structure.\r\n * Each row of the array starts with the child and ends with the topmost parent.\r\n * The function stops at structures or substructures.\r\n * Overlying structures will not see the subtypes contained inside the structure.\r\n * @param {Array} structures All structures, substructures, and subtypes seen in sidebar.\r\n * @returns {Array} Array of parents, child is the first entry of each row, respectively.\r\n */\r\nexport function generateParentList(structures) {\r\n let parentList = [];\r\n // First, each structure contains itself sa a minimum.\r\n for (let structure of structures) {\r\n parentList.push([structure]);\r\n }\r\n\r\n // Find all parents of a structure, bottom up.\r\n for (let idx = 0; idx < parentList.length; idx++) {\r\n let continueSearch = true;\r\n while (continueSearch) {\r\n let currentStruct = parentList[idx];\r\n // We're done when we reach the topmost layer\r\n // or if the next level would be a (sub-) structure\r\n if (\r\n !currentStruct[currentStruct.length - 1].classificationSubtype ||\r\n currentStruct[currentStruct.length - 1].parentId === 0\r\n ) {\r\n continueSearch = false;\r\n break;\r\n }\r\n\r\n // Add the parent structure to the row.\r\n parentList[idx].push(\r\n structures[\r\n getParentIndex(currentStruct[currentStruct.length - 1], structures)\r\n ]\r\n );\r\n }\r\n }\r\n\r\n return parentList;\r\n}\r\n\r\n/**\r\n * Generates an array which references all contained structures to their child structures.\r\n * Each row of the array starts with the parent and ends with the bottom-most child.\r\n * The function stops at structures or substructures.\r\n * Underlying structures will not see the subtypes contained inside the structure.\r\n * @param {Array} structures All structures, substructures, and subtypes seen in sidebar.\r\n * @returns {Array} Array of children, parent is the first entry of each row, respectively.\r\n */\r\nexport function generateChildrenList(structures) {\r\n let childrenList = [];\r\n for (let structure of structures) {\r\n childrenList.push(\r\n generateAListOfAllChildrenRecursively(structure, structures)\r\n );\r\n }\r\n return childrenList;\r\n}\r\n\r\n/**\r\n * Recursively goes down the structure tree, beginning from the given parent.\r\n * Adds all structures along the way until it reaches a structure without children.\r\n * @param {Object} structure The selected structure/substructure/subtype for this iteration.\r\n * @param {Array} structures All structures, substructures, and subtypes seen in sidebar.\r\n * @returns {Array} Array of Children when done.\r\n * @returns {Array} Object of a child in an array when child does not have a child of its own.\r\n */\r\nfunction generateAListOfAllChildrenRecursively(structure, structures) {\r\n // Continue until we reach the bottom-most layer\r\n // or if the current structure would be a (sub-) structure\r\n if (structure.hasChild) {\r\n // Add the structure itself to the tree\r\n let allChildren = [];\r\n allChildren.push(structure);\r\n\r\n // Find all children of the structure, that are subtypes, not substructures\r\n let children = structures.filter(\r\n (struct) =>\r\n struct.classificationSubtype && struct.parentId === structure.id\r\n );\r\n\r\n // Recursively add all children and children of children\r\n for (let child of children) {\r\n allChildren.push(\r\n ...generateAListOfAllChildrenRecursively(child, structures)\r\n );\r\n }\r\n return allChildren;\r\n } else {\r\n // No children, bottom-level child returns itself\r\n return [structure];\r\n }\r\n}\r\n\r\n/**\r\n * Returns index of the topmost parent structure\r\n * @param {Object} structure The selected structure/substructure/subtype from the sidebar.\r\n * @param {Array} structures All structures, substructures, and subtypes seen in sidebar.\r\n * @returns {Int} the index of the topmost parent structure.\r\n */\r\nexport function getParentIndexLayer(structure, structures) {\r\n let index = structures.findIndex((element) => element === structure);\r\n while (\r\n structures[index].subtypeLevel !== 0 &&\r\n structures[index].classificationSubtype\r\n ) {\r\n index = getParentIndex(structures[index], structures);\r\n }\r\n return structures.findIndex((element) => element === structures[index]);\r\n}\r\n\r\n/**\r\n * Returns index of the direct parent structure\r\n * @param {Object} structure The selected structure/substructure/subtype from the sidebar.\r\n * @param {Array} structures All structures, substructures, and subtypes seen in sidebar.\r\n * @returns {Int} the index of the parent structure.\r\n */\r\nexport function getParentIndex(structure, structures) {\r\n // return index of parent structure\r\n return structures.findIndex((element) => element.id === structure.parentId);\r\n}\r\n\r\n/**\r\n * Returns objects for a given structure, including its subtypes.\r\n * @param {Object} structure - The selected structure/substructure/subtype from the sidebar.\r\n * @param {Array} structures - All structures, substructures, and subtypes seen in the sidebar.\r\n * @param {List} roiLayers - Annotations of the structures ordered by structure.\r\n * @returns {List} - All ROIs for a certain structure, including its subtypes.\r\n */\r\nexport function getContainedRegionRois(structure, structures, roiLayers) {\r\n // Find the index of the given structure within the structures array\r\n const idx = structures.findIndex((struct) => struct.id === structure.id);\r\n // Generate a list of parent structures for each structure in the structures array\r\n const parentList = generateParentList(structures);\r\n\r\n // Find the direct parent of the given structure\r\n const parent = parentList[idx][parentList[idx].length - 1];\r\n\r\n // Find the index of the parent structure within the structures array\r\n const parentIdx = structures.findIndex((struct) => struct.id === parent.id);\r\n\r\n // Generate a list of children structures for each structure in the structures array,\r\n // then retrieve the children IDs for the given structure\r\n const decendantIds = generateChildrenList(structures)[idx].map(\r\n ({ id }) => id\r\n );\r\n\r\n // Filter the ROI layer of the parent structure to only include ROIs\r\n // that belong to the given structure and its decendants\r\n return roiLayers[parentIdx].layer.regionRois.filter((roi) =>\r\n decendantIds.includes(roi.structureId)\r\n );\r\n}\r\n\r\n/**\r\n * Updates the full structure tree of a structure, ensuring correctly displayed icons.\r\n * @param {Object} structure The full tree of this structure will be updated.\r\n * @param {Array} structures All structures. Contains the structure given.\r\n * @returns {Array} Updated structures.\r\n */\r\nexport function updateStructures(structure, structures) {\r\n // Check for missing strucutre import\r\n if (!structure) {\r\n console.debug(\"Error: No structure given, canceling strucutre update\");\r\n return structures;\r\n }\r\n\r\n // Get toplevel parent\r\n let toplevelParentIndex = getParentIndexLayer(structure, structures);\r\n\r\n // Not found, therefore return unedited structures\r\n if (toplevelParentIndex === -1) {\r\n console.debug(\r\n \"Error: Could not find top level parent when updating structures.\"\r\n );\r\n return structures;\r\n }\r\n\r\n // Get all children of toplevel parent\r\n let fullChildrenList = generateChildrenList(structures);\r\n let children = fullChildrenList[toplevelParentIndex];\r\n\r\n // Update their status\r\n for (let structure of children) {\r\n // Find children of currently viewed child\r\n let currentChildren = fullChildrenList.find(\r\n (children) => children[0].id === structure.id\r\n );\r\n\r\n // Update properties\r\n structure.hasChild = currentChildren.length > 0;\r\n\r\n // Find location of current structure in structures\r\n let structureIndex = structures.findIndex(\r\n (struct) => struct.id === structure.id\r\n );\r\n\r\n // Overwrite with updated properties\r\n structures[structureIndex] = structure;\r\n }\r\n\r\n return structures;\r\n}\r\n\r\n/**\r\n * Converts the legacy structures (ProjectModel.Structure) to the new structure format.\r\n * @param {Array[object]} structures All structures in a project, still in the legacy ProjectModel.Structure format.\r\n * @param {Array[object]} roiLayers The roiLayers of a loaded project.\r\n * @returns {Array[Structure]} The converted structures.\r\n */\r\nexport function convertLegacyStructures(structures, roiLayers) {\r\n const convertedStructures = structures.map((structure) => {\r\n return new Structure(\r\n structure.id,\r\n structure.label,\r\n !structure.classificationSubtype,\r\n isHexColor(structure.color)\r\n ? structure.color\r\n : rgbaToHex(structure.color),\r\n structure.dynamic,\r\n structure.parentId > 0 ? structure.parentId : null,\r\n 0, // sameLevelRank determined below\r\n structure.inversed,\r\n structure.isUnfolded,\r\n structure.visible,\r\n structure.hasChild,\r\n structure.subtypeLevel,\r\n getNumberOfAnnotations(structure, structures, roiLayers),\r\n true,\r\n false,\r\n [],\r\n null\r\n );\r\n });\r\n\r\n convertedStructures.forEach((structure) => {\r\n structure.sameLevelRank = getSameLevelRank(structure, convertedStructures);\r\n });\r\n\r\n return convertedStructures;\r\n}\r\n\r\n/**\r\n * Calculate the number of annotations assigend to a given structure.\r\n * @param {object} structure A structure in the legacy ProjectModel.Structure format.\r\n * @param {Array[object]} structures All structures in a project, still in the legacy ProjectModel.Structure format.\r\n * @param {Array[object]} roiLayers The roiLayers of a loaded project.\r\n * @returns {int} The calculated number of annotations for the structure.\r\n */\r\nexport function getNumberOfAnnotations(structure, structures, roiLayers) {\r\n if (structure.isSubtype) {\r\n const containedRois = getContainedRegionRois(\r\n structure,\r\n structures,\r\n roiLayers\r\n );\r\n return containedRois.length;\r\n } else {\r\n const structureIndex = structures.findIndex(\r\n (element) => element.id === structure.id\r\n );\r\n const roiLayer = roiLayers[structureIndex];\r\n return roiLayer ? roiLayer.layer.regionRois.length : 0;\r\n }\r\n}\r\n"],"sourceRoot":""}