在对dcm4che3和dicom协议进行了一些研究之后,重述了我的原始帖子。
我正在使用dcm4che3工具包来构建一个应用程序,该应用程序本质上将是一个简单的Image Archive,能够根据需要将研究转发到其他方式。该工具还实现了s-store scu服务来查询自身,而且其他方式。
一项要求是能够从此本地档案中定期“删除”研究。
我也是dicom协议和dcm4che的新手,所以我试图理解底层dicomdir(由dcm4che-tool-dcmqrscp使用)的逻辑以及删除研究的任何可用服务或方法。
所以我的问题如下:
在dicom协议的上下文中,“删除研究”一词是否有效?
正如我在删除研究(使用该工具)时看到的“ dcm4che-tool-dcmdir”一样,实际上发生的是“删除引用由file ..或directory ..自变量指定的DICOM文件的记录。现有的目录文件,方法是将其记录在用标志设置为“ 0”,以便文件保留在文件系统中。
当我使用c查找scu查询档案时,如果我尝试以此方式删除研究(工具dicomdir中的-d选项),我可以找到研究 >。因此,即使我对归档文件执行c查找查询,即使dicomdir中的记录被标记为“不活动”,我仍然可以将其提取。
如果我尝试从文件系统中手动删除研究文件,我猜dicomdir损坏了。
是否还有其他方法(或协议的一部分)以一致的方式从dicomdir中删除研究(永久地从dicomdir记录中删除,如果可能的话,还从文件系统中删除)?
我用来删除研究的代码(在dicomdir中使用带有-d选项的类似方法)是
public void deleteDicomDir(String studyDir) throws IOException {
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
LOG.info("$$$ Trying to delete dicomdir: " + studyDir);
main.open(new File("C:\\dicomrouter_dev\\dcmrouter_root\\dicomdir"));
main.removeReferenceTo(new File(studyDir));
main.close();
long end = System.currentTimeMillis();
System.out.println();
System.out.println(MessageFormat.format(
rb.getString("deleted"),
num, main.getFile(), (end - start)));
}
“ removeReferenceTo()”方法的实际作用是在DicomDirWritter方法的末尾调用:
public synchronized boolean deleteRecord(Attributes rec)
throws IOException {
if (rec.getInt(Tag.RecordInUseFlag, 0) == INACTIVE)
return false; // already disabled
for (Attributes lowerRec = readLowerDirectoryRecord(rec);
lowerRec != null;
lowerRec = readNextDirectoryRecord(lowerRec))
deleteRecord(lowerRec);
rec.setInt(Tag.RecordInUseFlag, VR.US, INACTIVE);
markAsDirty(rec);
return true;
}
感谢您的时间,我很期待有任何声明这一点的信息
实际上,在对dicom协议以及dcm4che工具包进行了一些研究之后,我能够删除记录并同步我的DICOMDIR,并通过3个步骤将Record in-use Flag = 0删除记录(或文件):
//delete records referring DICOM files specified by <directory:studyDir> arguments from existing directory file <dicomdir> by setting its Record In-use Flag = 0
public void deleteDicomDir(String studyDir) {
String dicomdir = "C:\\dicomrouter_dev\\dcmrouter_root\\DICOMDIR";
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
try {
LOG.info("$$$ Trying to delete dicomdir: " + studyDir);
main.open(new File(dicomdir));
int num = 0;
main.removeReferenceTo(new File(studyDir));
main.close();
long end = System.currentTimeMillis();
System.out.println();
System.out.println(MessageFormat.format(
rb.getString("deleted"),
num, main.getFile(), (end - start)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(DcmDir1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
main.close();
}
}
//purge records without file references from directory file <dicomdir> by setting its Record In-use Flag = 0
public void purgeDicomDir() {
String dicomdir = "C:\\dicomrouter_dev\\dcmrouter_root\\DICOMDIR";
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
try {
main.open(new File(dicomdir));
int num = main.purge();
main.close();
long end = System.currentTimeMillis();
System.out.println(MessageFormat.format(
rb.getString("purged"),
num, main.getFile(), (end - start)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(DcmDir1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
main.close();
}
}
//compact existing directory file <dicomdir> by removing records with Record In-use Flag != 0
public void compactDicomDir() {
String fpath = "C:\\dicomrouter_dev\\dcmrouter_root\\DICOMDIR";
File f = new File(fpath);
File bak = new File(fpath + "~");
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
try {
LOG.info("$$$ Trying to compact dicomdir: " + fpath);
main.compact(f, bak);
long end = System.currentTimeMillis();
System.out.println(MessageFormat.format(
rb.getString("compacted"),
f, bak.length(), f.length(), (end - start)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(DcmDir1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
main.close();
}
}
然后,我也可以安全地从磁盘中删除文件。
答案 0 :(得分:2)
我已经在评论中(现在已删除)向您说明了这一点。我还向您指出了this问题,该问题讨论了同一件事。正如我在评论中所说,这更多是关于协议而不是工具包。
第一件事,当您说“删除研究”时,我假设您实际上是想从硬盘上删除DICOM文件,并将其引用放在其他位置(DICOMDIR或数据库等)。
在DICOM中无法做到这一点。
DICOM中的N-DELETE命令不用于此目的。如this答案中所述,您可以尝试Imaging Object Change Management IHE集成配置文件。我没用过很抱歉,我无法对此进一步评论。
在dicom协议的上下文中,“删除研究”一词是否有效?
如上所述,不。
正如我在删除研究(使用工具)时所看到的“ dcm4che-tool-dcmdir”一样,实际上发生的是“从现有目录文件中删除引用由file ..或directory ..参数指定的DICOM文件的记录。通过设置其“记录使用中标志= 0”,使文件保留在文件系统中。
这似乎很自然。该命令应只修改DICOMDIR即可删除文件。它不应从硬盘删除物理文件。
当我使用c查找scu查询档案时,如果我尝试以此方式删除研究(工具dicomdir中的-d选项),我还能找到研究。因此,即使我对归档文件执行c查找查询,即使dicomdir中的记录被标记为“无效”,我仍然可以将其提取。
我不知道您的C-FIND-RESPONSE
的来源。如果它本身是DICOMDIR,则很可能不会保存您在先前步骤中所做的修改。保存所做的修改,它应该可以工作。但是请记住,这仍然不会从物理存储中删除文件。您只是删除它的引用。
我不是您正在使用的工具箱的专家。但是,您的问题中包含以下代码:
main.open(new File("C:\\dicomrouter_dev\\dcmrouter_root\\dicomdir"));
main.removeReferenceTo(new File(studyDir));
//Check if you need to save the changes here before closing
main.close();
似乎您正在打开DICOMDIR-从中删除目录引用-关闭DICOMDIR。我不知道removeReferenceTo
方法的实现;可能来自github。如果它也没有保存更改,则必须显式保存更改。可能是您需要使用DicomOutputStream
类来做到这一点。我发现以下示例代码here:
FileOutputStream fos = new FileOutputStream(fileOutput +".dcm");
BufferedOutputStream bos = new BufferedOutputStream(fos);
DicomOutputStream dos = new DicomOutputStream(bos);
dos.writeDicomFile(dio);
dos.close();
如果我尝试从文件系统中手动删除研究文件,我猜dicomdir损坏了。
是;那就对了。为避免这种情况,还应相应地修改DICOMDIR。物理存储和DICOMDIR都应处于一致状态。
提案-1:
-d
命令)。建议-2:
使用DICOM命令,实现自定义行为。修改DICOM命令的行为(可能为N-DELETE)以执行其他操作。仅当您有权访问源代码并愿意更改它时,才有可能。我个人不建议这样做,因为: