dicom

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2018 License: MIT Imports: 17 Imported by: 11

README

DICOM parser in Go

Build Status GoDoc Reference

This is a (hard-ish) fork of go-dicom--a golang DICOM image parsing library. A command line tool to parse imagery and data out of DICOM files is also included (dicomutil). We have been working on this package with the goal of building a full-featured and high-performance dicom parser with new features and improvements. So far improvements include:

  • parsing and extracting multi-frame DICOM imagery (both encapsulated and native pixel data)
  • exposing a Parser golang interface to make mock-based testing easier for clients
  • Channel-based streaming of frames to a client as they are parsed out of the dicom

We're open to suggestions and comments -- open an issue if you have any.

Usage

To use this in your golang project, simply import our pacakge github.com/gradienthealth/dicom and then you can use our Parser for your parsing needs:

p, err := dicom.NewParserFromFile("myfile.dcm", nil)
opts := dicom.ParseOptions{DropPixelData: true}

element := p.ParseNext(opts) // parse and return the next dicom element
// or
dataset, err := p.Parse(opts) // parse whole dicom

More details about the package can be found in the godoc

CLI Tool

A CLI tool that uses this package to parse imagery and metadata out of DICOMs is provided in the dicomutil package.

Usage
dicomutil --extract-images myfile.dcm

Note: for some dicoms (with native pixel data) no automatic intensity scaling is applied yet (this is coming). You can apply this in your image viewer if needed.

Docker build

To build the tool for all platforms (Mac, Windows, Linux) from source using docker, execute the following in the cloned repo:

docker build . -t godicom
docker run -it -v $PWD/build:/go/src/github.com/gradienthealth/dicom/build godicom make release

You can then use the binaries that will show up in the build folder in your current working directory

Build manually

To build manually, ensure you have make, golang, and dep installed on your machine. Clone (or go get) this repo into your gopath then:

make

Acknowledgements

Documentation

Index

Constants

View Source
const (
	InvalidYear  = -1
	InvalidMonth = -1
	InvalidDay   = -1
)
View Source
const GoDICOMImplementationClassUIDPrefix = "1.2.826.0.1.3680043.9.7133"

GoDICOMImplementationClassUIDPrefix defines the UID prefix for dicom. Provided by https://www.medicalconnections.co.uk/Free_UID

View Source
const GoDICOMImplementationVersionName = "GODICOM_1_1"

Variables

View Source
var GoDICOMImplementationClassUID = GoDICOMImplementationClassUIDPrefix + ".1.1"

Functions

func WriteDataSet

func WriteDataSet(out io.Writer, ds *DataSet) error

WriteDataSet writes the dataset into the stream in DICOM file format, complete with the magic header and metadata elements.

The transfer syntax (byte order, etc) of the file is determined by the TransferSyntax element in "ds". If ds is missing that or a few other essential elements, this function returns an error.

ds := ... read or create dicom.Dataset ...
out, err := os.Create("test.dcm")
err := dicom.Write(out, ds)

func WriteDataSetToFile

func WriteDataSetToFile(path string, ds *DataSet) error

WriteDataSetToFile writes "ds" to the given file. If the file already exists, existing contents are clobbered. Else, the file is newly created.

func WriteElement

func WriteElement(e *dicomio.Encoder, elem *Element)

WriteElement encodes one data element. Errors are reported through e.Error() and/or E.Finish().

REQUIRES: Each value in values[] must match the VR of the tag. E.g., if tag is for UL, then each value must be uint32.

func WriteFileHeader

func WriteFileHeader(e *dicomio.Encoder, metaElems []*Element)

WriteFileHeader produces a DICOM file header. metaElems[] is be a list of elements to be embedded in the header part. Every element in metaElems[] must have Tag.Group==2. It must contain at least the following three elements: TagTransferSyntaxUID, TagMediaStorageSOPClassUID, TagMediaStorageSOPInstanceUID. The list may contain other meta elements as long as their Tag.Group==2; they are added to the header.

Errors are reported via e.Error().

Consult the following page for the DICOM file header format.

http://dicom.nema.org/dicom/2013/output/chtml/part10/chapter_7.html

Types

type DataSet

type DataSet struct {
	// Elements in the file, in order of appearance.
	//
	// Note: unlike pydicom, Elements also contains meta elements (those
	// with Tag.Group==2).
	Elements []*Element
}

DataSet represents contents of one DICOM file.

func (*DataSet) FindElementByName

func (f *DataSet) FindElementByName(name string) (*Element, error)

FindElementByName finds an element from the dataset given the element name, such as "PatientName".

func (*DataSet) FindElementByTag

func (f *DataSet) FindElementByTag(tag dicomtag.Tag) (*Element, error)

FindElementByTag finds an element from the dataset given its tag, such as Tag{0x0010, 0x0010}.

type DateInfo

type DateInfo struct {
	// Input string.
	Str string
	// Results of parsing Str
	Year  int // Year (CE), in range [0,9999]. E.g., 2015
	Month int // Month of year, in range [1,12].
	Day   int // Day of month, in range [1,31].
}

DateInfo is a result of parsing a date string.

func ParseDate

func ParseDate(s string) (startDate, endDate DateInfo, err error)

ParseDate parses a date string or date-range string as defined for the VR type "DA". See https://www.medicalconnections.co.uk/kb/Dicom_Query_DateTime_range.

If "s" is for a point in time, startDate will show that point, and endDate will be {Year:-1,Month:-1,Day:-1}. Is "s" is for a range of dates, [startDate, endDate] stores the range (note: both ends are closed, even though the DICOM spec isn't clear about it.).

func (DateInfo) String

func (d DateInfo) String() string

type DirectoryRecord

type DirectoryRecord struct {
	Path string
}

DirectoryRecord contains info about one DICOM file mentioned in DICOMDIR.

func ParseDICOMDIR

func ParseDICOMDIR(in io.Reader) (recs []DirectoryRecord, err error)

ParseDICOMDIR parses contents of a "DICOMDIR" stored in "in".

http://dicom.nema.org/medical/Dicom/2016b/output/chtml/part03/sect_F.2.2.2.html

type Element

type Element struct {
	// Tag is a pair of <group, element>. See tags.go for possible values.
	Tag dicomtag.Tag

	// List of values in the element. Their types depends on value
	// representation (VR) of the Tag; Cf. tag.go.
	//
	// If Tag==TagPixelData, len(Value)==1, and Value[0] is PixelDataInfo.
	// Else if Tag==TagItem, each Value[i] is a *Element.
	//    a value's Tag can be any (including TagItem, which represents a nested Item)
	// Else if VR=="SQ", Value[i] is a *Element, with Tag=TagItem.
	// Else if VR=="OW", "OB", then len(Value)==1, and Value[0] is []byte.
	// Else if VR=="LT", or "UT", then len(Value)==1, and Value[0] is string
	// Else if VR=="DA", then len(Value)==1, and Value[0] is string. Use ParseDate() to parse the date string.
	// Else if VR=="US", Value[] is a list of uint16s
	// Else if VR=="UL", Value[] is a list of uint32s
	// Else if VR=="SS", Value[] is a list of int16s
	// Else if VR=="SL", Value[] is a list of int32s
	// Else if VR=="FL", Value[] is a list of float32s
	// Else if VR=="FD", Value[] is a list of float64s
	// Else if VR=="AT", Value[] is a list of Tag's.
	// Else, Value[] is a list of strings.
	//
	// Note: Use GetVRKind() to map VR string to the go representation of
	// VR.
	Value []interface{} // Value Multiplicity PS 3.5 6.4

	// VR defines the encoding of Value[] in two-letter alphabets, e.g.,
	// "AE", "UL". See P3.5 6.2. This field MUST be set.
	//
	// dicom.ReadElement() will fill this field with the VR of the tag,
	// either read from input stream (for explicit repl), or from the dicom
	// tag table (for implicit decl). This field need not be set in
	// WriteElement().
	//
	// Note: In a conformant DICOM file, the VR value of an element is
	// determined by its Tag, so this field is redundant.  This field is
	// still required because a non-conformant file with with explicitVR
	// encoding may have an element with VR that's different from the
	// standard's. In such case, this library honors the VR value found in
	// the file, and this field stores the VR used for parsing Values[].
	VR string

	// UndefinedLength is true if, in the DICOM file, the element is encoded
	// as having undefined length, and is delimited by end-sequence or
	// end-item element.  This flag is meaningful only if VR=="SQ" or
	// VR=="NA". Feel free to ignore this field if you don't understand what
	// this means.  It's one of the pointless complexities in the DICOM
	// standard.
	UndefinedLength bool
}

Element represents a single DICOM element. Use NewElement() to create a element denovo. Avoid creating a struct manually, because setting the VR field is a bit tricky.

func FindElementByName

func FindElementByName(elems []*Element, name string) (*Element, error)

FindElementByName finds an element with the given Element.Name in "elems" If not found, returns an error.

func FindElementByTag

func FindElementByTag(elems []*Element, tag dicomtag.Tag) (*Element, error)

FindElementByTag finds an element with the given Element.Tag in "elems" If not found, returns an error.

func MustNewElement

func MustNewElement(tag dicomtag.Tag, values ...interface{}) *Element

MustNewElement is similar to NewElement, but it crashes the process on any error.

func NewElement

func NewElement(tag dicomtag.Tag, values ...interface{}) (*Element, error)

NewElement creates a new Element with the given tag and values. The type of each each value must match the VR (value representation) of the tag (see tag_definition.go).

func Query

func Query(ds *DataSet, f *Element) (match bool, matchedElem *Element, err error)

Query checks if the dataset matches a QR condition "f". If so, it returns the <true, matched element, nil>. If "f" asks for a universal match (i.e., empty query value), and the element for f.Tag doesn't exist, the function returns <true, nil, nil>. If "f" is malformed, the function returns <false, nil, error reason>.

func (*Element) GetString

func (e *Element) GetString() (string, error)

GetString gets a string value from an element. It returns an error if the element contains zero or >1 values, or the value is not a string.

func (*Element) GetStrings

func (e *Element) GetStrings() ([]string, error)

GetStrings returns the list of strings stored in the elment. Returns an error if the VR of e.Tag is not a string.

func (*Element) GetUInt16

func (e *Element) GetUInt16() (uint16, error)

GetUInt16 gets a uint16 value from an element. It returns an error if the element contains zero or >1 values, or the value is not a uint16.

func (*Element) GetUInt32

func (e *Element) GetUInt32() (uint32, error)

GetUInt32 gets a uint32 value from an element. It returns an error if the element contains zero or >1 values, or the value is not a uint32.

func (*Element) GetUint16s

func (e *Element) GetUint16s() ([]uint16, error)

GetUint16s returns the list of uint16 values stored in the elment. Returns an error if the VR of e.Tag is not a uint16.

func (*Element) GetUint32s

func (e *Element) GetUint32s() ([]uint32, error)

GetUint32s returns the list of uint32 values stored in the elment. Returns an error if the VR of e.Tag is not a uint32.

func (*Element) MustGetString

func (e *Element) MustGetString() string

MustGetString is similar to GetString(), but panics on error.

TODO(saito): Add other variants of MustGet<type>.

func (*Element) MustGetStrings

func (e *Element) MustGetStrings() []string

MustGetStrings is similar to GetStrings, but crashes the process on error.

func (*Element) MustGetUInt16

func (e *Element) MustGetUInt16() uint16

MustGetUInt16 is similar to GetUInt16, but panics on error.

func (*Element) MustGetUInt32

func (e *Element) MustGetUInt32() uint32

MustGetUInt32 is similar to GetUInt32, but panics on error.

func (*Element) MustGetUint16s

func (e *Element) MustGetUint16s() []uint16

MustGetUint16s is similar to GetUint16s, but crashes the process on error.

func (*Element) MustGetUint32s

func (e *Element) MustGetUint32s() []uint32

MustGetUint32s is similar to GetUint32s, but crashes the process on error.

func (*Element) String

func (e *Element) String() string

Stringer

type EncapsulatedFrame

type EncapsulatedFrame struct {
	// Data is a collection of bytes representing a JPEG encoded image frame
	Data []byte
}

EncapsulatedFrame represents an encapsulated image frame

type Frame

type Frame struct {
	IsEncapsulated   bool
	EncapsulatedData EncapsulatedFrame
	NativeData       NativeFrame
}

Frame wraps a single encapsulated or native image frame

type NativeFrame

type NativeFrame struct {
	// Data is a slice of pixels, where each pixel can have multiple values
	Data          [][]int
	Rows          int
	Cols          int
	BitsPerSample int
}

NativeFrame represents a native image frame

type ParseOptions

type ParseOptions struct {
	// DropPixelData will cause the parser to skip the PixelData element
	// (bulk images) in ReadDataSet.
	DropPixelData bool

	// ReturnTags is a whitelist of tags to return.
	ReturnTags []dicomtag.Tag

	// StopAtag defines a tag at which when read (or a tag with a greater
	// value than it is read), the program will stop parsing the dicom file.
	StopAtTag *dicomtag.Tag
}

ParseOptions defines how DataSets and Elements are parsed.

type Parser

type Parser interface {
	// Parse DICOM data
	Parse(options ParseOptions) (*DataSet, error)
	// ParseNext reads and parses the next element
	ParseNext(options ParseOptions) *Element
	// DecoderError fetches an error (if exists) from the dicomio.Decoder
	DecoderError() error // This should go away as we continue refactors
	// Finish should be called after manually parsing elements using ParseNext (instead of Parse)
	Finish() error // This should maybe go away as we continue refactors
}

Parser represents an entity that can read and parse DICOMs

func NewParser

func NewParser(in io.Reader, bytesToRead int64, frameChannel chan *Frame) (Parser, error)

NewParser initializes and returns a new Parser

func NewParserFromBytes

func NewParserFromBytes(data []byte, frameChannel chan *Frame) (Parser, error)

NewParserFromBytes initializes and returns a new Parser from []byte

func NewParserFromFile

func NewParserFromFile(path string, frameChannel chan *Frame) (Parser, error)

NewParserFromFile initializes and returns a new dicom Parser from a file path

type PixelDataInfo

type PixelDataInfo struct {
	Offsets        []uint32 // BasicOffsetTable
	IsEncapsulated bool     // is the data encapsulated/jpeg encoded?
	Frames         []Frame  // Frames
}

PixelDataInfo is the Element.Value payload for PixelData element.

func (PixelDataInfo) String

func (data PixelDataInfo) String() string

Directories

Path Synopsis
Package dicomio provides utility functions for encoding and decoding low-level DICOM data types, such as integers and strings.
Package dicomio provides utility functions for encoding and decoding low-level DICOM data types, such as integers and strings.
Package dicomlog performs logging for go-dicom or go-netdicom.
Package dicomlog performs logging for go-dicom or go-netdicom.
Package dicomtag enumerates element tags defined in the DICOM standard.
Package dicomtag enumerates element tags defined in the DICOM standard.
Package dicomuid defines standard UIDs, as defined in P3.6.
Package dicomuid defines standard UIDs, as defined in P3.6.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL