export default function (image, storedPixelValue) {
  const patientStudyModule = cornerstone.metaData.get('patientStudyModule', image.imageId);
  const seriesModule = cornerstone.metaData.get('generalSeriesModule', image.imageId);

  if (!patientStudyModule || !seriesModule) {
    return;
  }

  const modality = seriesModule.modality;

    // Image must be PET
  if (modality !== 'PT') {
    return;
  }

  const modalityPixelValue = storedPixelValue * image.slope + image.intercept;

  const patientWeight = patientStudyModule.patientWeight; // In kg

  if (!patientWeight) {
    return;
  }

  const petSequenceModule = cornerstone.metaData.get('petIsotopeModule', image.imageId);

  if (!petSequenceModule) {
    return;
  }

  const radiopharmaceuticalInfo = petSequenceModule.radiopharmaceuticalInfo;
  const startTime = radiopharmaceuticalInfo.radiopharmaceuticalStartTime;
  const totalDose = radiopharmaceuticalInfo.radionuclideTotalDose;
  const halfLife = radiopharmaceuticalInfo.radionuclideHalfLife;
  const seriesAcquisitionTime = seriesModule.seriesTime;

  if (!startTime || !totalDose || !halfLife || !seriesAcquisitionTime) {
    return;
  }

  const acquisitionTimeInSeconds = fracToDec(seriesAcquisitionTime.fractionalSeconds || 0) + seriesAcquisitionTime.seconds + seriesAcquisitionTime.minutes * 60 + seriesAcquisitionTime.hours * 60 * 60;
  const injectionStartTimeInSeconds = fracToDec(startTime.fractionalSeconds) + startTime.seconds + startTime.minutes * 60 + startTime.hours * 60 * 60;
  const durationInSeconds = acquisitionTimeInSeconds - injectionStartTimeInSeconds;
  const correctedDose = totalDose * Math.exp(-durationInSeconds * Math.log(2) / halfLife);
  const suv = modalityPixelValue * patientWeight / correctedDose * 1000;

  return suv;
}
function getCompression(imageId) {
  const generalImageModule =
    cornerstone.metaData.get('generalImageModule', imageId) || {};
  const {
    lossyImageCompression,
    lossyImageCompressionRatio,
    lossyImageCompressionMethod
  } = generalImageModule;

  if (lossyImageCompression === '01' && lossyImageCompressionRatio !== '') {
    const compressionMethod = lossyImageCompressionMethod || 'Lossy: ';
    const compressionRatio = formatNumberPrecision(
      lossyImageCompressionRatio,
      2
    );
    return compressionMethod + compressionRatio + ' : 1';
  }

  return 'Lossless / Uncompressed';
}
Exemple #3
0
function getImageFrame (imageId) {
  const imagePixelModule = cornerstone.metaData.get('imagePixelModule', imageId);

  return {
    samplesPerPixel: imagePixelModule.samplesPerPixel,
    photometricInterpretation: imagePixelModule.photometricInterpretation,
    planarConfiguration: imagePixelModule.planarConfiguration,
    rows: imagePixelModule.rows,
    columns: imagePixelModule.columns,
    bitsAllocated: imagePixelModule.bitsAllocated,
    pixelRepresentation: imagePixelModule.pixelRepresentation, // 0 = unsigned,
    smallestPixelValue: imagePixelModule.smallestPixelValue,
    largestPixelValue: imagePixelModule.largestPixelValue,
    redPaletteColorLookupTableDescriptor: imagePixelModule.redPaletteColorLookupTableDescriptor,
    greenPaletteColorLookupTableDescriptor: imagePixelModule.greenPaletteColorLookupTableDescriptor,
    bluePaletteColorLookupTableDescriptor: imagePixelModule.bluePaletteColorLookupTableDescriptor,
    redPaletteColorLookupTableData: imagePixelModule.redPaletteColorLookupTableData,
    greenPaletteColorLookupTableData: imagePixelModule.greenPaletteColorLookupTableData,
    bluePaletteColorLookupTableData: imagePixelModule.bluePaletteColorLookupTableData,
    pixelData: undefined // populated later after decoding
  };
}
function onImageRendered (e, eventData) {
    // If we have no toolData for this element, return immediately as there is nothing to do
  const toolData = getToolState(e.currentTarget, toolType);

  if (!toolData) {
    return;
  }

  const image = eventData.image;
  const element = eventData.element;
  const lineWidth = toolStyle.getToolWidth();
  const config = ellipticalRoi.getConfiguration();
  const context = eventData.canvasContext.canvas.getContext('2d');
  const seriesModule = cornerstone.metaData.get('generalSeriesModule', image.imageId);
  let modality;

  if (seriesModule) {
    modality = seriesModule.modality;
  }

  context.setTransform(1, 0, 0, 1, 0, 0);

    // If we have tool data for this element - iterate over each set and draw it
  for (let i = 0; i < toolData.data.length; i++) {
    context.save();

    const data = toolData.data[i];

        // Apply any shadow settings defined in the tool configuration
    if (config && config.shadow) {
      context.shadowColor = config.shadowColor || '#000000';
      context.shadowOffsetX = config.shadowOffsetX || 1;
      context.shadowOffsetY = config.shadowOffsetY || 1;
    }

        // Check which color the rendered tool should be
    const color = toolColors.getColorIfActive(data.active);

        // Convert Image coordinates to Canvas coordinates given the element
    const handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
    const handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);

        // Retrieve the bounds of the ellipse (left, top, width, and height)
        // In Canvas coordinates
    const leftCanvas = Math.min(handleStartCanvas.x, handleEndCanvas.x);
    const topCanvas = Math.min(handleStartCanvas.y, handleEndCanvas.y);
    const widthCanvas = Math.abs(handleStartCanvas.x - handleEndCanvas.x);
    const heightCanvas = Math.abs(handleStartCanvas.y - handleEndCanvas.y);

        // Draw the ellipse on the canvas
    context.beginPath();
    context.strokeStyle = color;
    context.lineWidth = lineWidth;
    drawEllipse(context, leftCanvas, topCanvas, widthCanvas, heightCanvas);
    context.closePath();

        // If the tool configuration specifies to only draw the handles on hover / active,
        // Follow this logic
    if (config && config.drawHandlesOnHover) {
            // Draw the handles if the tool is active
      if (data.active === true) {
        drawHandles(context, eventData, data.handles, color);
      } else {
                // If the tool is inactive, draw the handles only if each specific handle is being
                // Hovered over
        const handleOptions = {
          drawHandlesIfActive: true
        };

        drawHandles(context, eventData, data.handles, color, handleOptions);
      }
    } else {
            // If the tool has no configuration settings, always draw the handles
      drawHandles(context, eventData, data.handles, color);
    }

        // Define variables for the area and mean/standard deviation
    let area,
      meanStdDev,
      meanStdDevSUV;

        // Perform a check to see if the tool has been invalidated. This is to prevent
        // Unnecessary re-calculation of the area, mean, and standard deviation if the
        // Image is re-rendered but the tool has not moved (e.g. during a zoom)
    if (data.invalidated === false) {
            // If the data is not invalidated, retrieve it from the toolData
      meanStdDev = data.meanStdDev;
      meanStdDevSUV = data.meanStdDevSUV;
      area = data.area;
    } else {
            // If the data has been invalidated, we need to calculate it again

            // Retrieve the bounds of the ellipse in image coordinates
      const ellipse = {
        left: Math.round(Math.min(data.handles.start.x, data.handles.end.x)),
        top: Math.round(Math.min(data.handles.start.y, data.handles.end.y)),
        width: Math.round(Math.abs(data.handles.start.x - data.handles.end.x)),
        height: Math.round(Math.abs(data.handles.start.y - data.handles.end.y))
      };

            // First, make sure this is not a color image, since no mean / standard
            // Deviation will be calculated for color images.
      if (!image.color) {
                // Retrieve the array of pixels that the ellipse bounds cover
        const pixels = cornerstone.getPixels(element, ellipse.left, ellipse.top, ellipse.width, ellipse.height);

                // Calculate the mean & standard deviation from the pixels and the ellipse details
        meanStdDev = calculateEllipseStatistics(pixels, ellipse);

        if (modality === 'PT') {
                    // If the image is from a PET scan, use the DICOM tags to
                    // Calculate the SUV from the mean and standard deviation.

                    // Note that because we are using modality pixel values from getPixels, and
                    // The calculateSUV routine also rescales to modality pixel values, we are first
                    // Returning the values to storedPixel values before calcuating SUV with them.
                    // TODO: Clean this up? Should we add an option to not scale in calculateSUV?
          meanStdDevSUV = {
            mean: calculateSUV(image, (meanStdDev.mean - image.intercept) / image.slope),
            stdDev: calculateSUV(image, (meanStdDev.stdDev - image.intercept) / image.slope)
          };
        }

                // If the mean and standard deviation values are sane, store them for later retrieval
        if (meanStdDev && !isNaN(meanStdDev.mean)) {
          data.meanStdDev = meanStdDev;
          data.meanStdDevSUV = meanStdDevSUV;
        }
      }

            // Retrieve the pixel spacing values, and if they are not
            // Real non-zero values, set them to 1
      const columnPixelSpacing = image.columnPixelSpacing || 1;
      const rowPixelSpacing = image.rowPixelSpacing || 1;

            // Calculate the image area from the ellipse dimensions and pixel spacing
      area = Math.PI * (ellipse.width * columnPixelSpacing / 2) * (ellipse.height * rowPixelSpacing / 2);

            // If the area value is sane, store it for later retrieval
      if (!isNaN(area)) {
        data.area = area;
      }

            // Set the invalidated flag to false so that this data won't automatically be recalculated
      data.invalidated = false;
    }

        // Define an array to store the rows of text for the textbox
    const textLines = [];

        // If the mean and standard deviation values are present, display them
    if (meanStdDev && meanStdDev.mean !== undefined) {
            // If the modality is CT, add HU to denote Hounsfield Units
      let moSuffix = '';

      if (modality === 'CT') {
        moSuffix = ' HU';
      }

            // Create a line of text to display the mean and any units that were specified (i.e. HU)
      let meanText = `Mean: ${numberWithCommas(meanStdDev.mean.toFixed(2))}${moSuffix}`;
            // Create a line of text to display the standard deviation and any units that were specified (i.e. HU)
      let stdDevText = `StdDev: ${numberWithCommas(meanStdDev.stdDev.toFixed(2))}${moSuffix}`;

            // If this image has SUV values to display, concatenate them to the text line
      if (meanStdDevSUV && meanStdDevSUV.mean !== undefined) {
        const SUVtext = ' SUV: ';

        meanText += SUVtext + numberWithCommas(meanStdDevSUV.mean.toFixed(2));
        stdDevText += SUVtext + numberWithCommas(meanStdDevSUV.stdDev.toFixed(2));
      }

            // Add these text lines to the array to be displayed in the textbox
      textLines.push(meanText);
      textLines.push(stdDevText);
    }

        // If the area is a sane value, display it
    if (area) {
            // Determine the area suffix based on the pixel spacing in the image.
            // If pixel spacing is present, use millimeters. Otherwise, use pixels.
            // This uses Char code 178 for a superscript 2
      let suffix = ` mm${String.fromCharCode(178)}`;

      if (!image.rowPixelSpacing || !image.columnPixelSpacing) {
        suffix = ` pixels${String.fromCharCode(178)}`;
      }

            // Create a line of text to display the area and its units
      const areaText = `Area: ${numberWithCommas(area.toFixed(2))}${suffix}`;

            // Add this text line to the array to be displayed in the textbox
      textLines.push(areaText);
    }

        // If the textbox has not been moved by the user, it should be displayed on the right-most
        // Side of the tool.
    if (!data.handles.textBox.hasMoved) {
            // Find the rightmost side of the ellipse at its vertical center, and place the textbox here
            // Note that this calculates it in image coordinates
      data.handles.textBox.x = Math.max(data.handles.start.x, data.handles.end.x);
      data.handles.textBox.y = (data.handles.start.y + data.handles.end.y) / 2;
    }

        // Convert the textbox Image coordinates into Canvas coordinates
    const textCoords = cornerstone.pixelToCanvas(element, data.handles.textBox);

        // Set options for the textbox drawing function
    const options = {
      centering: {
        x: false,
        y: true
      }
    };

        // Draw the textbox and retrieves it's bounding box for mouse-dragging and highlighting
    const boundingBox = drawTextBox(context, textLines, textCoords.x,
            textCoords.y, color, options);

        // Store the bounding box data in the handle for mouse-dragging and highlighting
    data.handles.textBox.boundingBox = boundingBox;

        // If the textbox has moved, we would like to draw a line linking it with the tool
        // This section decides where to draw this line to on the Ellipse based on the location
        // Of the textbox relative to the ellipse.
    if (data.handles.textBox.hasMoved) {
            // Draw dashed link line between tool and text

            // The initial link position is at the center of the
            // Textbox.
      const link = {
        start: {},
        end: {
          x: textCoords.x,
          y: textCoords.y
        }
      };

            // First we calculate the ellipse points (top, left, right, and bottom)
      const ellipsePoints = [{
                // Top middle point of ellipse
        x: leftCanvas + widthCanvas / 2,
        y: topCanvas
      }, {
                // Left middle point of ellipse
        x: leftCanvas,
        y: topCanvas + heightCanvas / 2
      }, {
                // Bottom middle point of ellipse
        x: leftCanvas + widthCanvas / 2,
        y: topCanvas + heightCanvas
      }, {
                // Right middle point of ellipse
        x: leftCanvas + widthCanvas,
        y: topCanvas + heightCanvas / 2
      }];

            // We obtain the link starting point by finding the closest point on the ellipse to the
            // Center of the textbox
      link.start = cornerstoneMath.point.findClosestPoint(ellipsePoints, link.end);

            // Next we calculate the corners of the textbox bounding box
      const boundingBoxPoints = [{
                // Top middle point of bounding box
        x: boundingBox.left + boundingBox.width / 2,
        y: boundingBox.top
      }, {
                // Left middle point of bounding box
        x: boundingBox.left,
        y: boundingBox.top + boundingBox.height / 2
      }, {
                // Bottom middle point of bounding box
        x: boundingBox.left + boundingBox.width / 2,
        y: boundingBox.top + boundingBox.height
      }, {
                // Right middle point of bounding box
        x: boundingBox.left + boundingBox.width,
        y: boundingBox.top + boundingBox.height / 2
      }];

            // Now we recalculate the link endpoint by identifying which corner of the bounding box
            // Is closest to the start point we just calculated.
      link.end = cornerstoneMath.point.findClosestPoint(boundingBoxPoints, link.start);

            // Finally we draw the dashed linking line
      context.beginPath();
      context.strokeStyle = color;
      context.lineWidth = lineWidth;
      context.setLineDash([2, 3]);
      context.moveTo(link.start.x, link.start.y);
      context.lineTo(link.end.x, link.end.y);
      context.stroke();
    }

    context.restore();
  }
}
function minimalStrategy (eventData) {
  const element = eventData.element;
  const enabledElement = cornerstone.getEnabledElement(element);
  const image = enabledElement.image;

  const context = enabledElement.canvas.getContext('2d');

  context.setTransform(1, 0, 0, 1, 0, 0);

  const color = toolColors.getActiveColor();
  const font = textStyle.getFont();
  const config = dragProbe.getConfiguration();

  context.save();

  if (config && config.shadow) {
    context.shadowColor = config.shadowColor || '#000000';
    context.shadowOffsetX = config.shadowOffsetX || 1;
    context.shadowOffsetY = config.shadowOffsetY || 1;
  }

  const seriesModule = cornerstone.metaData.get('generalSeriesModule', image.imageId);
  let modality;

  if (seriesModule) {
    modality = seriesModule.modality;
  }

  let toolCoords;

  if (eventData.isTouchEvent === true) {
    toolCoords = cornerstone.pageToPixel(element, eventData.currentPoints.page.x,
            eventData.currentPoints.page.y - textStyle.getFontSize() * 4);
  } else {
    toolCoords = cornerstone.pageToPixel(element, eventData.currentPoints.page.x,
            eventData.currentPoints.page.y - textStyle.getFontSize() / 2);
  }

  let storedPixels;
  let text = '';

  if (toolCoords.x < 0 || toolCoords.y < 0 ||
        toolCoords.x >= image.columns || toolCoords.y >= image.rows) {
    return;
  }

  if (image.color) {
    storedPixels = getRGBPixels(element, toolCoords.x, toolCoords.y, 1, 1);
    text = `R: ${storedPixels[0]} G: ${storedPixels[1]} B: ${storedPixels[2]}`;
  } else {
    storedPixels = cornerstone.getStoredPixels(element, toolCoords.x, toolCoords.y, 1, 1);
    const sp = storedPixels[0];
    const mo = sp * eventData.image.slope + eventData.image.intercept;

    const modalityPixelValueText = parseFloat(mo.toFixed(2));

    if (modality === 'CT') {
      text += `HU: ${modalityPixelValueText}`;
    } else if (modality === 'PT') {
      text += modalityPixelValueText;
      const suv = calculateSUV(eventData.image, sp);

      if (suv) {
        text += ` SUV: ${parseFloat(suv.toFixed(2))}`;
      }
    } else {
      text += modalityPixelValueText;
    }
  }

    // Prepare text
  const textCoords = cornerstone.pixelToCanvas(element, toolCoords);

  context.font = font;
  context.fillStyle = color;

    // Translate the x/y away from the cursor
  let translation;
  const handleRadius = 6;
  const width = context.measureText(text).width;

  if (eventData.isTouchEvent === true) {
    translation = {
      x: -width / 2 - 5,
      y: -textStyle.getFontSize() - 10 - 2 * handleRadius
    };
  } else {
    translation = {
      x: 12,
      y: -(textStyle.getFontSize() + 10) / 2
    };
  }

  context.beginPath();
  context.strokeStyle = color;
  context.arc(textCoords.x, textCoords.y, handleRadius, 0, 2 * Math.PI);
  context.stroke();

  drawTextBox(context, text, textCoords.x + translation.x, textCoords.y + translation.y, color);
  context.restore();
}
  render() {
    const imageId = this.props.imageId;
    if (!imageId) {
      return null;
    }

    const zoom = this.props.viewport.scale * 100;
    const seriesMetadata =
      cornerstone.metaData.get('generalSeriesModule', imageId) || {};
    const imagePlaneModule =
      cornerstone.metaData.get('imagePlaneModule', imageId) || {};
    const { rows, columns, sliceThickness, sliceLocation } = imagePlaneModule;
    const { seriesNumber, seriesDescription } = seriesMetadata;

    const generalStudyModule =
      cornerstone.metaData.get('generalStudyModule', imageId) || {};
    const { studyDate, studyTime, studyDescription } = generalStudyModule;

    const patientModule =
      cornerstone.metaData.get('patientModule', imageId) || {};
    const { patientId, patientName } = patientModule;

    const generalImageModule =
      cornerstone.metaData.get('generalImageModule', imageId) || {};
    const { instanceNumber } = generalImageModule;

    const cineModule = cornerstone.metaData.get('cineModule', imageId) || {};
    const { frameTime } = cineModule;

    const frameRate = formatNumberPrecision(1000 / frameTime, 1);
    const compression = getCompression(imageId);
    const windowWidth = this.props.viewport.voi.windowWidth || 0;
    const windowCenter = this.props.viewport.voi.windowCenter || 0;
    const wwwc = `W: ${windowWidth.toFixed(0)} L: ${windowCenter.toFixed(0)}`;

    const { imageIds } = this.props.stack;
    const imageIndex = imageIds.indexOf(this.props.imageId) + 1;
    const numImages = imageIds.length;
    const imageDimensions = `${columns} x ${rows}`;

    const normal = (
      <React.Fragment>
        <div className="top-left overlay-element">
          <div>{formatPN(patientName)}</div>
          <div>{patientId}</div>
        </div>
        <div className="top-right overlay-element">
          <div>{studyDescription}</div>
          <div>
            {formatDA(studyDate)} {formatTM(studyTime)}
          </div>
        </div>
        <div className="bottom-right overlay-element">
          <div>Zoom: {formatNumberPrecision(zoom, 0)}%</div>
          <div>{wwwc}</div>
          <div className="compressionIndicator">{compression}</div>
        </div>
        <div className="bottom-left overlay-element">
          <div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
          <div>
            {numImages > 1
              ? `Img: ${instanceNumber} ${imageIndex}/${numImages}`
              : ''}
          </div>
          <div>
            {frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}
            <div>{imageDimensions}</div>
            <div>
              {isValidNumber(sliceLocation)
                ? `Loc: ${formatNumberPrecision(sliceLocation, 2)} mm `
                : ''}
              {sliceThickness
                ? `Thick: ${formatNumberPrecision(sliceThickness, 2)} mm`
                : ''}
            </div>
            <div>{seriesDescription}</div>
          </div>
        </div>
      </React.Fragment>
    );

    const rightOnly = (
      <React.Fragment>
        <div className="top-right overlay-element">
          <div>{formatPN(patientName)}</div>
          <div>{patientId}</div>
          <div>{studyDescription}</div>
          <div>
            {formatDA(studyDate)} {formatTM(studyTime)}
          </div>
        </div>
        <div className="bottom-right overlay-element">
          <div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
          <div>
            {numImages > 1
              ? `Img: ${instanceNumber} ${imageIndex}/${numImages}`
              : ''}
          </div>
          <div>
            {frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}
          </div>
          <div>{imageDimensions}</div>
          <div>{seriesDescription}</div>
          <div>Zoom: {formatNumberPrecision(zoom, 0)}%</div>
          <div className="compressionIndicator">{compression}</div>
          <div>{wwwc}</div>
        </div>
      </React.Fragment>
    );

    const leftOnly = (
      <React.Fragment>
        <div className="top-left overlay-element">
          <div>{formatPN(patientName)}</div>
          <div>{patientId}</div>
          <div>{studyDescription}</div>
          <div>
            {formatDA(studyDate)} {formatTM(studyTime)}
          </div>
        </div>
        <div className="bottom-left overlay-element">
          <div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
          <div>
            {numImages > 1
              ? `Img: ${instanceNumber} ${imageIndex}/${numImages}`
              : ''}
          </div>
          <div>
            {frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}
          </div>
          <div>{imageDimensions}</div>
          <div>{seriesDescription}</div>
          <div>Zoom: {formatNumberPrecision(zoom, 0)}%</div>
          <div className="compressionIndicator">{compression}</div>
          <div>{wwwc}</div>
        </div>
      </React.Fragment>
    );

    return <div className="ViewportOverlay">{normal}</div>;
  }
// Renders the active reference line
export default function (context, eventData, targetElement, referenceElement) {
  const targetImage = cornerstone.getEnabledElement(targetElement).image;
  const referenceImage = cornerstone.getEnabledElement(referenceElement).image;

    // Make sure the images are actually loaded for the target and reference
  if (!targetImage || !referenceImage) {
    return;
  }

  const targetImagePlane = cornerstone.metaData.get('imagePlane', targetImage.imageId);
  const referenceImagePlane = cornerstone.metaData.get('imagePlane', referenceImage.imageId);

    // Make sure the target and reference actually have image plane metadata
  if (!targetImagePlane ||
        !referenceImagePlane ||
        !targetImagePlane.rowCosines ||
        !targetImagePlane.columnCosines ||
        !targetImagePlane.imagePositionPatient ||
        !referenceImagePlane.rowCosines ||
        !referenceImagePlane.columnCosines ||
        !referenceImagePlane.imagePositionPatient) {
    return;
  }

    // The image planes must be in the same frame of reference
  if (targetImagePlane.frameOfReferenceUID !== referenceImagePlane.frameOfReferenceUID) {
    return;
  }

    // The image plane normals must be > 30 degrees apart
  const targetNormal = targetImagePlane.rowCosines.clone().cross(targetImagePlane.columnCosines);
  const referenceNormal = referenceImagePlane.rowCosines.clone().cross(referenceImagePlane.columnCosines);
  let angleInRadians = targetNormal.angleTo(referenceNormal);

  angleInRadians = Math.abs(angleInRadians);
  if (angleInRadians < 0.5) { // 0.5 radians = ~30 degrees
    return;
  }

  const referenceLine = calculateReferenceLine(targetImagePlane, referenceImagePlane);

  if (!referenceLine) {
    return;
  }

  const refLineStartCanvas = cornerstone.pixelToCanvas(eventData.element, referenceLine.start);
  const refLineEndCanvas = cornerstone.pixelToCanvas(eventData.element, referenceLine.end);

  const color = toolColors.getActiveColor();
  const lineWidth = toolStyle.getToolWidth();

    // Draw the referenceLines
  context.setTransform(1, 0, 0, 1, 0, 0);

  context.save();
  context.beginPath();
  context.strokeStyle = color;
  context.lineWidth = lineWidth;
  context.moveTo(refLineStartCanvas.x, refLineStartCanvas.y);
  context.lineTo(refLineEndCanvas.x, refLineEndCanvas.y);
  context.stroke();
  context.restore();
}
Exemple #8
0
      sopClassUID: dataSet.string('x00080016'),
      sopInstanceUID: dataSet.string('x00080018')
    };
  }

  if (type === 'petIsotopeModule') {
    const radiopharmaceuticalInfo = dataSet.elements.x00540016;

    if (radiopharmaceuticalInfo === undefined) {
      return;
    }

    const firstRadiopharmaceuticalInfoDataSet = radiopharmaceuticalInfo.items[0].dataSet;


    return {
      radiopharmaceuticalInfo: {
        radiopharmaceuticalStartTime: dicomParser.parseTM(firstRadiopharmaceuticalInfoDataSet.string('x00181072') || ''),
        radionuclideTotalDose: firstRadiopharmaceuticalInfoDataSet.floatString('x00181074'),
        radionuclideHalfLife: firstRadiopharmaceuticalInfoDataSet.floatString('x00181075')
      }
    };
  }

}

// register our metadata provider
cornerstone.metaData.addProvider(metaDataProvider);

export default metaDataProvider;