dicom3tools 20260901__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. dicom3tools/__init__.py +138 -0
  2. dicom3tools/_version.py +24 -0
  3. dicom3tools/_version.pyi +2 -0
  4. dicom3tools/bin/ancp.exe +0 -0
  5. dicom3tools/bin/ancreate.exe +0 -0
  6. dicom3tools/bin/andiff +21 -0
  7. dicom3tools/bin/andump.exe +0 -0
  8. dicom3tools/bin/antodc.all +40 -0
  9. dicom3tools/bin/antodc.exe +0 -0
  10. dicom3tools/bin/binpatch.exe +0 -0
  11. dicom3tools/bin/bmpdump.exe +0 -0
  12. dicom3tools/bin/cygX11-6.dll +0 -0
  13. dicom3tools/bin/cygXau-6.dll +0 -0
  14. dicom3tools/bin/cygXdmcp-6.dll +0 -0
  15. dicom3tools/bin/cyggcc_s-seh-1.dll +0 -0
  16. dicom3tools/bin/cygiconv-2.dll +0 -0
  17. dicom3tools/bin/cygintl-8.dll +0 -0
  18. dicom3tools/bin/cygstdc++-6.dll +0 -0
  19. dicom3tools/bin/cygwin1.dll +0 -0
  20. dicom3tools/bin/cygxcb-1.dll +0 -0
  21. dicom3tools/bin/dcacqmap +340 -0
  22. dicom3tools/bin/dcanon +604 -0
  23. dicom3tools/bin/dcarith.exe +0 -0
  24. dicom3tools/bin/dcbriggs.exe +0 -0
  25. dicom3tools/bin/dcburn.exe +0 -0
  26. dicom3tools/bin/dcbzip2 +15 -0
  27. dicom3tools/bin/dccidump.exe +0 -0
  28. dicom3tools/bin/dcckovly +62 -0
  29. dicom3tools/bin/dccmp +21 -0
  30. dicom3tools/bin/dccomb.exe +0 -0
  31. dicom3tools/bin/dccp.exe +0 -0
  32. dicom3tools/bin/dccreate.exe +0 -0
  33. dicom3tools/bin/dccsdump.exe +0 -0
  34. dicom3tools/bin/dcdecmpr.exe +0 -0
  35. dicom3tools/bin/dcdeflate +11 -0
  36. dicom3tools/bin/dcdict.exe +0 -0
  37. dicom3tools/bin/dcdiff +21 -0
  38. dicom3tools/bin/dcdirdmp.exe +0 -0
  39. dicom3tools/bin/dcdirmk.exe +0 -0
  40. dicom3tools/bin/dcdisp.exe +0 -0
  41. dicom3tools/bin/dcdtchg.exe +0 -0
  42. dicom3tools/bin/dcdump.exe +0 -0
  43. dicom3tools/bin/dcencap.exe +0 -0
  44. dicom3tools/bin/dcentvfy.exe +0 -0
  45. dicom3tools/bin/dcfile.exe +0 -0
  46. dicom3tools/bin/dchist.exe +0 -0
  47. dicom3tools/bin/dcinflate +17 -0
  48. dicom3tools/bin/dcinfo.exe +0 -0
  49. dicom3tools/bin/dciodvfy.exe +0 -0
  50. dicom3tools/bin/dcj2k +80 -0
  51. dicom3tools/bin/dcjls +58 -0
  52. dicom3tools/bin/dcjpeg +58 -0
  53. dicom3tools/bin/dckey.exe +0 -0
  54. dicom3tools/bin/dclutburn.exe +0 -0
  55. dicom3tools/bin/dclutdmp.exe +0 -0
  56. dicom3tools/bin/dclutmix.exe +0 -0
  57. dicom3tools/bin/dcmerge.exe +0 -0
  58. dicom3tools/bin/dcmkpres.exe +0 -0
  59. dicom3tools/bin/dcmulti.exe +0 -0
  60. dicom3tools/bin/dcmvhier +73 -0
  61. dicom3tools/bin/dcmvhier.8only +90 -0
  62. dicom3tools/bin/dcmvhier.all +23 -0
  63. dicom3tools/bin/dcmvhier.datedesc +85 -0
  64. dicom3tools/bin/dcmvhier.datedescnoid +77 -0
  65. dicom3tools/bin/dcmvhier.uid +73 -0
  66. dicom3tools/bin/dcortho.exe +0 -0
  67. dicom3tools/bin/dcostosr.exe +0 -0
  68. dicom3tools/bin/dcpatmpl +51 -0
  69. dicom3tools/bin/dcposn.exe +0 -0
  70. dicom3tools/bin/dcpost.exe +0 -0
  71. dicom3tools/bin/dcproj.exe +0 -0
  72. dicom3tools/bin/dcrmmeta.exe +0 -0
  73. dicom3tools/bin/dcrmsfx.all +15 -0
  74. dicom3tools/bin/dcsmpte.exe +0 -0
  75. dicom3tools/bin/dcsort.exe +0 -0
  76. dicom3tools/bin/dcsqextr.exe +0 -0
  77. dicom3tools/bin/dcsrdiff +24 -0
  78. dicom3tools/bin/dcsrdump.exe +0 -0
  79. dicom3tools/bin/dcsrmrg.exe +0 -0
  80. dicom3tools/bin/dcstats.exe +0 -0
  81. dicom3tools/bin/dcsub.exe +0 -0
  82. dicom3tools/bin/dcswab +21 -0
  83. dicom3tools/bin/dctable.exe +0 -0
  84. dicom3tools/bin/dctable_decompressingprn +30 -0
  85. dicom3tools/bin/dctopdf.exe +0 -0
  86. dicom3tools/bin/dctopgm8.exe +0 -0
  87. dicom3tools/bin/dctopgx.exe +0 -0
  88. dicom3tools/bin/dctopnm.exe +0 -0
  89. dicom3tools/bin/dctoraw.exe +0 -0
  90. dicom3tools/bin/dcuidchg.exe +0 -0
  91. dicom3tools/bin/dcunbzip2 +17 -0
  92. dicom3tools/bin/dcuncat.exe +0 -0
  93. dicom3tools/bin/dcunjls +46 -0
  94. dicom3tools/bin/dcunjpeg +146 -0
  95. dicom3tools/bin/dcunjpeg.all +32 -0
  96. dicom3tools/bin/dcunmeta.exe +0 -0
  97. dicom3tools/bin/dcunrgb +125 -0
  98. dicom3tools/bin/dumptiff.exe +0 -0
  99. dicom3tools/bin/dumpwhat.exe +0 -0
  100. dicom3tools/bin/gawdump.exe +0 -0
  101. dicom3tools/bin/gawtodc.exe +0 -0
  102. dicom3tools/bin/ge9800dump.exe +0 -0
  103. dicom3tools/bin/ge9800todc.exe +0 -0
  104. dicom3tools/bin/ge98id.exe +0 -0
  105. dicom3tools/bin/ge98topgm.exe +0 -0
  106. dicom3tools/bin/gendump.exe +0 -0
  107. dicom3tools/bin/gentodc.dat.all +34 -0
  108. dicom3tools/bin/gentodc.exe +0 -0
  109. dicom3tools/bin/gentopgm.exe +0 -0
  110. dicom3tools/bin/himrdump.exe +0 -0
  111. dicom3tools/bin/himrtodc.exe +0 -0
  112. dicom3tools/bin/imtndump.exe +0 -0
  113. dicom3tools/bin/imtntodc.exe +0 -0
  114. dicom3tools/bin/jpegdump.exe +0 -0
  115. dicom3tools/bin/jpegsplit.exe +0 -0
  116. dicom3tools/bin/pacedump.exe +0 -0
  117. dicom3tools/bin/pacetodc.exe +0 -0
  118. dicom3tools/bin/pacetopgm.exe +0 -0
  119. dicom3tools/bin/paceunid +31 -0
  120. dicom3tools/bin/pbmswbit.exe +0 -0
  121. dicom3tools/bin/pbmtoovl.exe +0 -0
  122. dicom3tools/bin/pdftodc.exe +0 -0
  123. dicom3tools/bin/pgmtobmp.exe +0 -0
  124. dicom3tools/bin/pgxtodc.exe +0 -0
  125. dicom3tools/bin/pnmpred.exe +0 -0
  126. dicom3tools/bin/pnmtodc.exe +0 -0
  127. dicom3tools/bin/pnmtoraw.exe +0 -0
  128. dicom3tools/bin/pqdump.exe +0 -0
  129. dicom3tools/bin/pqsplit.exe +0 -0
  130. dicom3tools/bin/pqtodc.exe +0 -0
  131. dicom3tools/bin/rawarith.exe +0 -0
  132. dicom3tools/bin/rawdiff.exe +0 -0
  133. dicom3tools/bin/rawftodc.exe +0 -0
  134. dicom3tools/bin/rawmask.exe +0 -0
  135. dicom3tools/bin/rawnjl.exe +0 -0
  136. dicom3tools/bin/rawnjl2.exe +0 -0
  137. dicom3tools/bin/rawtodc.exe +0 -0
  138. dicom3tools/bin/sgndump.exe +0 -0
  139. dicom3tools/bin/sgntodc.exe +0 -0
  140. dicom3tools/bin/sgntopgm.exe +0 -0
  141. dicom3tools/bin/shimdump.exe +0 -0
  142. dicom3tools/bin/shimtodc.exe +0 -0
  143. dicom3tools/bin/sompdump.exe +0 -0
  144. dicom3tools/bin/somptodc.exe +0 -0
  145. dicom3tools/bin/somtopgm.exe +0 -0
  146. dicom3tools/bin/syttopgm.exe +0 -0
  147. dicom3tools/bin/toshtodc +68 -0
  148. dicom3tools/bin/vsntopgm.exe +0 -0
  149. dicom3tools/py.typed +0 -0
  150. dicom3tools/share/COPYRIGHT +28 -0
  151. dicom3tools/share/VERSION.txt +1 -0
  152. dicom3tools-20260901.dist-info/METADATA +361 -0
  153. dicom3tools-20260901.dist-info/RECORD +156 -0
  154. dicom3tools-20260901.dist-info/WHEEL +5 -0
  155. dicom3tools-20260901.dist-info/entry_points.txt +28 -0
  156. dicom3tools-20260901.dist-info/licenses/LICENSE +212 -0
@@ -0,0 +1,138 @@
1
+ """
2
+ dicom3tools: Python distribution of David Clunie's dicom3tools command line utilities.
3
+
4
+ The wheels wrap the official dicom3tools programs, built by the workflows in
5
+ ImagingDataCommons/dicom3tools. A curated set of them is installed on PATH as console scripts
6
+ (see binaries.txt), and every program in the wheel is callable from Python, so that
7
+
8
+ dcdump some.dcm
9
+
10
+ and
11
+
12
+ from dicom3tools import dcdump
13
+
14
+ behave the same way. Programs with no console script are reached the same way::
15
+
16
+ from dicom3tools import pnmtodc
17
+ pnmtodc() # argv-driven, like the command line
18
+
19
+ and the handful whose names are not Python identifiers -- the `dcmvhier.all` family -- through
20
+ ``run()``::
21
+
22
+ from dicom3tools import run
23
+ run("dcmvhier.all", ["/some/dir"])
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import os
29
+ import subprocess
30
+ import sys
31
+ from collections.abc import Callable, Sequence
32
+ from importlib.metadata import distribution
33
+ from pathlib import Path, PurePosixPath
34
+ from typing import NoReturn
35
+
36
+ from ._version import version as __version__
37
+
38
+ _PACKAGE = "dicom3tools"
39
+
40
+ # The Windows wheels ship the Cygwin runtime DLLs in the same directory as the executables;
41
+ # those are dependencies of the programs, not tools, and must not become callables.
42
+ _LIBRARY_SUFFIXES = frozenset({".dll"})
43
+
44
+
45
+ def _installed_tools() -> dict[str, Path]:
46
+ """Map every program in dicom3tools/bin to its installed path, keyed without .exe."""
47
+ files = distribution(_PACKAGE).files
48
+ tools: dict[str, Path] = {}
49
+ for _file in files or []:
50
+ # Distribution file paths are always posix-flavoured, on every platform.
51
+ parts = PurePosixPath(str(_file)).parts
52
+ if len(parts) != 3 or parts[0] != _PACKAGE or parts[1] != "bin":
53
+ continue
54
+ name = parts[2]
55
+ if PurePosixPath(name).suffix.lower() in _LIBRARY_SUFFIXES:
56
+ continue
57
+ stem = name[:-4] if name.lower().endswith(".exe") else name
58
+ tools[stem] = Path(_file.locate())
59
+ return tools
60
+
61
+
62
+ _TOOLS = _installed_tools()
63
+
64
+
65
+ def bin_dir() -> Path:
66
+ """Return the directory holding the packaged dicom3tools programs.
67
+
68
+ Useful for the programs that have no console script, and for putting the whole toolkit on
69
+ PATH in a subprocess of your own.
70
+ """
71
+ for path in _TOOLS.values():
72
+ return path.parent.resolve(strict=True)
73
+ msg = f"No dicom3tools programs are installed in '{_PACKAGE}/bin'."
74
+ raise FileNotFoundError(msg)
75
+
76
+
77
+ def _lookup(name: str) -> Path:
78
+ path = _TOOLS.get(name)
79
+ if path is None:
80
+ msg = (
81
+ f"'{name}' is not among the programs installed in '{_PACKAGE}/bin'. "
82
+ f"Installed: {', '.join(sorted(_TOOLS))}"
83
+ )
84
+ raise FileNotFoundError(msg)
85
+ return path.resolve(strict=True)
86
+
87
+
88
+ def run(name: str, args: Sequence[str] = ()) -> int:
89
+ """Run a packaged dicom3tools program and return its exit status.
90
+
91
+ The child inherits this process's streams, and note where dicom3tools writes: diagnostics
92
+ go to stderr, and for the reporting tools that is *all* their output -- ``dcdump`` prints
93
+ its entire dump there, so redirecting only stdout captures nothing. Exit statuses are also
94
+ less informative than they look: ``dcdump`` and ``dciodvfy`` do return 1 when they report an
95
+ error, but others (``dcfile``) return 0 on input they could not make sense of.
96
+ """
97
+ executable = _lookup(name)
98
+
99
+ if os.name == "nt" and executable.suffix.lower() != ".exe":
100
+ msg = (
101
+ f"'{name}' is a /bin/sh script from the Cygwin build and cannot be run natively on "
102
+ "Windows. Run it under a shell that can, or use the programs it wraps directly."
103
+ )
104
+ raise RuntimeError(msg)
105
+
106
+ # Several of the packaged tools are shell scripts that call their siblings by bare name
107
+ # (dccmp runs dctoraw, dcanon runs dcdump and dckey). Those lookups go through PATH, which
108
+ # only happens to contain the packaged bin directory when the caller installed into an
109
+ # active virtualenv and is invoking a console script. Prepending it here makes the tools
110
+ # behave the same whether they are reached from PATH, from Python, or from a subprocess of
111
+ # an application that never activated anything.
112
+ env = dict(os.environ)
113
+ env["PATH"] = os.pathsep.join(
114
+ part for part in (str(executable.parent), env.get("PATH", "")) if part
115
+ )
116
+
117
+ return subprocess.call([str(executable), *args], close_fds=False, env=env)
118
+
119
+
120
+ def _make_wrapper(name: str) -> Callable[[], NoReturn]:
121
+ def _wrapper() -> NoReturn:
122
+ raise SystemExit(run(name, sys.argv[1:]))
123
+
124
+ _wrapper.__name__ = name
125
+ _wrapper.__qualname__ = name
126
+ _wrapper.__doc__ = (
127
+ f"Run the {name} program with arguments passed to a Python script."
128
+ )
129
+ return _wrapper
130
+
131
+
132
+ # A callable for every installed program whose name can be an attribute. That excludes the
133
+ # `dcmvhier.all`-style variants, whose names contain dots; run() reaches those.
134
+ _callable_tools = sorted(name for name in _TOOLS if name.isidentifier())
135
+ for _name in _callable_tools:
136
+ globals()[_name] = _make_wrapper(_name)
137
+
138
+ __all__ = ["__version__", "bin_dir", "run", *_callable_tools] # noqa: PLE0604
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '20260901'
22
+ __version_tuple__ = version_tuple = (20260901,)
23
+
24
+ __commit_id__ = commit_id = 'g088efa4'
@@ -0,0 +1,2 @@
1
+ version: str
2
+ version_tuple: tuple[int, int, int] | tuple[int, int, int, str, str]
Binary file
Binary file
dicom3tools/bin/andiff ADDED
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+
3
+ # compare the dumps of two ACR-NEMA files
4
+
5
+ if [ $# != 2 ]
6
+ then
7
+ echo "usage: `basename $0` file1 file2"
8
+ exit 1
9
+ fi
10
+
11
+ TMPFILE1=/tmp/`basename $0`.$$.tmp1
12
+ TMPFILE2=/tmp/`basename $0`.$$.tmp2
13
+
14
+ andump "$1" >"$TMPFILE1" 2>&1
15
+ andump "$2" >"$TMPFILE2" 2>&1
16
+ diff "$TMPFILE1" "$TMPFILE2"
17
+
18
+ rm "$TMPFILE1" "$TMPFILE2"
19
+
20
+ exit 0
21
+
Binary file
@@ -0,0 +1,40 @@
1
+ #!/bin/sh
2
+
3
+ # Usage: antodc.all dirname
4
+ #
5
+ # where dirname is the directory name where images are
6
+ #
7
+ # converts files in place and adds .dcm extension
8
+ #
9
+ # removes private tags to avoid UN VR in explicit endian
10
+ # for those private tags that aren't in the dictionary
11
+ #
12
+ # removes any (obvious) sequences since they mess up some viewers
13
+ #
14
+
15
+ DCMSUFFIX="dcm"
16
+
17
+ STAMP=`date +%Y%m%d%H%M%S`.$$
18
+
19
+ ANTODC="antodc"
20
+
21
+ if [ ! $# = 1 ]
22
+ then
23
+ echo 1>&2 "Usage: `basename $0` dirname"
24
+ exit 1
25
+ fi
26
+
27
+ for i in `find "$1" -type f -a ! -name '.*' -print`
28
+ do
29
+ if [ -f "$i" ]
30
+ then
31
+ echo "Converting $i to $i.$DCMSUFFIX"
32
+
33
+ $ANTODC -output-vr explicit -output-endian little -stamp "$STAMP" \
34
+ -removeprivate \
35
+ -d ReferencedImageSequence -d IconImageSequence -d SourceImageSequence \
36
+ "$i" "$i.$DCMSUFFIX"
37
+ fi
38
+ done
39
+
40
+ exit 0
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,340 @@
1
+ #!/bin/sh
2
+ #
3
+ # not tolerant of spaces in file names
4
+ #
5
+
6
+ usage() {
7
+ echo 1>&2 "Usage: $1 [-byacqnumber] [-byslicelocation] [-byscanoptions] [-bytemporalpositionidentifier] [-locationtolerance n] [-iconsize n] [-nodump] [-xhtml] [-isonames] [-nostyle] filenamesfile resultfolder"
8
+ }
9
+
10
+ ACQUISITIONPARAMETER=AcquisitionTime
11
+ POSITIONPARAMETER=ImagePositionPatient
12
+ LOCATIONTOLERANCE=""
13
+ ICONSIZE=128
14
+ INCLUDEREPORT="yes"
15
+ MAKEXHTML="no"
16
+ USEUIDFORFILENAME="yes"
17
+ USESTYLESHEET="yes"
18
+ SHORTAGTERMINATOR=""
19
+
20
+ while [ $# -gt 2 ]
21
+ do
22
+ if [ "$1" = "-byacqnumber" ]
23
+ then
24
+ ACQUISITIONPARAMETER=AcquisitionNumber
25
+ elif [ "$1" = "-byorientation" ]
26
+ then
27
+ # useful for series with different angulations
28
+ ACQUISITIONPARAMETER=ImageOrientationPatient
29
+ elif [ "$1" = "-byscanoptions" ]
30
+ then
31
+ # useful for Siemens Cardiac acquisitions where %RR is embedded in this attribute
32
+ ACQUISITIONPARAMETER=ScanOptions
33
+ elif [ "$1" = "-bytemporalpositionidentifier" ]
34
+ then
35
+ # useful for Philips perfusion acquisitions, within set of images all with the same AcquisitionNumber
36
+ ACQUISITIONPARAMETER=TemporalPositionIdentifier
37
+ elif [ "$1" = "-byslicelocation" ]
38
+ then
39
+ POSITIONPARAMETER=SliceLocation
40
+ elif [ "$1" = "-nodump" ]
41
+ then
42
+ INCLUDEREPORT="no"
43
+ elif [ "$1" = "-xhtml" ]
44
+ then
45
+ MAKEXHTML="yes"
46
+ SHORTAGTERMINATOR="/"
47
+ elif [ "$1" = "-isonames" ]
48
+ then
49
+ USEUIDFORFILENAME="no"
50
+ elif [ "$1" = "-nostyle" ]
51
+ then
52
+ USESTYLESHEET="no"
53
+ elif [ "$1" = "-locationtolerance" ]
54
+ then
55
+ shift
56
+ LOCATIONTOLERANCE="$1"
57
+ elif [ "$1" = "-iconsize" ]
58
+ then
59
+ shift
60
+ ICONSIZE="$1"
61
+ else
62
+ usage `basename $0`
63
+ exit 1
64
+ fi
65
+ shift
66
+ done
67
+
68
+ FILENAMESFILE="$1"
69
+ RESULTFOLDERNAME="$2"
70
+
71
+ if [ $# -ne 2 -o ! -f "${FILENAMESFILE}" ]
72
+ then
73
+ usage `basename $0`
74
+ exit 1
75
+ fi
76
+
77
+ HTMLFILE="index.html"
78
+ ICONSDIR="icons"
79
+ REPORTSDIR="reports"
80
+ STYLESHEET="style.css"
81
+
82
+ mkdir -p "${RESULTFOLDERNAME}"
83
+
84
+ FQHTMLFILE="${RESULTFOLDERNAME}/${HTMLFILE}"
85
+ FQICONSDIR="${RESULTFOLDERNAME}/${ICONSDIR}"
86
+ FQSTYLESHEET="${RESULTFOLDERNAME}/${STYLESHEET}"
87
+ FQREPORTSDIR="${RESULTFOLDERNAME}/${REPORTSDIR}"
88
+
89
+ mkdir -p "${FQICONSDIR}"
90
+ if [ "${INCLUDEREPORT}" = "yes" ]
91
+ then
92
+ mkdir -p "${FQREPORTSDIR}"
93
+ fi
94
+
95
+ TMPROOT=/tmp/`basename $0`.$$.
96
+
97
+ SORTEDBYPOSITION="${TMPROOT}sortedbyposition.dat"
98
+ POSITIONLIST="${TMPROOT}positionlist.dat"
99
+ SUBKEYS="${TMPROOT}subkeys.dat"
100
+ UNIQUESUBKEYS="${TMPROOT}uniquesubkeys.dat"
101
+ PARAMETERSBYFILE="${TMPROOT}parametersbyfile.dat"
102
+
103
+ CURRENTPOSITIONFILES="${TMPROOT}currentpositionfiles.dat"
104
+ SORTEDWITHINPOSITION="${TMPROOT}sortedwithinposition.dat"
105
+ ROWFILE="${TMPROOT}rowfile.dat"
106
+
107
+ useTitle=""
108
+
109
+ echo 1>&2 "Stage 1: identifying unique values of position and sorting"
110
+ if [ -z "${LOCATIONTOLERANCE}" ]
111
+ then
112
+ dcsort -index -show -k "${POSITIONPARAMETER}" `cat "${FILENAMESFILE}"` >"${SORTEDBYPOSITION}" 2>&1
113
+ else
114
+ dcsort -index -show -k "${POSITIONPARAMETER}" `cat "${FILENAMESFILE}"` 2>&1 | awk -v locationtolerance="${LOCATIONTOLERANCE}" '{print $1 "\t" $2 "\t" (int($3*locationtolerance+0.5)/locationtolerance)}' >"${SORTEDBYPOSITION}"
115
+ fi
116
+ #cat 1>&2 "${SORTEDBYPOSITION}"
117
+ awk < "${SORTEDBYPOSITION}" '{print $3}' | sort -u -n -r > "${POSITIONLIST}" # -r here makes head to toe, rather than -descending in dcsort
118
+ #cat 1>&2 "${POSITIONLIST}"
119
+
120
+ echo 1>&2 "Stage 2: making icons, extracting other key values than position and identifying unique combinations of those keys"
121
+ rm -f "${UNIQUESUBKEYS}"
122
+ rm -f "${PARAMETERSBYFILE}"
123
+ for i in `cat "${FILENAMESFILE}"`
124
+ do
125
+ if [ -z "${useTitle}" ]
126
+ then
127
+ useTitle=`dckey -noerror -k PatientName "$i" 2>&1 | egrep -iv '(error|warning)' | head -1`
128
+ fi
129
+
130
+ dckey -brief -k SliceThickness -k ConvolutionKernel -k "${ACQUISITIONPARAMETER}" -k SOPInstanceUID "$i" >"${SUBKEYS}" 2>&1
131
+ #cat "${SUBKEYS}"
132
+ sopInstanceUID=`grep SOPInstanceUID "${SUBKEYS}"| sed -e 's/^SOPInstanceUID=//'`
133
+ if [ ! -f "${FQICONSDIR}/${sopInstanceUID}.jpg" ]
134
+ then
135
+ dctopgm8 -quiet "$i" 2>/dev/null | pamscale -xsize "${ICONSIZE}" -ysize "${ICONSIZE}" | cjpeg >"${FQICONSDIR}/${sopInstanceUID}.jpg"
136
+ fi
137
+
138
+ sliceThickness=`grep SliceThickness "${SUBKEYS}"| sed -e 's/^SliceThickness=//'`
139
+ if [ -z "${sliceThickness}" ]; then sliceThickness="0.0"; fi
140
+ convolutionKernel=`grep ConvolutionKernel "${SUBKEYS}"| sed -e 's/^ConvolutionKernel=//' -e 's/[^A-Za-z0-9_]/_/g'`
141
+ if [ -z "${convolutionKernel}" ]; then convolutionKernel="NONE"; fi
142
+ acquisitionParameter=`grep "${ACQUISITIONPARAMETER}" "${SUBKEYS}"| sed -e "s/^${ACQUISITIONPARAMETER}=//" -e 's/ $//g' -e 's/^ //g' -e 's/[^0-9a-zA-Z+-]/_/g'`
143
+ #echo "${acquisitionParameter}"
144
+ if [ -z "${acquisitionParameter}" ]; then acquisitionParameter="999999"; fi
145
+ echo "${acquisitionParameter} ${convolutionKernel} ${sliceThickness}" | awk '{print $1 " " $2 " " $3}' >>"${UNIQUESUBKEYS}" # awk is to get spaces same as later
146
+ echo "${acquisitionParameter} ${convolutionKernel} ${sliceThickness} ${sopInstanceUID} $i" >>"${PARAMETERSBYFILE}"
147
+
148
+ rm -f "${SUBKEYS}"
149
+ done
150
+ mv "${UNIQUESUBKEYS}" "${UNIQUESUBKEYS}.bak"
151
+ sort -u <"${UNIQUESUBKEYS}.bak" | sort -n -k1,1 -d -k2,2 -n -k3,3 >"${UNIQUESUBKEYS}" # why twice ? in case different alphas interpreted as same numeric
152
+ rm -f "${UNIQUESUBKEYS}.bak"
153
+
154
+ #cat 1>&2 "${PARAMETERSBYFILE}"
155
+ #cat 1>&2 "${UNIQUESUBKEYS}"
156
+ numberofuniquekeys=`wc -l "${UNIQUESUBKEYS}" | awk '{print $1}'` # is the number of html columns we will need
157
+ #echo 1>&2 "numberofuniquekeys = ${numberofuniquekeys}"
158
+
159
+ echo 1>&2 "Stage 3: building HTML file"
160
+ if [ "${MAKEXHTML}" = "yes" ]
161
+ then
162
+ echo > "${FQHTMLFILE}" '<?xml version="1.0" encoding="utf-8" ?>'
163
+ echo >>"${FQHTMLFILE}" '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">'
164
+ echo >>"${FQHTMLFILE}" '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'
165
+ else
166
+ echo >"${FQHTMLFILE}" "<html>"
167
+ fi
168
+ echo >>"${FQHTMLFILE}" "<head>"
169
+ echo >>"${FQHTMLFILE}" "<title>${useTitle}</title>"
170
+ if [ "${USESTYLESHEET}" = "yes" ]
171
+ then
172
+ echo >>"${FQHTMLFILE}" "<link rel=\"stylesheet\" type=\"text/css\" href=\"${STYLESHEET}\"${SHORTAGTERMINATOR}>"
173
+ fi
174
+ echo >>"${FQHTMLFILE}" "</head>"
175
+ if [ "${USESTYLESHEET}" = "yes" ]
176
+ then
177
+ echo >>"${FQHTMLFILE}" "<body>"
178
+ else
179
+ if [ "${MAKEXHTML}" = "yes" ]
180
+ then
181
+ echo >>"${FQHTMLFILE}" '<body style="color: lavender; background-color : black; font-family: Arial, sans-serif;">'
182
+ else
183
+ echo >>"${FQHTMLFILE}" "<body bgcolor=\"black\" text=\"lavender\">"
184
+ # note that the face attribute is only supported by IE (see "http://www.blooberry.com/indexdot/html/tagpages/b/basefont.htm"); size of 3 is default
185
+ echo >>"${FQHTMLFILE}" "<basefont size=\"3\" face=\"Arial, sans-serif\"${SHORTAGTERMINATOR}>"
186
+ fi
187
+ fi
188
+ echo >>"${FQHTMLFILE}" "<table>"
189
+ echo >>"${FQHTMLFILE}" "<tr><th>Position</th>"
190
+ xargs <"${UNIQUESUBKEYS}" -L1 -J% echo '<th align="center">' % '</th>' >>"${FQHTMLFILE}"
191
+ echo >>"${FQHTMLFILE}" "</tr>"
192
+
193
+ countForFileName=0
194
+ for position in `cat "${POSITIONLIST}"`
195
+ do
196
+ #echo 1>&2 "Position = ${position}"
197
+ echo >>"${FQHTMLFILE}" "<tr><td>${position}</td>"
198
+ positionWithPeriodEscaped=`echo "${position}" | sed -e 's/[.]/[.]/'`
199
+ #echo 1>&2 "positionWithPeriodEscaped = ${positionWithPeriodEscaped}"
200
+ grepstring="[^.0-9-]${positionWithPeriodEscaped}\$"
201
+ #echo 1>&2 "grepstring = ${grepstring}"
202
+ egrep "${grepstring}" "${SORTEDBYPOSITION}" | awk '{print $2}' >"${CURRENTPOSITIONFILES}"
203
+ #cat 1>&2 <"${CURRENTPOSITIONFILES}"
204
+ rm -f "${ROWFILE}"
205
+ for i in `cat "${CURRENTPOSITIONFILES}"`
206
+ do
207
+ #echo 1>&2 "i = $i"
208
+ whichfileentry=`grep "$i" "${PARAMETERSBYFILE}" | head -1`
209
+ #echo 1>&2 "whichfileentry = ${whichfileentry}"
210
+ parameters=`echo "${whichfileentry}" | awk '{print $1 " " $2 " " $3}'` # awk is to get spaces same as in UNIQUESUBKEYS (see grep later)
211
+ #echo 1>&2 "parameters = ${parameters}"
212
+ sopInstanceUID=`echo "${whichfileentry}" | awk '{print $4}'`
213
+ #echo 1>&2 "sopInstanceUID = ${sopInstanceUID}"
214
+ whichuniquesubkey=`grep -n "${parameters}" "${UNIQUESUBKEYS}" | sed -e 's/:.*$//'`
215
+ #echo 1>&2 "whichuniquesubkey = ${whichuniquesubkey}"
216
+ echo "${whichuniquesubkey}: ${sopInstanceUID} $i" >>"${ROWFILE}"
217
+ done
218
+ firstfile=""
219
+ count=1
220
+ while [ ${count} -le ${numberofuniquekeys} ]
221
+ do
222
+ row=`egrep "^$count: " "${ROWFILE}" | head -1 | sed -e 's/^[0-9]*:[ ]*//'`
223
+ if [ -z "${row}" ]
224
+ then
225
+ echo >>"${FQHTMLFILE}" "<td></td>"
226
+ else
227
+ #echo 1>&2 "Got row = ${row}"
228
+ sopInstanceUID=`echo "${row}" | sed -e 's/^\([0-9][0-9.]*\).*$/\1/'`
229
+ #echo 1>&2 "Got sopInstanceUID = ${sopInstanceUID}"
230
+ if [ "${USEUIDFORFILENAME}" = "yes" ]
231
+ then
232
+ baseForFileName="${sopInstanceUID}"
233
+ else
234
+ baseForFileName="${countForFileName}"
235
+ mv "${FQICONSDIR}/${sopInstanceUID}.jpg" "${FQICONSDIR}/${baseForFileName}.jpg"
236
+ fi
237
+ if [ "${INCLUDEREPORT}" = "no" ]
238
+ then
239
+ echo "<td align=\"center\"><img src=\"${ICONSDIR}/${baseForFileName}.jpg\" alt=\"NONE\"${SHORTAGTERMINATOR}></td>" >>"${FQHTMLFILE}"
240
+ else
241
+ fileName=`echo "${row}" | sed -e 's/^[^ ]*[ ]*\(.*\)$/\1/'`
242
+ #echo 1>&2 "Got fileName = ${fileName}"
243
+ report="${baseForFileName}.txt"
244
+ if [ -z "${firstfile}" ]
245
+ then
246
+ dcdump "$fileName" 2>&1 | grep -v 'Warning - Overriding UN With Dictionary VR' >"${FQREPORTSDIR}/${report}"
247
+ firstfile="$fileName"
248
+ else
249
+ dcdiff "${firstfile}" "$fileName" >"${FQREPORTSDIR}/${report}" 2>&1
250
+ fi
251
+ #echo "${whichuniquesubkey}: <td align=\"center\"><a href=\"${REPORTSDIR}/${report}\"><img src=\"${ICONSDIR}/${baseForFileName}.jpg\"${SHORTAGTERMINATOR}></a></td>" >>"${FQHTMLFILE}"
252
+ echo "<td align=\"center\"><a href=\"javascript:void(0)\" onclick=\"window.open('${REPORTSDIR}/${report}')\"><img src=\"${ICONSDIR}/${baseForFileName}.jpg\" alt=\"NONE\"${SHORTAGTERMINATOR}></a></td>" >>"${FQHTMLFILE}"
253
+ fi
254
+ fi
255
+ count=`expr ${count} + 1`
256
+ countForFileName=`expr ${countForFileName} + 1`
257
+ done
258
+ echo >>"${FQHTMLFILE}" "</tr>"
259
+ rm -f "${CURRENTPOSITIONFILES}"
260
+ rm -f "${ROWFILE}"
261
+ done
262
+ echo >>"${FQHTMLFILE}" "</table></body></html>"
263
+
264
+ rm -f "${UNIQUESUBKEYS}"
265
+ rm -f "${PARAMETERSBYFILE}"
266
+ rm -f "${SORTEDBYPOSITION}"
267
+ rm -f "${POSITIONLIST}"
268
+
269
+ if [ "${USESTYLESHEET}" = "yes" ]
270
+ then
271
+ cat <<EOF >"${FQSTYLESHEET}"
272
+ body {
273
+ color: lavender;
274
+ background-color: #000000;
275
+ text-decoration: none;
276
+ font-family: Arial, sans-serif;
277
+ font-size: 100%;
278
+ }
279
+
280
+ frame {
281
+ color: lavender;
282
+ background-color: #000000;
283
+ text-decoration: none;
284
+ font-family: Arial, sans-serif;
285
+ font-size: 100%;
286
+ }
287
+
288
+ p {
289
+ }
290
+
291
+ table {
292
+ border: 0px solid;
293
+ border-color: lavender;
294
+ }
295
+
296
+ th {
297
+ border: 1px solid;
298
+ padding-left: 2px;
299
+ padding-right: 2px;
300
+ border-color: feldspar;
301
+ }
302
+
303
+ td {
304
+ border: 1px solid;
305
+ padding-left: 0px;
306
+ padding-right: 0px;
307
+ border-color: feldspar;
308
+ }
309
+
310
+ a:link {
311
+ /* Applies to all unvisited links */
312
+ text-decoration: none;
313
+ color: black;
314
+ }
315
+
316
+ a:visited {
317
+ /* Applies to all visited links */
318
+ text-decoration: none;
319
+ color: black;
320
+ }
321
+
322
+ a:hover {
323
+ /* Applies to links under the pointer */
324
+ text-decoration: none;
325
+ background-color: lavender;
326
+ color: dimgray;
327
+ }
328
+
329
+ a:active {
330
+ /* Applies to activated links */
331
+ text-decoration: none;
332
+ color: black;
333
+ }
334
+
335
+ .centered {
336
+ text-align: center;
337
+ }
338
+ EOF
339
+ fi
340
+