mirror of
https://github.com/JHUAPL/PINE.git
synced 2026-01-09 14:38:06 -05:00
Merge pull request #18 from jhuapl-lglenden/develop-updates
Image annotation and MongoDB updates.
This commit is contained in:
@@ -33,11 +33,15 @@ RUN apt-get -y update && \
|
||||
pip3 install --upgrade pip gunicorn pipenv
|
||||
|
||||
# Install latest mongodb
|
||||
# It can no longer be installed from packages due to the packages relying on systemctl which is not
|
||||
# in the Ubuntu docker image.
|
||||
# https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu-tarball/
|
||||
ARG MONGO_VERSION=ubuntu1804-4.2.11
|
||||
RUN if [ -n "${DB_DIR}" ] ; then \
|
||||
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv E162F504A20CDF15827F718D4B7C549A058F8B6B && \
|
||||
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" > /etc/apt/sources.list.d/mongodb-org-4.2.list && \
|
||||
apt-get -y update && \
|
||||
apt-get install -y mongodb-org mongodb-org-server mongodb-org-tools mongodb-org-shell; \
|
||||
apt-get -y install libcurl4 openssl liblzma5 wget && \
|
||||
wget --progress=dot https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-${MONGO_VERSION}.tgz && \
|
||||
tar xzf mongodb-linux-x86_64-${MONGO_VERSION}.tgz && \
|
||||
mv mongodb-linux-x86_64-${MONGO_VERSION}/bin/* /usr/local/bin/; \
|
||||
fi
|
||||
|
||||
# Install python packages
|
||||
|
||||
@@ -29,6 +29,28 @@
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.image-annotation-container {
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
width: 204px;
|
||||
bottom: 10px;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.image-annotation-divider {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.image-annotation-list {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding-left: 8px;
|
||||
padding-right:4px;
|
||||
}
|
||||
|
||||
/* annotation tab */
|
||||
.filter-bar {
|
||||
position: absolute;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<!-- (C) 2019 The Johns Hopkins University Applied Physics Laboratory LLC.-->
|
||||
<div fxFlexFill class="page-container" fxLayout="column">
|
||||
<mat-toolbar class="title-toolbar">
|
||||
<button class="doc-back-button" mat-icon-button matTooltip="Go back to collection details" (click)="backToCollectionDetails()">
|
||||
<button class="doc-back-button" mat-icon-button matTooltip="Go back to collection details"
|
||||
(click)="backToCollectionDetails()">
|
||||
<mat-icon>keyboard_arrow_left</mat-icon>
|
||||
</button>
|
||||
<span class="page-title">Document {{doc?._id}}</span>
|
||||
@@ -56,8 +57,8 @@
|
||||
<b>
|
||||
Document Overall Agreement:
|
||||
</b>
|
||||
<span *ngIf="ann_agreement != undefined">{{ann_agreement | percent:'1.2-2'}}</span>
|
||||
<span *ngIf="ann_agreement == undefined">N/A</span>
|
||||
<span *ngIf="ann_agreement != null && ann_agreement != 'null'">{{ann_agreement | percent:'1.2-2'}}</span>
|
||||
<span *ngIf="ann_agreement == null || ann_agreement == 'null'">N/A</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -127,7 +128,8 @@
|
||||
</button>
|
||||
<app-error></app-error>
|
||||
<span fxFlex></span>
|
||||
<button class="annotate-button" mat-raised-button (click)="save(false)" [disabled]="!canCurrentlyAnnotate">
|
||||
<button class="annotate-button" mat-raised-button (click)="save(false)"
|
||||
[disabled]="!canCurrentlyAnnotate">
|
||||
<span class="material-icons">save</span>Save
|
||||
</button>
|
||||
<span fxFlex="10px"></span>
|
||||
@@ -140,6 +142,31 @@
|
||||
|
||||
<section *ngIf="tabIndex == 1 && !loading.loading && !loading.error" #imageSection fxFlexFill>
|
||||
<div *ngIf="doc.metadata && doc.metadata['imageUrl']" id="myDocImage" class="image-container">
|
||||
<mat-card class="image-annotation-container" fxLayout="column">
|
||||
<div>Annotations</div>
|
||||
<mat-divider class="image-annotation-divider"></mat-divider>
|
||||
<div class="image-annotation-list" fxLayout="column">
|
||||
<mat-chip-list class="mat-chip-list-stacked">
|
||||
<mat-checkbox *ngFor="let annotation of myDocAnnotations;" [(ngModel)]="annotation.checked">
|
||||
<mat-chip [style.background-color]="annotation.label.color"
|
||||
class="shadowed cursor-pointer">
|
||||
{{annotation.label.name}}</mat-chip>
|
||||
</mat-checkbox>
|
||||
</mat-chip-list>
|
||||
|
||||
</div>
|
||||
<div fxLayout="row">
|
||||
<mat-error *ngIf="!canAnnotate" id="cantAnnotate">
|
||||
<h3>Note: you do not have authority to change or add annotations for this document.</h3>
|
||||
</mat-error>
|
||||
<span fxFlex></span>
|
||||
<button class="btn-short annotate-button" mat-raised-button color="primary"
|
||||
(click)="save(false)" [disabled]="!canCurrentlyAnnotate">
|
||||
<span class="material-icons">save</span>Save
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</mat-card>
|
||||
<div style="position: absolute; top: 0px; bottom: 0; left: 0; right: 0;">
|
||||
<button class="full-screen-btn" mat-raised-button
|
||||
(click)="toggleImageFullscreen()">{{ isImageFullscreen() ? 'Close' : 'Open' }} Full
|
||||
|
||||
@@ -62,8 +62,9 @@ export class AnnotateComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild(LoadingComponent)
|
||||
public loading: LoadingComponent;
|
||||
|
||||
@ViewChild(ErrorComponent)
|
||||
public error: ErrorComponent;
|
||||
public htmlError: string;
|
||||
public httpError: HttpErrorResponse;
|
||||
public errorOperation: string;
|
||||
|
||||
@ViewChild("docElem")
|
||||
public docElem: ElementRef;
|
||||
@@ -558,6 +559,12 @@ export class AnnotateComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
}
|
||||
|
||||
private clearError() {
|
||||
this.httpError = null;
|
||||
this.htmlError = null;
|
||||
this.errorOperation = null;
|
||||
}
|
||||
|
||||
public save(andAdvance: boolean) {
|
||||
if (!this.canAnnotate) { return; }
|
||||
const docAnnotations = [];
|
||||
@@ -566,7 +573,7 @@ export class AnnotateComponent implements OnInit, AfterViewInit {
|
||||
docAnnotations.push(annotation.label.name);
|
||||
}
|
||||
}
|
||||
this.error.clear();
|
||||
this.clearError();
|
||||
this.annotations.saveAnnotations(this.doc._id, docAnnotations, this.nerData.annotations).subscribe((id: string) => {
|
||||
this.myNerAnnotations = this.nerData.annotations;
|
||||
this.changed = false;
|
||||
@@ -581,12 +588,13 @@ export class AnnotateComponent implements OnInit, AfterViewInit {
|
||||
this.advanceToNext();
|
||||
}
|
||||
}, (error: HttpErrorResponse) => {
|
||||
this.error.showHttp(error, "saving annotations");
|
||||
this.httpError = error;
|
||||
this.errorOperation = "saving annotations";
|
||||
});
|
||||
}
|
||||
|
||||
private advanceToNext() {
|
||||
this.error.clear();
|
||||
this.clearError();
|
||||
this.pipelines.advanceToNextDocumentForClassifier(this.classifier._id, this.doc._id).subscribe((success: boolean) => {
|
||||
if (success) {
|
||||
this.pipelines.getNextDocumentIdForClassifier(this.classifier._id).subscribe((documentId: string) => {
|
||||
@@ -599,13 +607,15 @@ export class AnnotateComponent implements OnInit, AfterViewInit {
|
||||
this.router.navigate([`/${PATHS.collection.details}`, this.collection._id]);
|
||||
}
|
||||
}, (error: HttpErrorResponse) => {
|
||||
this.error.showHttp(error, "advancing to next document");
|
||||
this.httpError = error;
|
||||
this.errorOperation = "advancing to next document";
|
||||
});
|
||||
} else {
|
||||
this.error.showHtml("Unable to advance to next document.");
|
||||
this.htmlError = "Unable to advance to next document.";
|
||||
}
|
||||
}, (error: HttpErrorResponse) => {
|
||||
this.error.showHttp(error, "advancing to next document");
|
||||
this.httpError = error;
|
||||
this.errorOperation = "advancing to next document";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*(C) 2019 The Johns Hopkins University Applied Physics Laboratory LLC. */
|
||||
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from "@angular/core";
|
||||
import { HttpErrorResponse } from "@angular/common/http";
|
||||
|
||||
@Component({
|
||||
@@ -8,7 +8,11 @@ import { HttpErrorResponse } from "@angular/common/http";
|
||||
templateUrl: "./error.component.html",
|
||||
styleUrls: ["./error.component.css"]
|
||||
})
|
||||
export class ErrorComponent implements OnInit {
|
||||
export class ErrorComponent implements OnInit, OnChanges {
|
||||
|
||||
@Input() httpError: HttpErrorResponse;
|
||||
@Input() htmlError: string;
|
||||
@Input() operation: string = null;
|
||||
|
||||
public visible = false;
|
||||
|
||||
@@ -19,6 +23,16 @@ export class ErrorComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if(this.htmlError) {
|
||||
this.showHtml(this.htmlError);
|
||||
} else if(this.htmlError) {
|
||||
this.showHttp(this.httpError);
|
||||
} else {
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public clear() {
|
||||
this.visible = false;
|
||||
this.innerHTML = "";
|
||||
|
||||
@@ -54,4 +54,12 @@
|
||||
.image-invert {
|
||||
-webkit-filter: invert(1);
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.pan-zoom-container {
|
||||
position: absolute;
|
||||
top: 54px;
|
||||
left: 224px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
@@ -12,8 +12,8 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button [color]="mode === 'invert' ? 'primary' : 'default'" class="image-btn image-btn-space image-btn-invert" mat-raised-button
|
||||
(click)="setMode('invert')" matTooltip="Invert Colors">
|
||||
<button [color]="mode === 'invert' ? 'primary' : 'default'" class="image-btn image-btn-space image-btn-invert"
|
||||
mat-raised-button (click)="setMode('invert')" matTooltip="Invert Colors">
|
||||
<mat-icon>compare</mat-icon>
|
||||
</button>
|
||||
<button [color]="mode === 'sharpen' ? 'primary' : 'default'" class="image-btn image-btn-space" mat-raised-button
|
||||
@@ -22,14 +22,19 @@
|
||||
</button>
|
||||
<button [color]="mode === 'histogram' ? 'primary' : 'default'" class="image-btn image-btn-space" mat-raised-button
|
||||
(click)="setMode('histogram')" matTooltip="Histogram Equalizer">
|
||||
<mat-icon>bar_chart</mat-icon>
|
||||
<mat-icon>insert_chart</mat-icon>
|
||||
</button>
|
||||
<button class="image-btn image-btn-space" mat-raised-button (click)="setMode('none')" matTooltip="Clear Filters">
|
||||
<mat-icon>layers_clear</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<pan-zoom [config]="panZoomConfig">
|
||||
<canvas id="imageCanvas" #imageCanvas [ngStyle]="{ 'filter': mode === 'invert' ? 'invert(1)' : 'none' }"></canvas>
|
||||
</pan-zoom>
|
||||
<div class="pan-zoom-container">
|
||||
<pan-zoom [config]="panZoomConfig">
|
||||
<canvas id="imageCanvas" #imageCanvas
|
||||
[ngStyle]="{ 'filter': mode === 'invert' ? 'invert(1)' : 'none' }"></canvas>
|
||||
</pan-zoom>
|
||||
</div>
|
||||
|
||||
<div *ngIf="loadError" class="image-error"><mat-error>Error Loading Image</mat-error></div>
|
||||
<div *ngIf="loadError" class="image-error">
|
||||
<mat-error>Error Loading Image</mat-error>
|
||||
</div>
|
||||
@@ -88,8 +88,8 @@ describe("Sanity Tests", function() {
|
||||
.within(() => {
|
||||
cy.contains("PINE", {timeout: 20 * 1000})
|
||||
.should("be.visible", {timeout: 20 * 1000});
|
||||
cy.contains("database")
|
||||
.should("be.visible");
|
||||
cy.contains("database", {timeout: 20 * 1000})
|
||||
.should("be.visible", {timeout: 20 * 1000});
|
||||
});
|
||||
cy.get("app-about")
|
||||
.find("button").contains("Close")
|
||||
|
||||
Reference in New Issue
Block a user