Revision: 85ea974db806
Branch: default
Author: Aditya Panchal <
apan...@bastula.org>
Date: Tue Jul 15 20:41:50 2014 UTC
Log: Updated wiki pages to reflect dicompyler 0.4.2 release.
http://code.google.com/p/dicompyler/source/detail?r=85ea974db806&repo=wiki
Modified:
/BuildRequirements.wiki
/News.wiki
/PluginDevelopmentGuide.wiki
/ReleaseNotes.wiki
/Roadmap.wiki
=======================================
--- /BuildRequirements.wiki Wed Sep 25 02:58:16 2013 UTC
+++ /BuildRequirements.wiki Tue Jul 15 20:41:50 2014 UTC
@@ -18,12 +18,12 @@
* Does NOT work on the system Python 2.6 on Mac OS X Snow Leopard due
to wxPython not being compatible
* Use the command python2.5 to run
* Install packages with easy_install-2.5
- * [
http://www.wxpython.org wxPython] 2.8 (2.9 is not supported yet)
- * [
http://www.pythonware.com/products/pil/ Python Imaging Library] (PIL)
1.1.7 or higher
+ * [
http://www.wxpython.org wxPython] 2.8.8.1 to 2.8.10.1 (2.9 is not
supported yet)
+ * [
http://www.pythonware.com/products/pil/ Python Imaging Library] (PIL)
1.1.7 or higher or any version of
[
https://pillow.readthedocs.org/en/latest/ Pillow]
* [
http://github.com/simplejson/simplejson simplejson] (*ONLY for Python
2.5* - Python 2.6+ includes JSON support)
*Scientific requirements:*
- * [
http://code.google.com/p/pydicom/ pydicom] 0.9.5 or higher
+ * [
http://code.google.com/p/pydicom/ pydicom] 0.9.5 or 0.9.6
* *IMPORTANT*: Currently pydicom 0.9.7 does not work due to the way
Decimal data is handled -
[
https://groups.google.com/d/topic/dicompyler/QxqJPESN8WA/discussion more
information]
* [
http://www.scipy.org/Download NumPy] 1.2.1 or higher
* [
http://matplotlib.sourceforge.net matplotlib] 0.99 to 1.1 (not 1.2 or
higher)
=======================================
--- /News.wiki Tue Sep 24 15:55:46 2013 UTC
+++ /News.wiki Tue Jul 15 20:41:50 2014 UTC
@@ -1,6 +1,12 @@
#summary dicompyler News Archive
#labels Featured
+===January 1st, 2012 - dicompyler 0.4.1-1 Released===
+
+*Important*: Please download dicompyler 0.4.1-1 since an important bug has
been fixed which may have stopped dicompyler from running.
+
+For additional changes, including the original changes from version 0.4.1,
please see the [
http://code.google.com/p/dicompyler/wiki/ReleaseNotes
release notes].
+
==December 31st, 2011 - dicompyler 0.4.1 Released==
* New features:
=======================================
--- /PluginDevelopmentGuide.wiki Sat Apr 23 04:53:55 2011 UTC
+++ /PluginDevelopmentGuide.wiki Tue Jul 15 20:41:50 2014 UTC
@@ -9,10 +9,14 @@
== Types of Plugins ==
-As of dicompyler version 0.4, plugins can be one of the following types:
+Plugins can be one of the following types:
* A *notebook tab plugin* which gets loaded as part of the main
interface. _Example:
[
http://wiki.dicompyler.googlecode.com/hg/images/0.3/2dview_mac.png 2D
View]_
* A *menu item plugin* which is executed from the Tools menu. _Example:
Dose Scaling_ available from the plugin repository.
* An *export menu plugin* is a just a special version of a menu plugin
which exports the loaded DICOM data to a particular format or destination.
_Example:
[
http://wiki.dicompyler.googlecode.com/hg/images/0.2/anonymize_mac.png
Anonymization]_
+*New in dicompyler version 0.4.2*:
+ * An *import plugin* which is executed from the File -> Import menu. The
`'patient.updated.raw_data'` message must be sent by this plugin. _Example:
Quick DICOM Import_ which is included with dicompyler.
+ * A *2D View plugin* which is executed from the 2D View _Tools_ Toolbar
icon. The plugin performs similarly to an *export menu* plugin but is
launched from the 2D View Tools item. _Example:
[PluginDevelopmentGuide#2D_View_Plugin_Example Measurement Plugin].
+
== Plugin Lifecycle ==
@@ -60,6 +64,27 @@
|| `'structures.checked'` || Python dictionary of structures that have
been checked, listed by structure id (integer) ||
|| `'structures.selected'` || Python dictionary of structure that has been
selected with key of `id` ||
|| `'isodoses.checked'` || Python dictionary of isodoses that have been
checked, listed by isodose level (integer) ||
+
+*New in dicompyler version 0.4.2* - Additional messages and data sent for
2D View plugins:
+
+|| *Message* || *Data* ||
+|| `'2dview.updated.image'` || Python dictionary of current image number
and various properties ||
+|| `'2dview.mousedown'` || Python dictionary mouse coordinates in pixel
and mm representation: `x`, `y`, `xmm`, `ymm`||
+
+The dictionary data sent by the `'2dview.updated.image'` message is as
follows:
+
+{{{
+{'number':self.imagenum, # slice number
+ 'z':self.z, # slice location
+ 'window':self.window, # current window value
+ 'level':self.level, # curent level value
+ 'gc':gc, # wx.GraphicsContext
+ 'scale':self.zoom, # current zoom level
+ 'transx':transx, # current x translation
+ 'transy':transy, # current y translation
+ 'imdata':imdata, # image data dictionary
+ 'patientpixlut':self.structurepixlut} # pat to pixel coordinate LUT
+}}}
= Examples =
@@ -230,6 +255,147 @@
dirdlg.Destroy()
}}}
+
+== 2D View Plugin Example ==
+
+This *2D View* plugin allows the user to measure distances on the 2D View.
The only requirements for this plugin are image files. When the menu item
is clicked, The user can click two points on the image and it will then
draw a line between the points and display the measurement. If the user
clicks the menu item again, they will be able to perform another
measurement.
+
+Note: For a 2D View plugin, just like a menu plugin, there is no
pluginLoader function, but instead there is a pluginMenu class method.
There are also two functions that are called when either the image changes
or the mouse button is clicked.
+
+{{{
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# distance.py
+"""dicompyler plugin that calculates the distance between two points."""
+# Copyright (c) 2014 Aditya Panchal
+
+import wx
+from wx.lib.pubsub import Publisher as pub
+from math import sqrt
+
+
+def pluginProperties():
+ """Properties of the plugin."""
+
+ props = {}
+ props['name'] = 'Measure Distance'
+ props['description'] = "Measures the distance between two points"
+ props['author'] = 'Aditya Panchal'
+ props['version'] = '0.4.2'
+ props['plugin_type'] = '2dview'
+ props['plugin_version'] = 1
+ props['min_dicom'] = ['images']
+ props['recommended_dicom'] = ['images']
+
+ return props
+
+
+class plugin:
+
+ def __init__(self, parent):
+
+ self.parent = parent
+
+ # Set up pubsub
+ pub.subscribe(self.OnUpdateImage, '2dview.updated.image')
+ pub.subscribe(self.OnMouseDown, '2dview.mousedown')
+
+ # Plugin is not ready to measure until the menu has been launched
+ self.start_measuring = False
+
+ def pluginMenu(self, evt):
+ """Start the measure distance plugin."""
+
+ # Set up variables
+ self.point_one = None
+ self.point_two = None
+ self.start_measuring = True
+ self.z = 0
+
+ # Refresh the 2D display to get the latest image data
+ self.parent.Refresh()
+
+ def OnUpdateImage(self, msg):
+ """Update and load the image data."""
+
+ if self.start_measuring:
+ # Get the image data when the 2D view is updated
+ self.imagedata = msg.data
+ self.gc = self.imagedata['gc']
+ self.gc.Scale(self.imagedata['scale'], self.imagedata['scale'])
+ self.gc.Translate(self.imagedata['transx'],
+ self.imagedata['transy'])
+ self.DrawMeasurement()
+
+ def OnMouseDown(self, msg):
+ """Get the cursor position when the left mouse button is
clicked."""
+
+ # Make sure that we are measuring
+ # This only occurs after the plugin has been launched via the menu
+ if self.start_measuring:
+
+ # Get the mouse cursor position point
+ point = msg.data
+
+ if (self.point_one is None):
+ self.point_one = point
+ # Record the z plane of the first point
+ self.z = self.imagedata['number'] - 1
+ elif (self.point_two is None):
+ # Make sure that the second point is on the same z plane
+ if (self.z == self.imagedata['number'] - 1):
+ self.point_two = point
+ # Measure the distance between the two points
+ self.MeasureDistance()
+ # Otherwise re-obtain first point since this is a new z
plane
+ else:
+ # Record the z plane of the first point
+ self.z = self.imagedata['number'] - 1
+ self.point_one = point
+
+ def MeasureDistance(self):
+ """Measure the distance between the two points."""
+
+ # Get the differences between the two points
+ px = self.point_one['xmm'] - self.point_two['xmm']
+ py = self.point_one['ymm'] - self.point_two['ymm']
+
+ # Calculate the distance
+ # Distance is reported in mm so convert to cm
+ self.dist_cm = sqrt((px) ** 2 + (py) ** 2) * 0.1
+
+ # Refresh the 2D display to draw the measured distance
+ self.parent.Refresh()
+
+ def DrawMeasurement(self):
+ """Draws the measurement line."""
+
+ # Make sure that the second point has been clicked
+ if not (self.point_two is None):
+
+ # If the slice number doesn't match the z plane
+ # don't draw the measurement line
+ if not (self.z == self.imagedata['number'] - 1):
+ return
+
+ # Set the color of the line
+ c = wx.Colour(255, 0, 0)
+ self.gc.SetBrush(wx.Brush(c, style=wx.TRANSPARENT))
+ self.gc.SetPen(wx.Pen(c, style=wx.SOLID))
+
+ # Create the drawing path for the measurement line
+ path = self.gc.CreatePath()
+ # Draw the measurement line
+ path.MoveToPoint((self.point_one['x'], self.point_one['y']))
+ path.AddLineToPoint((self.point_two['x'], self.point_two['y']))
+ # Close the subpath
+ path.CloseSubpath()
+ # Draw the final path
+ self.gc.DrawPath(path)
+ # Draw the measurement distance text
+ self.gc.DrawText('%.2f' % self.dist_cm + ' cm',
+ self.point_two['x'] + 2, self.point_two['y']
+ 2)
+}}}
= Additional Notes =
@@ -248,6 +414,21 @@
* `props['plugin_type']` is specified as `'export'` so dicompyler
understands to place it under the Export menu
* `props[menuname]` is the title of the menu so that it flows smoothly
in English with the prefix `'Export'`, i.e. if your plugin exported XML
data as above, the menuname should be `"as XML"`
+== Import Menu Plugins ==
+
+Import menu plugins allow data to be imported from various sources. As
long as the data is converted to a series of raw pydicom objects, it can be
used within dicompyler. A dictionary of objects following the
`'patient.updated.raw_data'` message standard must be sent via pubsub.
dicompyler will automatically receive this message and load the appropriate
plugins.
+
+The only other changes required for an export menu plugin is to add the
following lines to your `pluginProperties` dictionary:
+
+{{{
+props['plugin_type'] = 'import'
+props['menuname'] = "DVH Text File..."
+}}}
+
+where:
+ * `props['plugin_type']` is specified as `'import'` so dicompyler
understands to place it under the Import menu
+ * `props[menuname]` is the title of the menu so that it flows smoothly
in English with the prefix `'Import'`, i.e. if your plugin imported DVH
Text files as above, the menuname should be `"DVH Text File..."`
+
== dicompyler Plugin Repository ==
If you feel that your plugin is worthy of sharing, consider submitting it
to the [
http://code.google.com/p/dicompyler-plugins/ dicompyler Plugin
Repository]. You can have your plugin hosted for free, include a wiki for
your plugin, and it can be listed within the dicompyler plugin browser for
all users to see.
=======================================
--- /ReleaseNotes.wiki Sun Jan 1 20:16:54 2012 UTC
+++ /ReleaseNotes.wiki Tue Jul 15 20:41:50 2014 UTC
@@ -3,6 +3,33 @@
====For detailed change information, check out the
[
http://code.google.com/p/dicompyler/source/list source code] for further
information.====
+= Version 0.4.2 - Released July 15th, 2014=
+
+ * New Features
+ * Added Quick DICOM Import feature.
+ * Added Import plugin capability with toolbar icon support.
+ * Plugins can now access the 2D View drawing canvas.
+ * Refactored plugin manager to allow enabling/disabling of plugins.
+ * DICOM data can now be loaded via command line argument or dragging
and dropping a folder on the dicompyler icon on the Windows version.
+ * Added persistence of the window size and position.
+ * Added support to determine Rx Dose from RT Plan Fractionation
information. [
http://code.google.com/p/dicompyler/issues/detail?id=48 Issue
48]
+ * Display Rx Dose in the DICOM import window before importing.
[
http://code.google.com/p/dicompyler/issues/detail?id=48 Issue 48]
+ * Added support for DICOM files that don't include the
StudyInstanceUID tag.
+ * Added support for DICOM RT Dose files without dose grid data and/or
DVH data. [
http://code.google.com/p/dicompyler/issues/detail?id=35 Issue 35]
+ * Added support for DICOM RT Dose files that contain dose for an
individual beam. [
http://code.google.com/p/dicompyler/issues/detail?id=44
Issue 44]
+
+ * Bug Fixes
+ * Fixed a bug in the 2D View where the mouse might be clicked too
early after opening a patient.
[
http://code.google.com/p/dicompyler/issues/detail?id=62 Issue 62]
+ * Fixed a bug where a DVH may be found without a corresponding
structure, rendering the DVH unusable.
[
http://code.google.com/p/dicompyler/issues/detail?id=61 Issue 61]
+ * Fixed a bug where a forward slash might be used to encode the ROI
display color in an RT Structure Set.
[
http://code.google.com/p/dicompyler/issues/detail?id=64 Issue 64]
+ * Support encoded character sets in DICOM files. This addresses the
UnicodeDecodeError from occurring in the treeview plugin.
[
http://code.google.com/p/dicompyler/issues/detail?id=69 Issue 69]
+ * Implement sensible defaults for demographics in case they don't
exist. [
http://code.google.com/p/dicompyler/issues/detail?id=71 Issue 71]
+ * Fixed a bug where structures may be listed out of order if many
structures exist. [
http://code.google.com/p/dicompyler/issues/detail?id=66
Issue 66]
+ * Fixed a bug in the 2D View where the image number was incorrect when
loading a single image.
+ * Fixed a bug where it was possible to start multiple directory search
threads in the DICOM import window.
+ * Fixed a bug where an index might be out of bounds when obtaining a
dose grid slice. [
http://code.google.com/p/dicompyler/issues/detail?id=63
Issue 63]
+ * Fixed a bug where structure set contours may not display if contour
data is not exactly coincident with image data.
[
http://code.google.com/p/dicompyler/issues/detail?id=77 Issue 77]
+
= Version 0.4.1-1 - Released January 1st, 2012=
* General
=======================================
--- /Roadmap.wiki Sun Jan 1 02:59:03 2012 UTC
+++ /Roadmap.wiki Tue Jul 15 20:41:50 2014 UTC
@@ -67,7 +67,7 @@
* Preferences for each plugin
== Version 0.4.1 ==
-*Released*: December 31st, 2011
(*[
http://code.google.com/p/dicompyler/downloads/list Download now]*)
+*Released*: December 31st, 2011
*Features*:
* Refactored into a [
http://pypi.python.org/pypi/dicompyler Python
package]
@@ -77,20 +77,26 @@
* Support DICOM-RT Ion Plans
== Version 0.4.2 ==
-*Release*: Winter/Spring 2012
+*Release*: July 15th, 2014
(*[
http://code.google.com/p/dicompyler/downloads/list Download now]*)
*Features*:
- * Auto-updater for binary versions
+ * Added Quick DICOM Import plugin
+ * Plugins can now access the 2D View drawing canvas
* Advanced Plugin Manager
* Can enable/disable plugins
- * Plugin preferences
- * Download plugins from dicompyler plugin repository
+ * DICOM data can now be loaded via command line argument or dragging and
dropping a folder on the dicompyler icon on the Windows version
+ * Added persistence of the window size and position
+ * Many bug fixes
== Version 0.5 ==
*Release*: Future, TBD
*Features*:
- * Debug console
+ * Auto-updater for binary versions
+ * Auto-updater for binary versions
+ * Advanced Plugin Manager
+ * Can enable/disable plugins
+ * Download plugins from dicompyler plugin repository
* Structure interpolation
* 3-pane 2D Image viewer (transverse, sagittal, coronal)
* Editing of all DICOM fields