简体   繁体   English

如何为DICOM文件生成SOPInstance UID?

[英]How to generate SOPInstance UID for DICOM file?

I am developing a system which will be able to create structured report for PACS. 我正在开发一个能够为PACS创建结构化报告的系统。

Obviously in order to create a DICOM instance (file containing Report data), I need three UIDs for Study, Series and Instance. 显然,为了创建一个DICOM实例(包含Report数据的文件),我需要三个UID用于Study,Series和Instance。 StudyUID and SeriesUID must be the same as that of study and series that report is created for. StudyUID和SeriesUID必须与为其创建的研究和系列相同。 But for SOPInstanceUID, I need to generate new UID. 但对于SOPInstanceUID,我需要生成新的UID。

I have seen getNewSOPInstanceUID method in Pixelmed documentation, but I am not familiar with the Pixelmed source. 我在Pixelmed文档中看到了getNewSOPInstanceUID方法,但我不熟悉Pixelmed源代码。 I need an algorithm or Python source. 我需要一个算法或Python源。

There are 2 ways in DICOM to create UIDs. DICOM中有两种方法可以创建UID。 One based on a registered UID root and one based on a UUID. 一个基于已注册的UID根,另一个基于UUID。 The later method was added to the DICOM standard with CP-1156 in 2012. UIDs for things like Study UID, Series UID, SOP Instance UID can be created by converting a UUID to a DICOM UID. 后一种方法在2012年通过CP-1156添加到DICOM标准中。可以通过将UUID转换为DICOM UID来创建诸如Study UID,Series UID,SOP Instance UID之类的UID。

Most programming languages have build in support to create a UUID. 大多数编程语言都支持创建UUID。 The sample code code below creates a valid DICOM UID in C# based on a GUID value. 下面的示例代码代码根据GUID值在C#中创建有效的DICOM UID。

public static string GuidToUidStringUsingStringAndParse(Guid value)
{
    var guidBytes = string.Format("0{0:N}", value);
    var bigInteger = BigInteger.Parse(guidBytes, NumberStyles.HexNumber);
    return string.Format(CultureInfo.InvariantCulture, "2.25.{0}", bigInteger);
}

The following method does the same but is about 5 times faster: 以下方法执行相同但速度提高约5倍:

public static string ConvertGuidToUuidInteger(ref Guid value)
{
    // ISO/IEC 9834-8, paragraph 6.3 (referenced by DICOM PS 3.5, B.2) defines how
    // to convert a UUID to a single integer value that can be converted back into a UUID.

    // The Guid.ToByteArray Method returns the array in a strange order (see .NET docs),
    // BigInteger expects the input array in little endian order.
    // The last byte controls the sign, add an additional zero to ensure
    // the array is parsed as a positive number.
    var octets = value.ToByteArray();
    var littleEndianOrder = new byte[]
    { octets[15], octets[14], octets[13], octets[12], octets[11], octets[10], octets[9], octets[8],
        octets[6], octets[7], octets[4], octets[5], octets[0], octets[1], octets[2], octets[3], 0 };

    return "2.25." + new BigInteger(littleEndianOrder).ToString(CultureInfo.InvariantCulture);
}

Refer this answer for more details about DICOM UID. 有关DICOM UID的更多详细信息,请参阅答案。

A] Increment the counters [Not Recommended] A]增加计数器[不推荐]

One simple logic is to get your SeriesInstanceUID and increment it by 1. So say your SeriesInstanceUID is "1.1.1.1.1" then your SOPInstanceUID may be "1.1.1.1. 2 " or "1.1.1.1.1. 1 ". 一个简单的逻辑是让你SeriesInstanceUID和1递增呢?所以说,你SeriesInstanceUID为“1.1.1.1.1”,那么你的SOPInstanceUID可能是“1.1.1.1。2”“1.1.1.1.1。1”。

Problems: 问题:

  • When the instance is deleted and next instance is created, the earlier counter should not be used. 删除实例并创建下一个实例时,不应使用较早的计数器。
  • In multi-threaded environment, enough care should be taken. 在多线程环境中,应该充分注意。
  • Does not guarantee uniqueness across different systems/applications. 不保证不同系统/应用程序的唯一性。

B] Date Time [Not Recommended] B]日期时间[不推荐]

Other technique generally used is to append time stamp (with ticks) to organization root. 通常使用的其他技术是将时间戳(带刻度)附加到组织根。

Problems: 问题:

  • Multi-threaded environment is an issue. 多线程环境是一个问题。
  • System clock may go off. 系统时钟可能会熄灭。
  • Uniqueness across different systems/applications cannot be guaranteed. 不能保证不同系统/应用程序的唯一性。

C] More Complex [RECOMMENDED] C]更复杂[推荐]

1.2.840.xxxxx.30.152.99999.235.20.100.yyyyMMddHHmmss.zzzzzz

Where: 哪里:

1.2.840.xxxxx: Organization Root 1.2.840.xxxxx:组织根
30: Application ID 30:应用程序ID
152: Application Version 152:应用程序版本
99999: Installation/Location ID 99999:安装/位置ID
235: Study ID 235:研究ID
20: Series Number 20:系列号
100: Image Number 100:图像编号
yyyyMMddHHmmss: Date Time yyyyMMddHHmmss:日期时间
zzzzzz: Thread safe counter/Random Number zzzzzz:线程安全计数器/随机数

Problems: 问题:

  • Algorithm may fail in case system clock goes off; 系统时钟关闭时算法可能会失败; this is protected by thread safe counter/random number further. 这受到线程安全计数器/随机数的进一步保护。 Remote possibility; 远程可能性; need to take little care. 需要小心谨慎。

D] UUID Derived UID [RECOMMENDED] D] UUID派生的UID [推荐]

UID may be generated from the root "2.25." 可以从根“2.25”生成UID。 followed by a decimal representation of a Universally Unique Identifier (UUID). 后跟通用唯一标识符(UUID)的十进制表示。

Problems: 问题:

  • This may be appropriate for dynamically created UIDs, such as SOP Instance UIDs, but is not appropriate for UIDs determined during design, such as private SOP Class or Transfer Syntax UIDs, or Implementation Class UIDs. 这可能适用于动态创建的UID,例如SOP实例UID,但不适用于在设计期间确定的UID,例如私有SOP类或传输语法UID或实现类UID。
  • UID is restricted to only 128 bits. UID仅限于128位。 DICOM UID support wider range. DICOM UID支持更广泛的范围。

According to the DICOM standard (PS 3.5-2011 Page 61), you need an orgroot and a suffix. 根据DICOM标准 (PS 3.5-2011第61页),您需要一个orgroot和一个后缀。 Examples can be found here (PS 3.5-2011 Page 83). 可以在此处找到示例(PS 3.5-2011第83页)。

Also do not forget that UI Fields have to be padded (if they do not have an even length) with '\\0' bytes and not with spaces. 另外,不要忘记UI字段必须用'\\ 0'字节填充(如果它们没有偶数长度)而不是空格。

I would suggest to create the UID like this: 我建议像这样创建UID:

YOUR_ORGROOT.Year.Month.Day.Hour.Minute.Second.Milliseconds.StaticCounter YOUR_ORGROOT.Year.Month.Day.Hour.Minute.Second.Milliseconds.StaticCounter

Beware that the limit is 64 chars! 请注意,限制是64个字符!

I would really suggest you go away from implementing it yourself. 我真的建议你从自己实现它 Most language do provide a UUID library these days, do not reinvent the wheel. 如今大多数语言确实提供了一个UUID库,不要重新发明轮子。 Esp. ESP。 if you are going to write code to extract MAC adress, this can be very complex writing it in portable C. 如果你要编写代码来提取MAC地址,那么在便携式 C中编写代码会非常复杂。

UUID do not exactly fit the DICOM definition, so you need to register your own Organisation Root UID, then simply pad with a generated UUID which bring spatial and time uniqueness condition. UUID不完全符合DICOM定义,因此您需要注册自己的组织根UID,然后使用生成的UUID填充,这会带来空间和时间唯一性条件。

YOUR_ORG_ROOT.CONVERTED_UUID

Pay attention that you have 64 bytes (that's plenty already, see here ) for storage in Value Representation UI: 请注意,您在Value Representation UI中有64个字节(已经很多,请参见此处 )存储:

  • Convert Hexadecimal notation of UUID to VR: UI definition ([0-9.]+) 将UUID的十六进制表示法转换为VR:UI定义([0-9.]+)
  • Trim with extreme care (you may introduce redundancy during this operation) 仔细修剪(在此操作期间可能会引入冗余)
  • Choose a short Org Root 选择一个简短的Org Root
  • Pad with \\0 (0 binary) if needed. 如果需要,使用\\0 (0二进制)填充。

Finally since you are using python, use uuid lib python-uuid . 最后因为您使用的是python,请使用uuid lib python-uuid


The above should be considered an alternate implementation to what is officially defined in the standard: 以上内容应被视为标准中正式定义的替代实现:

When converting directly a UUID to a UID, one must use the "2.25." 将UUID直接转换为UID时,必须使用“2.25”。 root. 根。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM