Visualise fluoroscopic dose distribution

Issue #61 resolved
Ed McDonagh created an issue

Probably on a rotatable cylindrical model

Comments (310)

  1. David Platten

    Added calculation of skin dose map data to the rf detailed view. The data is returned to the template as a new variable called skinmap. References issue #61

    → <<cset e970bde114ed>>

  2. David Platten

    Updated code to check that certain fields have a value before trying to calculate the dose from a view. Do I need to check all of these? Should they be set to None or 0 if a value isn't found? The python and JavaScript code is hard-written for a 70 x 90 skin dose map at the moment: needs to be made more general. References issue #61

    → <<cset 5a9aebba89a3>>

  3. Ed McDonagh reporter

    Nice!

    Would min/max be more intuitive than level/width? I think my main two views would be 0 to max and 0 to xGy where x would be the same for a range of scans that I wanted to compare. Maybe a preference I could set somewhere. I think both of these would be trickier to manually set with level/width as I'd have to do some mental arithmetic!

  4. Ed McDonagh reporter

    That's pretty. But I still think min/max slider bars make more sense. Particularly as I now understand the min/max dose below the diagram represents the min/mas in the image, not the min/max of the scale, and because the scale can go negative.

  5. David Platten

    Done:

    • Calculate the skin dose map during import of each study, as an admin option
    • Make calculation of skin dose map happen via AJAX
      • Would be better to show the pending graphic in the skin map div
    • Decide on what controls the user should have (window/level or max/min)
      • User can interactively switch between one or the other
    • Store the calculated data somewhere so that it can be retrieved almost instantly if the map is viewed again
      • Create a folder called skin_maps inside MEDIA_ROOT?
      • Use the pk as the basis of a filename (skin_map_pkValue.p)
      • Use pickle to store variable data in a file
    • Enable a choice of colour scales
    • Remove use of skinDose JavaScript variable
    • Display the dose at the mouse cursor in a tooltip by the mouse pointer
    • Encapsulate the skin dose map JavaScript code into an object. This will remove the need for the messy global variables
    • Enable viewing of a 3D representation of the skin dose map using three.js
    • 3d skin map should be put into an object to tidy it up
    • 3d skin map calculations currently hard-written to specific phantom dimensions: need to be made generic
      • New object code can accept custom dimensions
    • 3d skin map now showing data in the correct place around the phantom - adjusting array by half of flat front width
    • Enable saving of the displayed skin dose map as a graphic
    • Label the skin dose map to show which part is front, back, left and right of patient
      • 3d skin dose map now has a mini-person to orientate the user
      • 2d skin dose map now labelled with an overlay
    • Decide on what numerical values should be displayed (dose at cursor; max dose of whole map etc)
    • Display phantom details (height, width, depth)
    • Display patient values used (height and weight)
    • Add a full-screen button similar to the one for the charts
  6. Ed McDonagh reporter

    It would be good if the storing of calculated data and the check to see if is there before recalculating it could be done in a standard way such that we could have jobs running on Celery to do them in the background if desired.

    I would suggest the data is stored in a folder in MEDIA_ROOT.

  7. David Platten

    Added max and min displayed dose values to the skin dose map. These are in addition to the existing window and level controls. Changing any of them updates the display of the skin dose map, and also updates the other sliders as appropriate. The live version will only display one set of sliders: either the max / min dose, or the window / level ones. References issue #61

    → <<cset d56c9d178724>>

  8. David Platten

    Updated JavaScript code to prevent min dose slider from having a larger value than the max dose slider. Also updated to prevent the max dose slider from having a value less than the min dose slider. References issue #61

    → <<cset 9c1223462121>>

  9. David Platten

    Skin map controls are now either min/max or window width/level, and can be swapped from one to the other using a button. Also formatted buttons to match the rest of the site. References issue #61

    → <<cset f732df4ecc70>>

  10. David Platten

    Not sure: the output is just what OpenSkin spits out from a standard sized 3D phantom. I'm not sure which part of the image equates to left, front, right and back.

  11. David Platten

    Visualising the flat image in 3D terms is tricky - it's where the 3D visualisation comes in...

  12. David Platten

    Included skin map width and height in json return. Changed hard-written dimensions in JavaScript code to use mag, skin map width and height instead. Will add control to change mag at some point. References issue #61

    → <<cset 5600949027eb>>

  13. Jonathan Cole

    The left and right bits are because the map is like slicing down the sternum and peeling the skin off flat.

    I have had a bit of a crack at the 3D stuff but haven't had time recently.

    David, is it possible to change the colour map to something else? I am not a fan of this one.

  14. Jonathan Cole

    Any of the sequential Brewer scales would be fine. If users can change it that clears up most of my concerns.

  15. David Platten

    Skin dose map data is now stored as a pickle in a skin_maps sub-folder of MEDIA_ROOT. Before the calculation of a skin map this folder is checked to see if there is a pickle file in the folder corresponding to the current study. If there is, the data in the pickle is loaded rather than recalculating the skin dose map. I've used cPickle rather than pickle, as apparently it is much faster (http://wiki.python.org/moin/UsingPickle). I've also added a line of JavaScript to resize the dose scale to the height of the displayed skin dose map. References issue #61

    It's likely that when I get around to the 3D visualisation of the dose maps that I'll need to store a few more things in the pickle, such as the 3D phantom height, width and depth.

    → <<cset 8b9f2a5cf430>>

  16. David Platten

    Now calculating min and max dose of skin map from as this is a much smaller array than . Calculating from the magnified array was causing memory problems. References issue #61

    → <<cset 9a5aeb330043>>

  17. David Platten

    Now using slider max and min values when resetting the controls. Calculating from the magnified array was causing memory problems. References issue #61

    → <<cset 4a22a4a5fcc3>>

  18. David Platten

    Put a border around the skin dose map that matches the border around the tabulated data. Increased the width of the dose scale. References issue #61

    → <<cset f45f5d2774d7>>

  19. David Platten

    Added the width of the flat part of the phantom and the distance around the curved edge to the 3D phantom properties. These will be useful when splitting the totalDose array into front, back, left and right parts for 3D display. References issue #61

    → <<cset 26bcabb6663b>>

  20. David Platten

    Skin dose maps now make use of new JavaScript objects: one for the skin dose map, and the other for the colour scale. These make the code cleaner, with newer global variables. Also updated the style of the colour scale selection div. References issue #61

    → <<cset 518a5c1d0444>>

  21. David Platten

    Corrected a couple of errors in the JavaScript code; reduced the number of decimal places used for total skin dose; changed Scanner to Equipment on the rfdetail.html page. References issue #61

    → <<cset b8e43397f2bf>>

  22. David Platten

    I need to remove the calls that redraw the skin map and colour scale: at the moment the map is being redrawn multiple times with every change.

  23. David Platten

    Not yet: Jon replied to me on the OpenSkin site yesterday with some comments about that, but I haven't read them properly yet. I think that the color scale clubs needs a cull too.

  24. David Platten

    Added a 3D view of a skin dose map as a proof-of-concept (using four fixed png files, not the specific skin dose map being viewed). References issue #61

    → <<cset 95e7af159a5c>>

  25. David Platten

    Removed reverse colour scale property (was considering allowing the user to reverse their selected colour scale, but have decided against it). References issue #61.

    → <<cset 07dab3225924>>

  26. David Platten

    Used numpy roll to adjust the 3d skin dose map data for the split front portion. 3d map should now be correctly orientated. References issue #61

    → <<cset c4795419d14f>>

  27. Jonathan Cole

    That looks great!

    Are you handling different sized patients or do you want me to expose the dimensions of the phantom still?

  28. David Platten

    Hi @jacole. It should handle different sized patients already, although none of my data contains that information.

  29. David Platten

    I don't know if there's any account for a prone vs. supine patient when a study is imported into OpenREM - a good point. @edmcdonagh would be the person to answer that...

  30. Ed McDonagh reporter

    Does that bump in his face represent a nose?

    I'll take a look at the patient orientation.

  31. David Platten

    Added stylised person to orientate the user when viewing the 3d skin dose map. I'd prefer that it was displayed in the bottom-left corner, rather than the top-left, but can't work out the css for that at the moment. References issue #61

    → <<cset 3c9670089f98>>

  32. David Platten

    Changed the material used for the ends of the 3d phantom and added a light source to illumunate them. Adjusted the brightness of the light source for the person. References issue #61

    → <<cset 20ebf7b76231>>

  33. Ed McDonagh reporter

    Looking at a Siemens RDSR, the patent orientation is not in any official field, just tucked away in a comment field right at the end.

  34. Ed McDonagh reporter

    Toshiba do log this information on an exposure-by-exposure basis, as per TID 10003. This goes into the IrradEventXrayData model:

        patient_table_relationship_cid = models.ForeignKey(
            ContextID, blank=True, null=True, related_name='tid10003_pttablerel')  # CID 21
        patient_orientation_cid = models.ForeignKey(
            ContextID, blank=True, null=True, related_name='tid10003_ptorientation')  # CID 19
        patient_orientation_modifier_cid = models.ForeignKey(
            ContextID, blank=True, null=True, related_name='tid10003_ptorientationmod')  # CID 20
    

    On a sample of one of each, Toshiba seem to populate the orientation (erect, recumbant, semi-erect) and orientation_modifier (prone, supine etc), but not the table relationship (ie where the patient is relative to the head of the table). Siemens don't populate these fields.

  35. Ed McDonagh reporter

    I've been trying and failing to find a method of anonymising a decent fluoro RDSR, including times in all the sequences etc.

    So instead I've pulled the code locally to see what it looks like; unfortunately the patient size being present has made it fall over :-(

    Traceback (most recent call last):
      File "/home/mcdonaghe/research/veOpenREM/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "/home/mcdonaghe/research/veOpenREM/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 22, in _wrapped_view
        return view_func(request, *args, **kwargs)
      File "/home/mcdonaghe/research/bbOpenREM/openrem/remapp/views.py", line 515, in rf_detail_view_skin_map
        matt_thick=4.0, matt_trans=0.75)
      File "/home/mcdonaghe/research/bbOpenREM/openrem/remapp/tools/openskin/calc_exp_map.py", line 37, in __init__
        self.phantom = geomclass.Phantom_3([0, -25, -self.matt_thick], mass=self.pat_mass, height=self.pat_height)
      File "/home/mcdonaghe/research/bbOpenREM/openrem/remapp/tools/openskin/geomclass.py", line 155, in __init__
        torso = refTorso * height / refHeight
    TypeError: unsupported operand type(s) for *: 'float' and 'Decimal'
    
  36. Ed McDonagh reporter

    I've now tried displaying some studies that don't have patient size included, and whilst the 2D version displays (on a simple study at least), I've not managed to get the 3D version.

    Is it likely to be a memory or processing issue? Might it be that I'm just using SQLite/runserver?

  37. David Platten

    Preventing page from scrolling when mouse wheel is used over the 3d skin dose map. Makes zooming in and out of the map easier. References issue #61

    → <<cset fb7b3b7a210d>>

  38. David Platten

    @edmcdonagh, commit 41576a3 should have sorted out the problem that you had with skin maps failing when patient height and mass were present.

  39. David Platten

    Added styles to the range sliders; replaced hard-written dimensions with whatever the current skin dose map has; Update the size of the skinDoseMapGroup div according to the size of the current skin dose map. I've just noticed that the range sliders don't appear in Internet Explorer or Edge (whether they're styled or not) - need to find out why. References issue #61

    → <<cset b70b955d21e5>>

  40. David Platten

    Added overlay to the 2d skin dose map that will orientate the user. The display of this overlap can be toggled on and off by the user. The overlay contains a little text at the moment, but also needs to have some lines drawn on to illustrate the boundaries between anterior, left, posterior, right and anterior. References issue #61

    → <<cset cac8229dd113>>

  41. David Platten

    Latest updates on the DJP site. I'd like comments on what users (and developers - @edmcdonagh and @jacole) would like displayed on the overlay. I think I'm going to fix the colours used in the overlay, rather than have it follow the colour of the skin dose map colour scale. Thoughts on suitable colours would also be welcome.

  42. Ed McDonagh reporter

    It's looking really good! Only looked on my phone (away, with no laptop aaaarrrrrgggghhhh!). Labels were hard to see in grey, easier when the dose map was in colour and the labels stayed grey.

    Couple of things that don't help to answer your request - save to png doesn't show the overlay or the little man; and the new scale widgets don't show on Chrome on Android, but as discussed previously that is a niche use case!

  43. Ed McDonagh reporter

    Is using black except when greyscale an option? Or fix a colour for all, but use a font outline effect to ensure contrast?

  44. David Platten

    Removed need for a second (rotated) copy of the skin dose map array for the 3d object. This halves the storage requirement (the pickle files are half thier size if there's only one skin dose map array). I've also shifted the skin dose map by half the flat front width, so that it now displays from left to right as front, left, back, right. This enables the overlay to be simplified. Anyone testing this themselves will need to delete their existing pickle files from their MEDIA_ROOT folder as the new code creates a different data file. References issue #61.

    → <<cset dbfc2459b5ce>>

  45. Jonathan Cole

    Wow, it is looking really good.

    I'd like to be able to set maximum doses higher than the maximum in the image so it is possible to do a comparison between two patients. Is this a change that would be useful for other people or would it be better as a local change on my copy when I get a chance to reinstall?

  46. David Platten

    Enabled the user to manually set any max and min dose levels: they can be typed into the boxes that show the current max and min dose values. References issue #61.

    → <<cset e14dd0d3e6d5>>

  47. David Platten

    @jacole, it's now possible to manually type a min and max displayed dose value in so that you can set the values to exactly what you want.

  48. David Platten

    Hi @edmcdonagh, Would you like the save button for the 3d map to include the little man, and the 2d map save to include the overlay?

  49. David Platten

    Overlay is now saved if it is being displayed when the user clicks on the save button. Hopefully Ed will like this. I'll take a look at including the orientation man on the 3d map at some point. It also references issue #61

    → <<cset 1615be391423>>

  50. David Platten

    3d skin dose map and orientation person now drawn on the same canvas. This means that the orientation man is included in the png when saved. It also means that there is only one 3d render, which is apparently a good thing. References issue #61

    → <<cset f21e4d7d31db>>

  51. David Platten

    Prevent an error if the skin dose map was unsuccessful. This was failing for a bi-plane Toshiba study where there was no value available for d_ref. References issue #61

    → <<cset 65345a14c9bb>>

  52. David Platten

    @JLMPO, do you know what the reference distance is that Toshiba use for the skin doses reported from your bi-plane system?

  53. David Platten

    Added new <div> to display peak skin dose, phantom dimensions and patient height and mass. Not in it's final position yet. Added more information to the saved pickle, so any existing pickle files will need to be deleted. References issue #61

    → <<cset 0ea40ed1c487>>

  54. David Platten

    Adjusted appearence of peak dose, phantom size and patient height and mass data. Now automatically adjusting the number of decimal places used to display skin dose values. Switched the skin dose values to the right of the colour scale to avoid lots of white space between the values and the colour scale when only a few decimal places are shown. References issue #61

    → <<cset fe61ac3a0d41>>

  55. David Platten

    I've done everything on my to-do list for this except for calculating the skin dose maps at the point that a new study arrives in OpenREM.

    Does anyone have any comments on how things currently look? Is there anything you'd like added or changed? The most recent commit is on the DJP demo site.

  56. Ed McDonagh reporter

    I'll try and have a look today. Does it need a comment along the lines of: Indication only: calculations not validated. Contributions welcome, see ... for details

    Also, is @jacole happy that the code is distributed within OpenREM rather than being submitted to PyPI as OpenSkin and then pulled in?

    Does the current view mention OpenSkin (I should really just look - sorry! I'm about to lose signal on the train!)

  57. Jonathan Cole

    OpenSkin is GPL'd so as long as you keep the copyright notice use it how you like.

    Let me know if you need it relicensed in any way.

  58. Ed McDonagh reporter

    Thanks @jacole. I guess the question is more about how you want your codebase and @dplatten's version to be maintained? Should they be the same codebase, which would favour pulling in OpenSkin version x from PyPI? Otherwise I guess they'll diverge (which would be a shame in my opinion).

  59. Ed McDonagh reporter

    @dplatten I still can't get it to work with studies with patient size information. And I don't see any useful error messages either, either with the inspection tools or at the server logs.

    As proper anonymisation of these studies is so difficult, would you be able to add height and weight into some of your data to see if you can replicate the issue?

    Otherwise, with the restriction that I can't use the 3D version on my VM due to lack of working WebGL, its looking really good 😄

  60. David Platten

    OK @edmcdonagh. I've just added a patient_size and patient_weight to a study in the patientstudymoduleattr table. I used 155 for the size, and 66 for the weight. The resulting skin dose map worked perfectly...

    Should patient size be stored as cm or m in the database?

  61. David Platten

    I think I've answered my own question: the height is stored in m. This may be why it's not working for you, as OpenSkin expects height in cm... Sorting out the issue now (multiplying the stored height by 100).

  62. David Platten

    Patient height (patient_size) is stored in the database in m, so need to multiply this value by 100 before passing it on to OpenSkin, as this needs the height in cm. References issue #61 and hopefully fixes the issue that Ed was having with the skin dose maps displaying.

    → <<cset 9c0b60011b46>>

  63. David Platten

    Fixed problem where skin dose map group canvas wasn't resizing for different sized skin dose maps. Also added code to reset the rotation and zoom of the 3d skin dose map when the reset button is clicked. References issue #61

    → <<cset dc2832f9828a>>

  64. David Platten

    @edmcdonagh, I'd like to make Celery calculate the skin dose map data at the point that a new fluoroscopy study is sent to OpenREM. I'm not sure about how to do this: can you give me any pointers?

  65. Ed McDonagh reporter

    Love to :-)

    from celery import shared_task
    
    @shared_task(name='remapp.tools.openskin.CalcExpMap')
    class CalcExpMap(object):  # or which ever function it is...
    

    Then at the end of the _rsdr2db function in rdsr.py

        CalcExpMap.delay(stuff)
        # After importing it of course, and switching it for whichever is the right function.
    
  66. Ed McDonagh reporter

    How would you feel @dplatten about rolling this into develop for the next beta? I want to get it out soon, so that the people who are wanting to use mammo RDSR can do so, but it would be great to drop this in too!

  67. David Platten

    Hi @edmcdonagh. That is fine with me, but I do have some concerns:

    • It's not well-tested across systems (my Siemens Artis Zee data works well)
    • It fails with the test RDSR that @JLMPO send to me from a Toshiba system (there is no reference distance in the RDSR, and I don't know what the value should be)
      • Perhaps have a sensible default d_ref, rather than letting it fail?
  68. Ed McDonagh reporter

    Mmm. I'm getting myself confused. The two Tosh CCL RDSRs I have on the laptop, one is a DFP-8000D software v6.01, the other is also a DFP-8000D but software v6.10. Both of them have a Reference Point Definition of the usual 113860/15cm from Isocenter toward Source.

    The Philips RDSR I have, with no model name or software version, though I think it's an Allura, has an unusual RP Definition of '15cm below BeamIsocenter', in text rather than using the coded version. Don't know why, means the same thing.

    What is it that isn't being picked up for OpenSkin?

  69. David Platten

    Hi @edmcdonagh. I've just deleted the bi-plane study that John sent to me (and fixed the problem that gave). I then re-imported it into OpenREM and looked at it in the rfdetail view: no skin map. This is because the distance_source_to_isocentre field in the doserelateddistancemeasurement table are blank. The distance_source_to_reference_point data is also blank.

  70. Ed McDonagh reporter

    I don't have direct access to any, though I could probably look at a single plane system that's linked to one of my installs, with permission.

    I have one single plane and one bi-plane in my samples folder.

  71. David Platten

    OK. Have you tried importing the RDSR that John sent, and if so, does the skin dose map work?

  72. Ed McDonagh reporter

    Both the Tosh studies give me a uniform dose map with infinite peak skin dose.

    The Philips study gives me a peak of 0 Gy

  73. Ed McDonagh reporter

    I'll see if I can find out what the geometry of the Toshiba system is. That isn't the problem for the Philips. Do you have one of those?

  74. David Platten

    Hi @edmcdonagh. I don't have any Philips RDSR files. Perhaps we could put out a request on the mailbase for people to send in a QA RDSR from their fluoro systems?

  75. Ed McDonagh reporter

    I've sent you one. But asking for others isn't a bad idea!

    Meanwhile, do you have a black background when you view the 3D view (any colour scheme)? It makes the text at the top regarding the doses impossible to read. This is from the djp demo, as I don't get the 3D on my laptop VM.

  76. David Platten

    Made skin dose map information text turn white when viewing 3d map so that it remains legible. Made a few tweaks to other html to make it more correct. References issue #61

    → <<cset f77252f91527>>

  77. Ed McDonagh reporter

    I've committed a small change to add Source to Detector Distance to the detail view - not strictly related to this branch, but I was wanting it when I was trying to work out what we know about distances, and thought it should stay. Hope that's ok!

  78. David Platten

    Introduced a skin_map_version to version.py. This is used to check that skin dose map pickle files are compatable with the current version of the skin dose mapping code. I've set the version to 0.7 to begin with. References issue #61

    → <<cset 628f4a1435f5>>

  79. Jonathan Cole

    Just a thought. I've never been able to test openSkin with anything but Siemens as no-one sent me any RDSRs.

    It is entirely possible that the reported geometry uses different reference points which could screw up skin dose calculations. Do we know these RDSRs actually work with openSkin?

  80. Ed McDonagh reporter

    Siemens and Toshiba use the same definition of RP. Philips uses a free text definition instead, which is legal, but means the same as the coded version Siemens and Toshiba use so it's annoying they didn't just use that!

    Sample sizes for the above statements by the way are 2 for Toshiba and 1 for Philips...

  81. Jonathan Cole

    What about the reference for the table position and c-arm angulation? Do we know if these are the same?

  82. Ed McDonagh reporter

    Toshiba uses the standard template for:

    • Positioner Primary Angle
    • Positioner Secondary Angle
    • Table Longitudinal Position
    • Table Lateral Position
    • Table Height Position
    • Table Head Tilt Angle
    • Table Cradle Tilt Angle
    • Patient Orientation
    • Patient Orientation Modifier

    For the angles the orientation and positive direction are defined, but not where 0 is as far as I can see. Similarly the table movement positive direction is defined but the 0 position is arbitary.

    I'll look at Philips later. They seem to have more information but quite a lot of it is using a Philips coding scheme :-(

  83. Ed McDonagh reporter

    Philips Allura

    • 113780 DCM Reference Point Definition Text 15cm below BeamIsocenter
    • 112011 DCM Positioner Primary Angle Numeric Value
    • 112012 DCM Positioner Secondary Angle Numeric Value
    • 113745 DCM Patient Table Relationship F-10470 SRT headfirst
    • 113743 DCM Patient Orientation F-10450 SRT recumbent
    • 113744 DCM Patient Orientation Modifier F-10340 SRT supine
    • 113751 DCM Table Longitudinal Position Numeric Value
    • 113752 DCM Table Lateral Position Numeric Value
    • 113754 DCM Table Head Tilt Angle Numeric Value
    • 113755 DCM Table Horizontal Rotation Angle Numeric Value
    • 113756 DCM Table Cradle Tilt Angle Numeric Value

    Additionally the following are described using 99PHI-IXR-XPER coding scheme rather than DCM or SRT:

    • wedges and shutters
    • beam position/angle
    • table height position
    • final versions of SDD, table cradle angle, table height position
    • detector field size in x and y
    • object thickness!
  84. David Platten

    Switched on anti-aliasing for 3d skin dose map. Moved skin dose map AJAX progress animation to sit within the skin dose map group. References issue #61

    → <<cset 5f5fbcab1de1>>

  85. David Platten

    Fixed an error where skin dose map calculation failed if a filter existed without a material. I have also hidden the skin dose map group and controls until the map is available to view. References issue #61

    → <<cset e8de3456610c>>

  86. David Platten

    I had a look at implementing a celery task to create a skin dose map on import of a new RF study a few minutes ago. However, I'm unclear about where to put the @shared_task, and quite what function this needs to be. Feeling dense. @edmcdonagh, can you offer any more pointers?

  87. Ed McDonagh reporter

    Bother. Didn't reference this issue in commit 4118fb5.

    Objects passed to celery need to be JSON serializable, which is why this isn't working currently.

  88. Ed McDonagh reporter

    Trying to remember how to deal with this. Easiest way is probably to create a new function in remapp.tools.openskin somewhere that becomes the shared task, and takes just the id of the study. Then the call only includes the study id, which then looks up the study, gets the height and weight etc and calls CalcExpMap.

  89. Ed McDonagh reporter

    I think users aught to be able to choose whether OpenSkin maps should be available, and if so whether they should be made automatically (celery) or just on page view.

    Also, what happens if RDSR comes in, OpenSkin job goes into the RabbitMQ queue, then the user loads the detail view of that study before Celery has had a chance to process it. Does overwriting the pickle cause any issues?

    Also (!), I think it would be better/safer/easier to maintain if the function I more-or-less lifted from views into rdsr were just the one function used by both.

  90. David Platten

    Created new tools file that comtains the make_skin_map routine. This single routine is now the only one used to calculate skin dose maps. I've checked that it works when being used to calculate data that's already in the database, but am unable to check that it works for skin dose map calculations that are made when a new study is imported into the system from an RDSR. References issue #61.

    → <<cset 82420cbdf09e>>

  91. David Platten

    @edmcdonagh, are you able to confirm at some point that my revised code successfully calculates a skin dose map and saves a pickle file when a new study is imported from an RDSR file?

  92. David Platten

    Hi @edmcdonagh (and @jacole), the skin dose maps are working well with the Siemens RDSRs that I have in my system. I'm glad that the skin dose maps can now be calculated at the point at which a new study comes into the system. However, neither the Toshiba bi-plane nor Philips Allura RDSR files that I have produce a working skin dose map. At the moment I don't know why: I've tried forcing a sensible default d_ref, but that doesn't work. As I don't have any vested interest in getting the Toshiba or Philips systems to work, I'm not going to spend any further time investigating. However, I am keen that version 0.7 of OpenREM is released in the not-too-distant future. So: what do you think is the best way forward with this?

    I'm happy to take a look at creating an option for skin dose maps to be available, and also whether they should be created on import, or just on study view.

  93. Ed McDonagh reporter

    I'm content that Philips and Toshiba are left for 0.7.1 or later, as long as a sensible message appears instead.

    I'll check the auto processing of RDSRs.

  94. David Platten

    Created global setting to enable or disable skin dose maps. Also added global setting to enable or disable calculation of skin dose map data on import. Not done yet: there's no way to change these settings yet (need to add a new admin menu item); the setting values aren't populated to start with (I had to manually add the values to the database table). References issue #61

    → <<cset ab439fd294bc>>

  95. David Platten

    Created new config menu item that enables an admin user to update the skin dose map settings. It's a bit clunky at the moment. References issue #61

    → <<cset cfae5bd39816>>

  96. Jonathan Cole

    Do we still have a CSV exporter? if someone could send me a Toshiba or Philips dataset I will try and see what is wrong.

  97. Jonathan Cole

    The table top position is given by reference to an arbitrary point on the equipment. It would appear (as is typical) that all the companies use a different point.

    We would need to convert them all to the same co-ordinate system.

    The first thing I would need is to know what point the Toshiba and Philips are using. Does anyone have the DICOM info?

  98. Ed McDonagh reporter

    From the Philips Allura I just sent you:

    • height of system: 1065 mm
    • focal spot to isocenter: 810 mm
    • distance source to isocenter: 810 mm
    • distance source to detector: 1194 mm
    • table longitudinal position: 12 mm
    • table lateral position: 1818.6 mm
    • table height postition: 905 mm
  99. Jonathan Cole

    Yeah, so the distances for table position clearly indicate they are not using the head end, table plane, mid-line. Looks more like foot-end, floor and mid-line. OpenSkin is calculating the dose, but it is outside the phantom because of the assumed table position.

    Siemens define the zero point in their DICOM conformance statement but the ones I have found on the internet for Toshiba and Philips do not.

  100. Ed McDonagh reporter

    Toshiba single plane I sent you:

    • distance source to detector: 1200 mm
    • table longitudinal position: 520 mm
    • table lateral position: 30 mm
    • table height position: 990 mm
  101. Jonathan Cole

    I've asked Toshiba and Philips for how they define the table position distances. When I know how they are defined I will look at the best ways to include them.

  102. David Platten

    Added openSkin data export back to the rfdetail page if skin dose map display is switched off. Also included the text about only Cu filters being included. Added some text to let the user know that this version of OpenREM can calculate and display skin dose maps for some systems. References issue #61, issue #382 and issue #384.

    → <<cset 128002420c9c>>

  103. David Platten

    I think this is done now. Calculations don't work for some systems, but that's an openSkin issue rather than an OpenREM one.

  104. David Platten

    Adjusted the way that the colour scale increments and values are put on the colour scale to fix a display glitch. Also reduced the number of decimal places shown. References issue #61

    → <<cset e0612d90ed5b>>

  105. David Platten

    If skin dose map cannot be calculated or displayed then an appropriate message is displayed on the screen. This works as expected for Toshiba and Philips systems. References issue #61.

    → <<cset d04a666b8cdd>>

  106. Ed McDonagh reporter

    @dplatten - did you or @jacole ever establish the head toe orientation on the 3D model?

    I've been having fun generating 3D visualisations for some of the studies in my laptop test database, and I'm pretty sure that for my datasets they are wrong in the head-toe direction.

    The coronary catheterizations are all taking place in the lower half of the phantom, and an NG tube insert has radiation right on the bottom edge of the phantom and a little further up - I hope for that patient's sake that it is displayed upside down!

    These are all Siemens Zee units.

  107. David Platten

    No, I've not confirmed that I'm displaying things the right way up. It's something that needs to be answered before 0.7.0 is released.

  108. David Platten

    Flipped display of skin dose maps so that what was the top is now the bottom; left and right remain as they were. Need to confirm that this is correct. References issue #61.

    @edmcdonagh, do your skin dose maps look better now?

    → <<cset c63d2fe9d53d>>

  109. Ed McDonagh reporter

    Yes, the radiation is at the right end of the phantom now, but i'm not convinced about the angles. I must book some time in one of the rooms to thrash it out!

    In the mean time, can you add openSkin to the release notes?

  110. Jonathan Cole

    I thought I had checked orientations. It is possible top-bottom needs flipping but left-right doesn't as David has found.

    Have you tried it straight in openSkin with the PNG map? Is that upside down as well?

    There might be some co-ordinate system differences we need to account for.

  111. Ed McDonagh reporter

    I haven't tried using openSkin (directly) recently - does it indicate orientation now?

  112. Jonathan Cole

    Head should be at the top of the PNG.

    If the orientation is wrong in openSkin we should fix it there. If it is just a matter of how the array is treated in the python, javascript and PNG export we can fix it in either.

    I'm going to try and install the latest dev version of OpenREM today so I can work on these issues properly.

  113. Ed McDonagh reporter

    Do you want me to roll a new beta for you with David's openSkin integrations? Current beta doesn't have them.

  114. Jonathan Cole

    That might help.

    It's going to be painful because it is a Windows server with no internet...

    May take me a while.

  115. David Platten

    Added some (commented out) code that will try and calculate skin dose map data for every RF study in f when the user goes to the rffiltered.html page. I put this in as I wanted to calculate the skin dose map data for all of the studies in my off-line install of OpenREM. May be useful to have this as a feature at some point. References issue #61

    → <<cset be6f67576f28>>

  116. Jonathan Cole

    Testing this now and seems to work.

    It does block loading the page while rendering the skin doses though. Any way to avoid that? It takes about 10 minutes per skin map on my poor little server.

  117. Jonathan Cole

    I stand corrected. It doesn't seem to realise it already has some and is redoing them all.

    It's looking for a date folder structure that doesn't exist. My pickle files are all in the skin_maps with names skin_map_138.p

  118. Jonathan Cole

    It works as expected if I remove

    if study_date:
        skin_map_path = os.path.join(MEDIA_ROOT, 'skin_maps', "{0:0>4}".format(study_date.year), "{0:0>2}".format(study_date.month), "{0:0>2}".format(study_date.day), 'skin_map_'+str(study.pk)+'.p')
    else:
    

    and just leave the path without the date bits.

  119. Jonathan Cole

    Works if I update make_skin_map.py to the latest version.

    What was the motivation for changing the folder structure for skin maps? Just to make it tidier?

  120. Ed McDonagh reporter

    My fault. See Issue 398. I was thinking of Windows users like you, in the very long term, getting many thousand pickles in one folder and finding that the filesystem limits prevented any more going in.

    Have you been able to make any progress with orientations?

  121. Jonathan Cole

    OK, so it turns out my real issue is I never enabled celery. Now skin doses are running in the background. I don't know whether from this code or the original import.

  122. Jonathan Cole

    Orientations are definitely wrong right back in openSkin. I never noticed because of how I was using it.

    It's next on my list. I wanted to get the skin dose maps processing first so I have good guidance of what is right and wrong.

  123. Ed McDonagh reporter

    Celery should be processing them as they come in - if you view a fluoro study that was already in the database or hasn't yet been processed by Celery, then it should be generated on-the-fly. But I think Celery will do it again when it gets around to it.

    Regarding the orientations - I'm trying to work out a strategy for getting 0.7 to release, so any indication of timelines would be welcome 😄

  124. Jonathan Cole

    Realistically I won't get much more done before the end of June. There's a new CT to commission, a weak of leave and regular QA on top.

  125. David Platten

    The IrradEventXRayData database table has the following fields that I assume will be populated if the data is available in the rdsr, but I'm not sure if this is really what we need as these could be different on an exposure-by-exposure basis (I think in practice this is unlikely as once a patient is positioned for a fluoroscopy procedure they usually stay there for the duration). @edmcdonagh, any thoughts?

    patient_table_relationship_cid, includes "feet-first" and "headfirst" (http://dicom.nema.org/MEDICAL/Dicom/2015c/output/chtml/part16/sect_CID_21.html)

    patient_orientation_modifier_cid, includes "prone", "supine" etc. (http://dicom.nema.org/MEDICAL/Dicom/2015c/output/chtml/part16/sect_CID_20.html)

  126. Jonathan Cole

    The Siemens unit gives me a choice of: HFS, FFS, HFP, FFP, HFLL, FFLL, HFRL, FFRL I've checked all of these and concluded the following: - As defined in the DICOM standard angles are always 0 degrees out of the chest and -90 degrees to the patient's right. - Table movement directions are defined once and does not change with patient position.

    I can either correct the angles to the table geometry and then we can change the display based on orientation or I can correct the table directions based on orientation and we always display the patient standing up.

    Somehow OpenREM will need to know that it is one of these 8 choices.

  127. Jonathan Cole

    I am tempted to ignore the laterals for now as they may need modifications to the patient model.

  128. David Platten

    My Siemens Artis Zee OpenREM data does not have any information in the patient_table_relationship or patient_orientation_modifier fields. However, the study includes the text Postion SRData="HFS " within the comment field.

    We could look for suitable data in the proper fields, and then try looking in the comment, and then revert to some sort of sensible default.

  129. Jonathan Cole

    I've got some code for correct patient orientations (the main ones anyway). Can anyone help with modifying the RDSR extractor to capture the orientation as David suggested?

  130. David Platten

    Skin dose maps now display either Assumed or Extracted for patient height, mass and orientation information depending on whether the corresponding information is available in the database. I think I'd prefer verbose orientations to be displayed, such as Head-first supine, rather than HFS, but can't work out how to do this at the moment (ideas welcome...). References issue #438 and #61

    → <<cset 80713e1992b4>>

  131. David Platten

    phantom width and height were being calculated as float values, causing an error with the creation of Numpy arrays. Forced width and height to be int. References issue #438 and #61

    → <<cset 83b26f71bb8d>>

  132. David Platten

    Update disclaimer below skin dose map? Make failure graceful for more systems

    The Philips RDSR on the demo site fails, for example:

    UnboundLocalError at /openrem/rf/9/skin_map/ local variable 'patPosZ' referenced before assignment Request Method: GET Request URL: http://testing.openrem.org/openrem/rf/9/skin_map/?http%3A%2F%2Ftesting.openrem.org%2Fopenrem%2Frf%2F9%2F=undefined Django Version: 1.8.18 Exception Type: UnboundLocalError Exception Value:
    local variable 'patPosZ' referenced before assignment Exception Location: /home/deploy/sites/testing.openrem.org/source/openrem/remapp/tools/openskin/geomclass.py in init, line 213 Python Executable: /home/deploy/sites/testing.openrem.org/virtualenv/bin/python2 Python Version: 2.7.12 Python Path:
    ['/home/deploy/sites/testing.openrem.org/source/openrem', '/home/deploy/sites/testing.openrem.org/virtualenv/bin', '/home/deploy/sites/testing.openrem.org/virtualenv/lib/python2.7', '/home/deploy/sites/testing.openrem.org/virtualenv/lib/python2.7/plat-x86_64-linux-gnu', '/home/deploy/sites/testing.openrem.org/virtualenv/lib/python2.7/lib-tk', '/home/deploy/sites/testing.openrem.org/virtualenv/lib/python2.7/lib-old', '/home/deploy/sites/testing.openrem.org/virtualenv/lib/python2.7/lib-dynload', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/home/deploy/sites/testing.openrem.org/virtualenv/local/lib/python2.7/site-packages', '/home/deploy/sites/testing.openrem.org/source', '/home/deploy/sites/testing.openrem.org/source/openrem'] Server time: Sat, 24 Jun 2017 09:50:09 +0100

  133. David Platten

    Regarding manipulating the 3D visualisation, we could detect if a mobile device is being used and then load in either desktop / laptop events, or mobile touch events as appropriate:

    if( /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()) ) {
        // include jQuery mobile and also the mobile touch events
        // http://www.w3schools.com/jquerymobile/jquerymobile_events_intro.asp
    }
    else {
        // include the non-touch events that are used at the moment
    }
    
  134. Ed McDonagh reporter

    As previously established, low priority. But the proposed test would mean that touch screen desktop/laptops would not be able to play... Is there a disadvantage to having the touch controls available all the time? The trackball link above seems to work as nicely with a mouse, track-pad or a finger.

  135. David Platten

    The previous commit seems to have largely worked. With Chrome on my laptop in "mobile device" mode it all works as expected. On my Nexus 5 phone it isn't quite as good: pinch zooming doesn't work, but everything else does. @edmcdonagh, how does this look for you?

  136. Ed McDonagh reporter

    On my Windows touchscreen laptop and my android phone, both using Chrome, single finger touch works well once it has made the first jump - initial touch makes a random spin, then it works as you'd want it to until you lift your finger.

    Multi-touch just makes it spin crazily.

    At first I looked using Chrome on my Ubuntu virtual machine and it didn't work very well - then I realised that normally 3D is disabled in that environment because there is a problem with the WebGL graphics or something in virtualbox. Has this new code disabled or overcome the disabling? It works ok-ish with the mouse.

  137. Ed McDonagh reporter

    I can't remember how it was before, but now the first press is always nice and glitch free. However, subsequent ones are usually subject to an initial jump. Two fingers does nothing (it used to spin madly).

    That is assuming I'm not using cached js. I tried it on Edge, and it ignored that there was anything there.

  138. Ed McDonagh reporter

    Same on firefox on Android, so not a caching issue (hadn't tried using that browser before).

  139. David Platten

    My fault: I've added a handler for pinch zoom, but haven't populated it with code to do anything...

  140. David Platten

    Further changes to pinch zoom code. It's really annoying not having a local touch screen to test this on before committing the code. References issue #61

    → <<cset 0aef7b2496a7>>

  141. Luuk

    I don't know if it is the right issue to put this in, but it seemed the most suitable. A lot of skin maps (from Siemens, but also from Philips, using branch Issue446PrivateFieldsPhilipsAlluraXper) result in a small band of dose at the top of the phantom (see below, very unlikely with a dose at reference point of 6 Gy) or a message that all the exposures missed the phantom. skindosemap.png

    • Is the reason for this known (what should be done to fix it)?
    • Shouldn't we inform the user for any event/exposure that misses the phantom (N of the Ntotal events/exposures missed the phantom)
    • Would it be an option to set per system a default matrass thickness / table thickness, -width, -length? Although the matrass thickness may vary for different procedures.

    Thanks, Luuk

  142. Jonathan Cole

    Thanks Luuk, This may be an orientation problem. I know that there are definitely some issues with exposures that are not head first supine. I have some fixed code somewhere (maybe on the OpenSkin bitbucket?), but haven't had a chance to run through it properly. I'm hoping to have some time early in the new year but almost certainly won't before then. We absolutely can add some pre set mattress and table details. I only have full information for the Siemens Zeego at the Royal Free, but it wasn't hard to measure. Perhaps some of these thoughts should be split out in to separate feature requests? Either here or on the OpenSkin repo.

    Jon

  143. Luuk

    I'm going to make some test runs for the Philips table (beam) position parameters on an Allura FD20 probably Friday (so far it seems one angio suite will be available for some time). If time permits, I'm willing to do some dose (transmission) measurements also. @jacole Do you have a protocol / measurement sheet to fill? Or should I just look at the values given in getTableTrans and getTableMattressTrans (in geomfunc.py)? Just to confirm: is the last one mattress AND table?

  144. Jonathan Cole

    I'm afraid I don't have a protocol.

    If I remember correctly I measured transmission through the table and then through both table and mattress for a range of kV and skin saving filter combinations to cover what might occur clinically.

  145. Luuk

    With respect to the Philips Table Position. We have an older Allura FD20 system not sending Table Longitudinal and Lateral Positions. I had hoped that the private beam position would be a substitute, but it isn't (it really is the position of the beam to a reference point in the room, not with respect to the table). So if Table Positions aren't filled we don't have anything to determine the position. I'll try to see how skin dose maps works out for the newer system (also an Allura system, we don't have the newer Azurion type).

    I also did some transmission measurements (but should have prepared myself better). Philips (almost) always uses 1 mm Al-filter in addition to the inherent filtering and also can choose from 0.1, 0.4 or 0.9 mm copper. It turned out that in service mode you can set tube voltage, tube current and exposure time only. You can't set the filtration. So we manually added copper filtration to the beam (and only had 0.3 mm plates of copper at hand. So we might do some additional measurements later). The results are in the same range as the Siemens results: TransmissieTafel.pngTransmissieTafelMatras.png

    For table only, the maximum deviation compared to the Siemens Artis Zee is 2,8% and for table and matrass 7,8 % (especially for 0 mm Cu the Philips matrass has a higher transmission factor)

  146. Ed McDonagh reporter

    @dplatten , @jacole , @LuukO - do you think we can mark this issue as 'done'? And take the 'other manufacturers' and any other issue/improvements into new issues?

    Otherwise I'll need to kick this into 'Future' as an issue.

  147. Log in to comment