Warning: Can't synchronize with repository "(default)" (/home/git/ome.git does not appear to be a Git repository.). Look in the Trac log for more information.

Ticket #1739: boxer.py

File boxer.py, 9.8 KB (added by wmoore, 14 years ago)

Script working better now!

Line 
1"""
2
3This script is a "proof of principle" to demonstrate how Spider and EMAN2 can work with OMERO.
4This uses the auto-box functionality of EMAN2, which takes one or more user-defined particle ROIs,
5and uses this as the basis for picking additional particles from the image.
6In this script, OMERO is used as the source of the image, with the user-defined particles as ROIs on
7the server. Spider is used to turn the plane array into a Spider image. The EMAN2 subclasses
8use this, with the server ROI(s) to generate additional ROIs which are then saved back to
9the server.
10The script below is currently implemented as a client-side script, but could easily be
11converted into a server-side script, with EMAN2 and Spider installed on the server.
12
13"""
14from EMAN2 import *
15
16from e2boxer import *
17
18import numpy
19import omero
20from omero.rtypes import *
21import omero.util.script_utils as scriptUtil
22from Spider.Spiderarray import array2spider
23
24from Tkinter import Tk, Label
25import Image, ImageTk
26
27
28class DummyWindow():
29        """
30        Just need a blank class to replace the need for a UI
31        """
32        def updateGL(self):
33                pass
34
35
36class OmeroSwarmPanel():
37        """
38        Another blank class to replace the need for a UI
39        """
40       
41        def __init__(self, box_size):
42                self.box_size = box_size
43               
44        def set_picking_data(self, peak_score, profile, profile_trough_point):
45                print "Dummy PanelObject: set_picking_data()"
46                print "    peak_score: " + str(peak_score)
47                print "    profile: " + str(profile)
48                print "    profile_trough_point: " + str(profile_trough_point)
49
50
51class OmeroSwarmTool(SwarmBoxer):
52        '''
53        Subclass the main Boxer class, to add data source, UI elements etc.
54        '''     
55       
56        def __init__(self,target,particle_diameter=128):
57                # import sys
58                # print >> sys.stderr, target.__class__
59                SwarmBoxer.__init__(self,particle_diameter)
60                self.target = weakref.ref(target)       # now, the target() method will return target
61                window = DummyWindow()
62                def getWindow():
63                        return window
64                self.get_2d_window = getWindow
65                #self.panel_object = SwarmPanel(self,self.particle_diameter)
66                self.panel_object = OmeroSwarmPanel(self.particle_diameter)     # needs to implement set_picking_data(self.peak_score, self.profile, self.profile_trough_point)
67                self.gui_mode = False
68
69
70class Target():
71        """
72        Dummy target to get / save boxes to omero etc.
73        Replaces the functionality of emboxerbase.EMBoxerModule which is used in the workflow UI.
74        Takes a reference to an OMERO session in the constructor, which is then used to write the picked particles as
75        ROIs to the image, identified by imageId
76        """
77        def __init__(self, box_size, session, imageId):
78                def getFileName():
79                        return "/Users/will/Documents/dev/EMAN2/06jul12a.mrc"
80                self.current_file = getFileName
81                #self.current_file = "/Users/will/Documents/dev/EMAN2/06jul12a.mrc"
82                self.box_size = box_size
83                self.box_list = EMBoxList(self)         # has methods like detect_collision()
84                self.session = session
85                self.imageId = imageId
86               
87                # create the service and image for adding ROIs later...
88                self.updateService = self.session.getUpdateService()
89                gateway = self.session.createGateway()
90                self.image = gateway.getImage(self.imageId)
91                self.imageY = self.image.getPrimaryPixels().getSizeY().getValue()
92       
93        # code from emboxerbase.EMBoxerModule
94        def add_box(self, x, y, type):
95                """
96                add a box to the list
97                If type = SwarmBoxer.REF_NAME then this is a reference box.
98                """
99                print "add_box() x: %d, y: %d" % (x, y)
100                box_num = self.box_list.add_box(x,y,type=type)
101               
102               
103        # code from emboxerbase.EMBoxerModule
104        def clear_boxes(self,type,cache=False):
105                self.box_list.clear_boxes(type,cache=cache)
106       
107       
108        # code from emboxerbase.EMBoxerModule
109        def get_box(self,box_number):
110                '''
111                @param box_number the number of the box for which you want to get
112                '''
113                return self.box_list.get_box(box_number)
114       
115       
116        # code from emboxerbase.EMBoxerModule
117        def set_box(self,box,box_number,update_display=False):
118                '''
119                @param box_number the number of the box for which you want to get
120                '''
121                self.box_list.set_box(box,box_number)
122                #if update_display:
123                #       self.full_box_update()
124       
125       
126        # code from emboxerbase.EMBoxerModule
127        def add_boxes(self,boxes,update_gl=True):
128                '''
129                boxes should be a list like [[x,y,type],[x,y,type],....[int,int,string]]
130                '''
131                for b in boxes:
132                        print b
133                        x,y,type,v = b
134                        x -= self.box_size/2    # convert from centre of particle, to top-left of ROI
135                        y = self.imageY - y             # convert from bottom to top Y coordinates.
136                        y -= self.box_size/2
137                        self.addRectangleRoi(x, y)
138                # removed a lot of UI code from emboxerbase.EMBoxerModule
139                self.box_list.add_boxes(boxes)
140               
141               
142        # code from emboxerbase.EMBoxerModule
143        def get_subsample_rate(self):
144                '''
145               
146                '''
147                return int(math.ceil(float(self.box_size)/float(TEMPLATE_MIN)))
148                               
149        # code from emboxerbase.EMBoxerModule
150        def get_exclusion_image(self,mark_boxes=False):
151                '''
152                @mark_boxes if true the exclusion image is copied and the locations of the current boxes are painted in as excluded regions
153                This is useful for autoboxers - they  obviously dont want to box any region that already has a box in it (such as a manual box,
154                or a previously autoboxed box)
155                '''
156                exc_image = ScaledExclusionImageCache.get_image(self.current_file(), self.get_subsample_rate())         # class 'libpyEMData2.EMData'
157                print "Target get_exclusion_image() mark_boxes: " + str(mark_boxes)     
158               
159                #display(exc_image)             # blank image
160               
161                if not mark_boxes: return exc_image
162               
163                else:
164                        print "    Ignoring request to mark_boxes: returning unmasked image..."
165                        return exc_image        # hack to avoid fixing the code below. Manually added boxes will not be excluded from being auto-boxed.
166                       
167                        image = exc_image.copy()
168                        boxes = self.box_list.get_boxes()
169                        if len(boxes) > 0:
170                                sr = self.get_subsample_rate()
171                                global BinaryCircleImageCache
172                                mask = BinaryCircleImageCache.get_image_directly(int(self.box_size/(2*sr)))
173                                for box in self.box_list.get_boxes():
174                                        x,y = int(box.x/sr),int(box.y/sr)
175                                        # from EMAN2 import BoxingTools
176                                        BoxingTools.set_region(image,mask,x,y,0.1) # 0.1 is also the value set by the eraser - all that matters is that it's zon_zero
177                       
178                        return image
179                       
180        # code from emboxerbase.EMBoxerModule
181        def detect_box_collision(self,data):
182                print "target detect_box_collision() " + str(data)
183                return self.box_list.detect_collision(data[0], data[1], self.box_size)
184
185               
186        def addRectangleRoi(self, x, y):
187                """
188                Adds a Rectangle (particle) to the current OMERO image, at point x, y.
189                Uses the self.image (OMERO image) and self.updateService
190                """
191                width = self.box_size
192                height = self.box_size
193
194                # create an ROI, add the rectangle and save
195                roi = omero.model.RoiI()
196                roi.setImage(self.image)
197                r = self.updateService.saveAndReturnObject(roi)
198
199                # create and save a rectangle shape
200                rect = omero.model.RectI()
201                rect.x = rdouble(x)
202                rect.y = rdouble(y)
203                rect.width = rdouble(width)
204                rect.height = rdouble(height)
205                rect.theZ = rint(0)
206                rect.theT = rint(0)
207
208                # link the rectangle to the ROI and save it
209                rect.setRoi(r)
210                r.addShape(rect)       
211                self.updateService.saveAndReturnObject(rect)
212
213
214def getRectangles(session, imageId):
215        """ Returns (x, y, width, height) of each rectange ROI in the image """
216       
217        rectangles = []
218        shapes = []             # string set.
219       
220        roiService = session.getRoiService()
221        result = roiService.findByImage(imageId, None)
222       
223        rectCount = 0
224        for roi in result.rois:
225                for shape in roi.copyShapes():
226                        if type(shape) == omero.model.RectI:
227                                x = shape.getX().getValue()
228                                y = shape.getY().getValue()
229                                width = shape.getWidth().getValue()
230                                height = shape.getHeight().getValue()
231                                rectangles.append((int(x), int(y), int(width), int(height)))
232                                continue
233        return rectangles
234
235
236def downloadImage(session, imageId, imageName):
237        """
238        This method downloads the first (only?) plane of the OMERO image and saves it as a local image.
239       
240        @param session          The OMERO session
241        @param imageId          The ID of the image to download
242        @param imageName        The name of the image to write. If no path, saved in the current directory.
243        """
244        queryService = session.getQueryService()
245        rawPixelStore = session.createRawPixelsStore()
246
247        # get pixels with pixelsType
248        query_string = "select p from Pixels p join fetch p.image i join fetch p.pixelsType pt where i.id='%d'" % imageId
249        pixels = queryService.findByQuery(query_string, None)
250        theX = pixels.getSizeX().getValue()
251        theY = pixels.getSizeY().getValue()
252
253        # get the plane
254        theZ, theC, theT = (0,0,0)
255        pixelsId = pixels.getId().getValue()
256        bypassOriginalFile = True
257        rawPixelStore.setPixelsId(pixelsId, bypassOriginalFile)
258        plane2D = scriptUtil.downloadPlane(rawPixelStore, pixels, theZ, theC, theT)
259       
260        plane2D.resize((3135, 2875))
261        p = Image.fromarray(plane2D)
262        p.show()
263        p.save(imageName)
264       
265        return (theX, theY)
266
267if __name__ == "__main__":
268       
269        # start by logging in to server
270        client = omero.client("localhost")
271        session = client.createSession("root", "omero")
272       
273        imageId = 969
274       
275        # download the image as a local temp image
276        #image_name = "tempImage.dat"
277        image_name = "newTestImage.tiff"
278        imgW, imgH = downloadImage(session, imageId, image_name)
279       
280        #showImage(image_name)
281        print "image downloaded"
282       
283       
284        # get list of ROI boxes as (x, y, width, height) on the image
285        boxes = getRectangles(session, imageId)
286        if len(boxes) == 0:
287                print "No ROIs found - exiting!"
288                import sys
289                sys.exit()
290       
291        # use the width of the first box as the box_size (all should be same w,h)
292        x,y,w,h = boxes[0]
293        box_size = w
294       
295        # create a 'target' which will save the generated boxes as ROI rectangles to OMERO
296        target = Target(box_size, session, imageId)
297        omeroBoxer = OmeroSwarmTool(target, particle_diameter=box_size)         # pass target to Boxer
298       
299        # add the reference boxes to the boxer
300        for box in boxes:
301                x, y, w, h = box
302                x += box_size/2         # convert from top-left of ROI (OMERO) to centre of particle (EMAN2)
303                y += box_size/2
304                y = imgH - y            # convert distance from Top of image (OMERO) to distance from bottom (EMAN2)
305                omeroBoxer.add_ref(x,y,image_name)
306       
307        # perform auto-boxing - results are written back to server, as ROIs on the image.
308        omeroBoxer.auto_box(image_name)
309       
310       

1.3.13-PRO © 2008-2011 Agilo Software all rights reserved (this page was served in: 0.74568 sec.)

We're Hiring!