createOrUpdateAnnotation()

in pathology/viewer/src/components/image-viewer-side-nav/image-viewer-side-nav.component.ts [753:852]


  createOrUpdateAnnotation() {
    const slideInfo = this.getSlideInfo();
    if (!slideInfo) return;

    const sopInstanceUid = slideInfo.levelMap[0].properties[0].instanceUid;

    if (!sopInstanceUid) {
      return;
    }
    const annotations: SideNavLayer[] = [...this.sideNavDrawLayers];
    const annotationGroups =
        annotations
            .filter((annotation) => {
              return annotation.annotatorId === this.currentUser;
            })
            .map((annotation, index) => {
              const annotationKey = getFeatureAnnotationKey(annotation.feature);
              annotationKey.notes = annotationKey?.notes?.trim() ?? '';
              const coordinates =
                  ((((annotation.feature as Feature<Polygon>).getGeometry())
                        ?.getCoordinates() ??
                    [])[0] as Coordinate[]);
              // Set label to be the first 3 words of the comment otherwise ROI.
              const annotationLabel = (annotationKey.notes ?? '')
                                          .split(' ')
                                          .slice(0, 3)
                                          .join(' ')
                                          .substring(0, 15) ||
                  'ROI';

              const annotationGroup: AnnotationGroup = {
                idNumber: index + 1,
                annotationGroupUid: '',
                annotationGroupLabel: annotationLabel,
                annotationGroupDescription: annotationKey.notes ?? '',
                annotationGroupGenerationType: 'MANUAL',
                annotationPropertyCategoryCodeSequence: [],
                graphicType: 'POLYGON',
                pointCoordinatesData: coordinates,
                longPrimitivePointIndexList: [1],  // DICOM indices are 1 based
              };
              return annotationGroup;
            });

    const seriesId = this.selectedSplitViewSlideDescriptor?.id as string;

    const slidePath = parseDICOMwebUrl(seriesId).path;
    if (!slidePath.studyUID || !slidePath.seriesUID) return;

    const referencedSeries: ReferencedSeries =
        this.annotationInstances
            .find(
                (annotationInstance) =>
                    annotationInstance.annotatorId === this.currentUser &&
                    annotationInstance.referencedSeries.seriesInstanceUid ===
                        slidePath.seriesUID)
            ?.referencedSeries ??
        // If not found, create an ReferencedSeries based on slideInfo.
        {
          seriesInstanceUid: slidePath.seriesUID,
          referencedImage: {
            sopClassUid: slideInfo.sopClassUid,
            sopInstanceUid: slideInfo.levelMap[0].properties[0].instanceUid,
            dicomModel: slideInfo.levelMap[0].dicomModel,
            pixelSize: {
              width: slideInfo.levelMap[0].pixelWidth,
              height: slideInfo.levelMap[0].pixelHeight
            },
          }
        } as ReferencedSeries;

    const dicomAnnotation: DicomAnnotation = {
      instance: {
        path: {
          studyUID: slidePath.studyUID,
        },
        annotatorId: this.currentUser,
        referencedSeries,
      },
      annotationCoordinateType: '2D',
      annotationGroupSequence: annotationGroups,
    };

    this.imageViewerPageStore
        .createOrModifyDicomAnnotation(
            this.getSelectedSlideId(),
            dicomAnnotation,
            )
        .pipe(
            catchError((error) => {
              this.snackBar.open('Failed to write annotation', 'Dismiss', {
                duration: 3000,
              });
              // Remove recently added feature.
              this.handleRecentFeature();
              return error;
            }),
            )
        .subscribe();
  }