Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@lunit/insight-viewer2

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lunit/insight-viewer2

dcm viewer component library

  • 0.2.2
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
0
Maintainers
1
Weekly downloads
 
Created
Source

cornerstone 등 OPT 기능을 구현하기 위한 여러 graphics layer를 구현한다.

Install

npm install @lunit/insight-viewer2

Sample Codes

Storybook

Stories

__stories__/InsightViewer.stories.tsx

```tsx import { withOptTheme } from '@lunit/opt-theme'; import { storiesOf } from '@storybook/react'; import React from 'react'; import { InsightViewer } from '../components/InsightViewer'; import { useInsightViewerSync } from '../hooks/useInsightViewerSync'; import { CornerstoneSingleImage } from '../image/CornerstoneSingleImage'; import { CornerstoneImage } from '../image/types'; import { installWADOImageLoader, unloadWADOImage } from '../installWADO'; import { useController, withTestController } from './decorators/withTestController';

// cornerstoneWADOImageLoader 초기화 installWADOImageLoader();

// 을 변경하면 Viewport 등 cornerstone-core 관련 속성들이 초기화 된다 const resetTime: number = Date.now();

// unload 옵션은 위에 선언된 installWADOImageLoader()와 함께 동작한다 // CornerstoneImage 객체를 unload 할때 wado image loader의 unload 동작을 하게 된다 const image: CornerstoneImage = new CornerstoneSingleImage(wadouri:samples/series/CT000010.dcm, {unload: unloadWADOImage});

function Sample() { // addDecorator(withTestController())의 값을 받는다 const { width, height, control, wheel, invert, flip, } = useController();

const { updateCornerstoneRenderData, } = useInsightViewerSync();

return ( <InsightViewer width={width} height={height} invert={invert} flip={flip} pan={control === 'pan'} adjust={control === 'adjust'} zoom={wheel === 'zoom'} resetTime={resetTime} image={image} updateCornerstoneRenderData={updateCornerstoneRenderData}/> ); }

storiesOf('insight-viewer2', module) .addDecorator(withOptTheme) .addDecorator(withTestController({ width: [600, 400, 1000], height: [700, 400, 1000], control: ['pan', ['none', 'pan', 'adjust']], wheel: ['zoom', ['none', 'zoom']], flip: false, invert: false, })) .add('', () => );

<h3>__stories__/MachineHeatmapViewer.stories.tsx</h3>
```tsx
import { MachineHeatmapViewer } from '@lunit/insight-viewer2';
import { withOptTheme } from '@lunit/opt-theme';
import { storiesOf } from '@storybook/react';
import React, { useState } from 'react';
import { InsightViewer } from '../components/InsightViewer';
import { InsightViewerContainer } from '../components/InsightViewerContainer';
import { ProgressViewer } from '../components/ProgressViewer';
import { UserContourDrawer } from '../components/UserContourDrawer';
import { UserContourViewer } from '../components/UserContourViewer';
import { useInsightViewerSync } from '../hooks/useInsightViewerSync';
import { useUserContour } from '../hooks/useUserContour';
import { CornerstoneSingleImage } from '../image/CornerstoneSingleImage';
import { CornerstoneImage } from '../image/types';
import { installWADOImageLoader, unloadWADOImage } from '../installWADO';
import { useController, withTestController } from './decorators/withTestController';
import data from './posMap.sample.json';

const {engine_result: {engine_result: {pos_map: posMap}}} = data;

installWADOImageLoader();

const resetTime: number = Date.now();
const image: CornerstoneImage = new CornerstoneSingleImage(`wadouri:samples/series/CT000010.dcm`, {unload: unloadWADOImage});

function Sample() {
  const {
    width,
    height,
    control,
    wheel,
    invert,
    flip,
  } = useController();
  
  const [interactionElement, setInteractionElement] = useState<HTMLElement | null>(null);
  
  const {
    cornerstoneRenderData,
    updateCornerstoneRenderData,
  } = useInsightViewerSync();
  
  const {
    contours,
    focusedContour,
    addContour,
    removeContour,
    focusContour,
  } = useUserContour();
  
  return (
    <InsightViewerContainer ref={setInteractionElement} width={width} height={height}>
      <InsightViewer width={width}
                     height={height}
                     invert={invert}
                     flip={flip}
                     pan={control === 'pan' && interactionElement}
                     adjust={control === 'adjust' && interactionElement}
                     zoom={wheel === 'zoom' && interactionElement}
                     resetTime={resetTime}
                     image={image}
                     updateCornerstoneRenderData={updateCornerstoneRenderData}/>
      {/*
      engineResult.posMap을 그리는 Layer
      현재 Heatmap Spec (number[][])에 맞춰서 개발되었기 때문에
      Spec이 다르다면 새로운 Viewer를 만들어야 한다
      */}
      <MachineHeatmapViewer width={width}
                            height={height}
                            posMap={posMap}
                            threshold={0.1}
                            cornerstoneRenderData={cornerstoneRenderData}/>
      {
        contours &&
        contours.length > 0 &&
        cornerstoneRenderData &&
        <UserContourViewer width={width}
                           height={height}
                           contours={contours}
                           focusedContour={focusedContour}
                           cornerstoneRenderData={cornerstoneRenderData}/>
      }
      {
        contours &&
        cornerstoneRenderData &&
        control === 'pen' &&
        <UserContourDrawer width={width}
                           height={height}
                           contours={contours}
                           draw={control === 'pen' && interactionElement}
                           onFocus={focusContour}
                           onAdd={contour => addContour(contour, 0)}
                           onRemove={removeContour}
                           cornerstoneRenderData={cornerstoneRenderData}/>
      }
      <ProgressViewer image={image}
                      width={width}
                      height={height}/>
    </InsightViewerContainer>
  );
}

storiesOf('insight-viewer2', module)
  .addDecorator(withOptTheme)
  .addDecorator(withTestController({
    width: [600, 400, 1000],
    height: [700, 400, 1000],
    control: ['pan', ['none', 'pen', 'pan', 'adjust']],
    wheel: ['zoom', ['none', 'zoom']],
    flip: false,
    invert: false,
  }))
  .add('<MachineHeatmapViewer>', () => <Sample/>);

__stories__/ProgressCollector.stories.tsx

```tsx import { withOptTheme } from '@lunit/opt-theme'; import { storiesOf } from '@storybook/react'; import React, { CSSProperties } from 'react'; import { InsightViewer } from '../components/InsightViewer'; import { InsightViewerContainer } from '../components/InsightViewerContainer'; import { ProgressCollector, ProgressViewer, useContainerStyleOfProgressViewersInactivity, useProgressViewersActivity, } from '../components/ProgressViewer'; import { useInsightViewerSync } from '../hooks/useInsightViewerSync'; import { CornerstoneSeriesImage } from '../image/CornerstoneSeriesImage'; import { CornerstoneSingleImage } from '../image/CornerstoneSingleImage'; import { CornerstoneImage } from '../image/types'; import { installWADOImageLoader, unloadWADOImage } from '../installWADO'; import { useController, withTestController } from './decorators/withTestController'; import series from './series.json';

installWADOImageLoader();

const resetTime: number = Date.now(); const image1: CornerstoneImage = new CornerstoneSingleImage(wadouri:samples/series/CT000010.dcm, {unload: unloadWADOImage}); const image2: CornerstoneImage = new CornerstoneSingleImage(wadouri:samples/series/CT000020.dcm, {unload: unloadWADOImage}); const image3: CornerstoneImage = new CornerstoneSingleImage(wadouri:samples/series/CT000030.dcm, {unload: unloadWADOImage}); const image4: CornerstoneImage = new CornerstoneSeriesImage(series.map(p => wadouri:samples/series/${p}), {unload: unloadWADOImage});

function Sample() { // 는 하위의 들의 상태를 수집한다 return ( ); }

function Container() { // 에서 수집한 정보를 얻을 수 있다 const progressActivity: boolean = useProgressViewersActivity(); // 혹은 가 동작중일때 비활성을 처리할 Style을 만들 수 있다 const containerDisabledStyle: CSSProperties = useContainerStyleOfProgressViewersInactivity({pointerEvents: 'none'});

return (

<div style={{display: 'flex'}}>

{ progressActivity ? '가 하나 이상 작동 중입니다!!!' : '동작중인 가 없습니다!!!' }

); }

function Component({image}: {image: CornerstoneImage}) { const { width, height, control, wheel, invert, flip, } = useController();

const {updateCornerstoneRenderData} = useInsightViewerSync();

return ( <InsightViewer width={width} height={height} invert={invert} flip={flip} pan={control === 'pan'} adjust={control === 'adjust'} zoom={wheel === 'zoom'} resetTime={resetTime} image={image} updateCornerstoneRenderData={updateCornerstoneRenderData}/> {/* 이 에 수집된다 */} ); }

storiesOf('insight-viewer2', module) .addDecorator(withOptTheme) .addDecorator(withTestController({ width: [300, 200, 500], height: [400, 300, 600], control: ['pan', ['none', 'pen', 'pan', 'adjust']], wheel: ['zoom', ['none', 'zoom']], flip: false, invert: false, })) .add('', () => );

<h3>__stories__/SeriesImage.stories.tsx</h3>
```tsx
import { UserContourDrawer, UserContourViewer, useUserContour } from '@lunit/insight-viewer2';
import { withOptTheme } from '@lunit/opt-theme';
import { storiesOf } from '@storybook/react';
import React, { useState } from 'react';
import { InsightViewer } from '../components/InsightViewer';
import { InsightViewerContainer } from '../components/InsightViewerContainer';
import { ProgressViewer } from '../components/ProgressViewer';
import { useBulkImageScroll } from '../hooks/useBulkImageScroll';
import { useInsightViewerSync } from '../hooks/useInsightViewerSync';
import { CornerstoneSeriesImage } from '../image/CornerstoneSeriesImage';
import { CornerstoneBulkImage } from '../image/types';
import { installWADOImageLoader, unloadWADOImage } from '../installWADO';
import { withSeriesImageController } from './decorators/withSeriesImageController';
import { useController, withTestController } from './decorators/withTestController';
import series from './series.json';

installWADOImageLoader();

const resetTime: number = Date.now();

// CornerstoneSeriesImage는 여러장의 dcm 이미지를 받는다
const image: CornerstoneBulkImage = new CornerstoneSeriesImage(series.map(p => `wadouri:samples/series/${p}`), {unload: unloadWADOImage});

function Component() {
  const {
    width,
    height,
    control,
    wheel,
    invert,
    flip,
  } = useController();
  
  const [interactionElement, setInteractionElement] = useState<HTMLElement | null>(null);
  
  const {
    cornerstoneRenderData,
    updateCornerstoneRenderData,
  } = useInsightViewerSync();
  
  const {
    contours,
    focusedContour,
    addContour,
    removeContour,
    focusContour,
  } = useUserContour();
  
  // CornerstoneBulkImage를 Wheel과 연결 시킨다
  useBulkImageScroll({
    image,
    element: interactionElement,
    enabled: wheel === 'scroll',
  });
  
  return (
    <InsightViewerContainer ref={setInteractionElement} width={width} height={height}>
      <InsightViewer width={width}
                     height={height}
                     invert={invert}
                     flip={flip}
                     pan={control === 'pan' && interactionElement}
                     adjust={control === 'adjust' && interactionElement}
                     zoom={wheel === 'zoom' && interactionElement}
                     resetTime={resetTime}
                     image={image}
                     updateCornerstoneRenderData={updateCornerstoneRenderData}/>
      {
        contours &&
        contours.length > 0 &&
        cornerstoneRenderData &&
        <UserContourViewer width={width}
                           height={height}
                           contours={contours}
                           focusedContour={focusedContour}
                           cornerstoneRenderData={cornerstoneRenderData}/>
      }
      {
        contours &&
        cornerstoneRenderData &&
        control === 'pen' &&
        <UserContourDrawer width={width}
                           height={height}
                           contours={contours}
                           draw={control === 'pen' && interactionElement}
                           onFocus={focusContour}
                           onAdd={contour => addContour(contour, 0)}
                           onRemove={removeContour}
                           cornerstoneRenderData={cornerstoneRenderData}/>
      }
      <ProgressViewer image={image}
                      width={width}
                      height={height}/>
    </InsightViewerContainer>
  );
}

storiesOf('insight-viewer2', module)
  .addDecorator(withOptTheme)
  .addDecorator(withTestController({
    width: [600, 400, 1000],
    height: [700, 400, 1000],
    control: ['pan', ['none', 'pen', 'pan', 'adjust']],
    wheel: ['scroll', ['none', 'zoom', 'scroll']],
    flip: false,
    invert: false,
  }))
  .addDecorator(withSeriesImageController(image))
  .add('Series Image', () => <Component/>);

__stories__/UserContourViewer.stories.tsx

```tsx import { withOptTheme } from '@lunit/opt-theme'; import { storiesOf } from '@storybook/react'; import React, { useState } from 'react'; import { InsightViewer } from '../components/InsightViewer'; import { InsightViewerContainer } from '../components/InsightViewerContainer'; import { ProgressViewer } from '../components/ProgressViewer'; import { UserContourDrawer } from '../components/UserContourDrawer'; import { UserContourViewer } from '../components/UserContourViewer'; import { useInsightViewerSync } from '../hooks/useInsightViewerSync'; import { useUserContour } from '../hooks/useUserContour'; import { CornerstoneSingleImage } from '../image/CornerstoneSingleImage'; import { CornerstoneImage } from '../image/types'; import { installWADOImageLoader, unloadWADOImage } from '../installWADO'; import { useController, withTestController } from './decorators/withTestController';

installWADOImageLoader();

const resetTime: number = Date.now(); const image: CornerstoneImage = new CornerstoneSingleImage(wadouri:samples/series/CT000010.dcm, {unload: unloadWADOImage});

function Sample() { const { width, height, control, wheel, invert, flip, } = useController();

// pan, adjust, zoom은 // pan={true}로 설정하면 내부 Element를 사용해서 MouseEvent를 처리하게 되고, // pan={HTMLElement}로 설정하면 해당 Element를 사용해서 MouseEvent를 처리하게 된다. // MouseEvent를 처리하는 Layer가 여러개 중첩될 때, 하위 Layer의 MouseEvent가 막히는 현상을 해결해준다. const [interactionElement, setInteractionElement] = useState<HTMLElement | null>(null);

// 내부의 Canvas Render를 외부의 다른 Component들에 동기화 시키기 위한 Hook const { cornerstoneRenderData, updateCornerstoneRenderData, } = useInsightViewerSync();

// Annotation (사용자 Contour)를 다루기 위한 Hook const { contours, focusedContour, addContour, removeContour, focusContour, } = useUserContour();

return ( <InsightViewer width={width} height={height} invert={invert} flip={flip} pan={control === 'pan' && interactionElement} adjust={control === 'adjust' && interactionElement} zoom={wheel === 'zoom' && interactionElement} resetTime={resetTime} image={image} updateCornerstoneRenderData={updateCornerstoneRenderData}/> { // 사용자가 그린 Annotation을 보여준다 // contours가 있는 경우에만 출력 contours && contours.length > 0 && cornerstoneRenderData && } { // Annotation을 그리고, 지우게 해준다 // control === 'pen' 인 경우에만 출력 contours && cornerstoneRenderData && control === 'pen' && <UserContourDrawer width={width} height={height} contours={contours} draw={control === 'pen' && interactionElement} onFocus={focusContour} onAdd={contour => addContour(contour, 0)} onRemove={removeContour} cornerstoneRenderData={cornerstoneRenderData}/> } ); }

storiesOf('insight-viewer2', module) .addDecorator(withOptTheme) .addDecorator(withTestController({ width: [600, 400, 1000], height: [700, 400, 1000], control: ['pan', ['none', 'pen', 'pan', 'adjust']], wheel: ['zoom', ['none', 'zoom']], flip: false, invert: false, })) .add('', () => );

<h3>__stories__/UserContourViewerCanvasStyle.stories.tsx</h3>
```tsx
import { withOptTheme } from '@lunit/opt-theme';
import { storiesOf } from '@storybook/react';
import React, { useState } from 'react';
import { InsightViewer } from '../components/InsightViewer';
import { InsightViewerContainer } from '../components/InsightViewerContainer';
import { ProgressViewer } from '../components/ProgressViewer';
import { UserContourDrawer } from '../components/UserContourDrawer';
import { UserContourViewer } from '../components/UserContourViewer';
import { useInsightViewerSync } from '../hooks/useInsightViewerSync';
import { useUserContour } from '../hooks/useUserContour';
import { CornerstoneSingleImage } from '../image/CornerstoneSingleImage';
import { CornerstoneImage } from '../image/types';
import { installWADOImageLoader, unloadWADOImage } from '../installWADO';
import { useController, withTestController } from './decorators/withTestController';

installWADOImageLoader();

const resetTime: number = Date.now();
const image: CornerstoneImage = new CornerstoneSingleImage(`wadouri:samples/series/CT000010.dcm`, {unload: unloadWADOImage});

function Sample() {
  const {
    width,
    height,
    control,
    wheel,
    invert,
    flip,
  } = useController();
  
  const [interactionElement, setInteractionElement] = useState<HTMLElement | null>(null);
  
  const {
    cornerstoneRenderData,
    updateCornerstoneRenderData,
  } = useInsightViewerSync();
  
  const {
    contours,
    focusedContour,
    addContour,
    removeContour,
    focusContour,
  } = useUserContour();
  
  return (
    <InsightViewerContainer ref={setInteractionElement} width={width} height={height}>
      <InsightViewer width={width}
                     height={height}
                     invert={invert}
                     flip={flip}
                     pan={control === 'pan' && interactionElement}
                     adjust={control === 'adjust' && interactionElement}
                     zoom={wheel === 'zoom' && interactionElement}
                     resetTime={resetTime}
                     image={image}
                     updateCornerstoneRenderData={updateCornerstoneRenderData}/>
      {
        contours &&
        contours.length > 0 &&
        cornerstoneRenderData &&
        // Canvas Style을 변경할 수 있다
        <UserContourViewer width={width}
                           height={height}
                           contours={contours}
                           focusedContour={focusedContour}
                           cornerstoneRenderData={cornerstoneRenderData}
        
                           canvasStrokeLineWidth={10}
                           canvasStrokeStyle="blue"
                           canvasFillStyle="rgba(0, 0, 255, 0.3)"
                           canvasFontStyle="normal normal 600 40px proximanova"
                           canvasFocusedStrokeLineWidth={20}
                           canvasFocusedStrokeStyle="red"
                           canvasFocusedFillStyle="rgba(255, 0, 0, 0.3)"
                           canvasFocusedFontStyle="normal normal 600 50px proximanova"/>
      }
      {
        contours &&
        cornerstoneRenderData &&
        control === 'pen' &&
        // Canvas Style을 변경할 수 있다
        <UserContourDrawer width={width}
                           height={height}
                           contours={contours}
                           draw={control === 'pen' && interactionElement}
                           onFocus={focusContour}
                           onAdd={contour => addContour(contour, 0)}
                           onRemove={removeContour}
                           cornerstoneRenderData={cornerstoneRenderData}
        
                           canvasStokeLineWidght={8}
                           canvasStokeStyle="purple"
                           canvasFillStyle="rgba(255, 255, 255, 0.4)"/>
      }
      <ProgressViewer image={image}
                      width={width}
                      height={height}/>
    </InsightViewerContainer>
  );
}

storiesOf('insight-viewer2', module)
  .addDecorator(withOptTheme)
  .addDecorator(withTestController({
    width: [600, 400, 1000],
    height: [700, 400, 1000],
    control: ['pan', ['none', 'pen', 'pan', 'adjust']],
    wheel: ['zoom', ['none', 'zoom']],
    flip: false,
    invert: false,
  }))
  .add('<UserContourViewer canvasStokeStyle="{}">', () => <Sample/>);

__stories__/useResizeObserver.stories.tsx

```tsx import { InsightViewerContainer } from '@lunit/insight-viewer2'; import { withOptTheme } from '@lunit/opt-theme'; import { storiesOf } from '@storybook/react'; import React from 'react'; import useResizeObserver from 'use-resize-observer'; import { InsightViewer } from '../components/InsightViewer'; import { useInsightViewerSync } from '../hooks/useInsightViewerSync'; import { CornerstoneSingleImage } from '../image/CornerstoneSingleImage'; import { CornerstoneImage } from '../image/types'; import { installWADOImageLoader, unloadWADOImage } from '../installWADO';

installWADOImageLoader();

const resetTime: number = Date.now(); const image: CornerstoneImage = new CornerstoneSingleImage(wadouri:samples/series/CT000010.dcm, {unload: unloadWADOImage});

function Sample() { const { updateCornerstoneRenderData, } = useInsightViewerSync();

// 특정 Element의 width, height를 지속적으로 감지한다 // flex 등 layout으로 처리된

Element의 width, height를 useResizeObserver()로 받아서 // 로 넘길 수 있다 const [resizeRef, width, height] = useResizeObserver();

console.log('useResizeObserver.stories.tsx..Sample()', width, height);

return ( <div ref={resizeRef} style={{width: '50vw', height: '80vh'}}>

); }

storiesOf('insight-viewer2', module) .addDecorator(withOptTheme) .add('useResizeObserver', () => );

<!-- importend -->

## Tests

<!-- import __tests__/*.{ts,tsx} --title-tag h3 -->
<!-- importend -->

FAQs

Package last updated on 26 Aug 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc