Ticket #9770: IDF_to_PLY.py

File IDF_to_PLY.py, 5.5 KB (added by Anders Markvardsen, 6 years ago)
Line 
1from mantid.kernel import *
2from mantid.api import *
3
4# Author: E. Farhi  <farhi@ill.fr>
5# Date:   June 19th 2014
6# Description: IDF to PLY/OFF converter
7 
8class IDF_to_PLY(PythonAlgorithm):
9
10    def category(self):
11        return 'Utilities'
12
13    def PyInit(self):
14        # Declare properties
15        self.declareProperty(FileProperty(name="InputFile",defaultValue="",
16                                action=FileAction.Load, extensions = ["xml","hdf","nxs"]), 
17                                direction=Direction.Input, 
18                                doc="An input file with associated instrument definition (IDF/XML in MANTIDPATH/instrument, NeXus or HDF)")
19       
20        # output direction specified explicitly
21        self.declareProperty(FileProperty(name="OutputFile",defaultValue="instrument_Description",
22                                action=FileAction.Save, extensions = ["off","ply"]), 
23            direction=Direction.Output,
24            doc="The output file name where the geometry will be saved")
25
26        # the type of Data File generated
27        self.declareProperty("OutputFormat","OFF", StringListValidator(["OFF","PLY"]))
28
29    def PyExec(self):
30        # Run the algorithm
31
32        # Load the Instrument Definition File (IDF) e.g. XML or from NXS
33        ws = Load(Filename=self.getPropertyValue("InputFile"))
34       
35        inst  = ws.getInstrument()
36       
37        nhist = ws.getNumberHistograms()
38
39        self.log().information( "IDF_to_PLY: Opening instrument " + inst.getName() + " definition from file " + self.getPropertyValue("InputFile") + " with " + str(nhist) + " pixels."
40
41        name = self.getPropertyValue("OutputFile")
42        fid = open(name, "w")
43
44        self.log().information( "IDF_to_PLY: Generating output file " + self.getPropertyValue("OutputFile") )
45
46        # Mantid::Geometry::OCGeometryGenerator
47        # methods: getNumberOfPoints, getNumberOfTriangles, getTriangleFaces, getTriangleVertices
48
49        nb_vertices = 0
50        nb_polygons = 0
51        vout = ""
52        pout = ""
53
54        # traverse all detector pixels
55        for i in range(nhist):
56            det = inst.getDetector(i);
57            if not det.isMonior():
58              # det.getPos() is the position of the detector object, whatever be its internal shape and definition of origin
59              # we thus prefer to use the shape and its bounding box
60
61                BBox = det.shape().getBoundingBox() # use .centrePoint() and .width() which are V3D objects
62                # create a cuboid from the boundingBox. centerPoint is really at the center of the max-min
63                # so we add the +/- width/2
64                pos = BBox.centrePoint() -  inst.getSample().getPos()     # shift from sample
65                x0 = pos.X()
66                y0 = pos.Y()
67                z0 = pos.Z()
68                dx = BBox.width().X()/2.0
69                dy = BBox.width().Y()/2.0
70                dz = BBox.width().Z()/2.0
71
72                i = nb_vertices   # offset for vertices index
73
74                # write the X Y Z coordinate of Detector BBox position wrt sample
75                vout += '%g %g %g\n' % (x0+dx, y0-dy, z0-dz)
76                vout += '%g %g %g\n' % (x0-dx, y0+dy, z0-dz)
77                vout += '%g %g %g\n' % (x0-dx, y0-dy, z0+dz)
78                vout += '%g %g %g\n' % (x0-dx, y0-dy, z0-dz)
79                vout += '%g %g %g\n' % (x0+dx, y0-dy, z0+dz)
80                vout += '%g %g %g\n' % (x0+dx, y0+dy, z0-dz)
81                vout += '%g %g %g\n' % (x0+dx, y0+dy, z0+dz)
82                vout += '%g %g %g\n' % (x0-dx, y0+dy, z0+dz)
83                nb_vertices += 8
84
85                # write the connections after the vertices
86                pout += '%i %i %i\n' % (4 0+i 5+i 6+i 4+i)
87                pout += '%i %i %i\n' % (4 1+i 5+i 6+i 7+i)
88                pout += '%i %i %i\n' % (4 2+i 4+i 6+i 7+i)
89                pout += '%i %i %i\n' % (4 3+i 0+i 4+i 2+i)
90                pout += '%i %i %i\n' % (4 3+i 0+i 5+i 1+i)
91                pout += '%i %i %i\n' % (4 3+i 1+i 7+i 2+i)
92                nb_polygons += 6
93
94        # get the file type to export, write the file content
95        if self.getPropertyValue("InputFile") == 'OFF':
96            fid.write("OFF\n")  # 1st line, mandatory
97            fid.write("# This is an Object File Format (geomview). Use e.g. Meshlab to view it.\n")
98            fid.write("# nb points, nb faces, void\n")
99            fid.write("# List point coordinates\n")
100            fid.write("%i %i 0\n" % (nb_vertices,nb_polygons))       # nb points, nb faces, void
101            fid.write(vout)
102            fid.write("# List faces, all rectangular\n")
103            fid.write(pout)
104        else:
105            fid.write("ply\n")
106            fid.write("format ascii 1.0\n")
107            fid.write("comment " + inst.getName() + " geometry (Mantid IDF) from file " + self.getPropertyValue("InputFile") + "\n")
108            fid.write("comment This is an PLY File Format. Use e.g. Meshlab to view it.\n")
109            fid.write("element vertex %i\n" % (nb_vertices))
110            fid.write("property float32 x\n")
111            fid.write("property float32 y\n")
112            fid.write("property float32 z\n")
113            fid.write("element face %i\n" % (nb_polygons))
114            fid.write("property list uint8 int32 vertex_indices\n")
115            fid.write("end_header\n")
116            fid.write(vout)
117            fid.write(pout)
118             
119        self.log().information( "IDF_to_PLY: " + inst.getName() + " written to " + self.getPropertyValue("OutputFile") + " with %i vertices and %i polygons" % (nb_vertices, nb_polygons) )
120        deleteWorkspace(ws) 
121
122# Register algorithm with Mantid
123AlgorithmFactory.subscribe(IDF_to_PLY)