Exemplo n.º 1
0
def roi(experimenter, experimenter_group, permissions):
    o = RoiI()
    o.id = rlong(1L)
    o.name = rstring('the_name')
    o.description = rstring('the_description')
    o.details.owner = experimenter
    o.details.group = experimenter_group
    o.details.permissions = permissions
    return o
def roi(experimenter, experimenter_group, permissions):
    o = RoiI()
    o.id = rlong(1L)
    o.name = rstring('the_name')
    o.description = rstring('the_description')
    o.details.owner = experimenter
    o.details.group = experimenter_group
    o.details.permissions = permissions
    return o
Exemplo n.º 3
0
def roi(experimenter, experimenter_group, permissions, externalInfo):
    o = RoiI()
    o.id = rlong(1L)
    o.name = rstring("the_name")
    o.description = rstring("the_description")
    o.details.owner = experimenter
    o.details.group = experimenter_group
    o.details.permissions = permissions
    o.details.externalInfo = externalInfo
    return o
Exemplo n.º 4
0
    def addRoi(self, request, imageid):
        img = self.getImage0(imageid)
        if img is None:
            return None

        data = json.loads(request.body)
        shapes = data['shapes']
        x = y = l = z = t = -1
        for s in shapes:
            for k in s:
                val = s[k]
                if k == "x":
                    x = int(val)
                elif k == "y":
                    y = int(val)
                elif k == "width":
                    l = int(val)
                elif k == "theZ":
                    z = int(val)
                elif k == "theT":
                    t = int(val)
                elif k == "fillColorAsInt":
                    fill = int(val)
                elif k == "strokeColorAsInt":
                    stroke = int(val)
                elif k == "strokeWidth":
                    strokeWidth = int(val)
        
        if (x < 0 or y < 0 or z < 0 or t < 0 or l <= 0):
            return None
        
        updateService = self._connection.getUpdateService()
        roi = RoiI()
        roi.setImage(img._obj)
        rect = RectangleI()
        rect.x = rdouble(x)
        rect.y = rdouble(y)
        rect.width = rdouble(l)
        rect.height = rdouble(l)
        rect.theZ = rint(z)
        rect.theT = rint(t)
        rect.setFillColor(rint(fill))
        strokeLen = LengthI()
        strokeLen.setValue(strokeWidth)
        strokeLen.setUnit(UnitsLength.PIXEL)
        rect.setStrokeWidth(strokeLen)
        rect.setStrokeColor(rint(stroke))
        roi.addShape(rect)
        
        if (updateService.saveAndReturnObject(roi) is None):
            return None
        return self.get_rois(imageid) 
def to_rois(cx_column, cy_column, pixels):
    unloaded_image = ImageI(pixels.image.id, False)
    rois = list()
    for index in range(len(cx_column.values)):
        cx = rdouble(cx_column.values[index])
        cy = rdouble(cy_column.values[index])
        roi = RoiI()
        shape = PointI()
        shape.theZ = rint(0)
        shape.theT = rint(0)
        shape.cx = cx
        shape.cy = cy
        roi.addShape(shape)
        roi.image = unloaded_image
        rois.append(roi)
    return rois
def process_file(inputfile, image, svc, offset):
    """
    Read each line of the file
    """
    parents = dict()
    line_count = 0
    roi = None
    parent_shape_id = -1
    parent_id = -1
    cell_id = 0
    x = image.getSizeX() / 2
    y = 0
    if offset is not None:
        y = image.getSizeY() - int(offset[1])

    last_frame = 0
    with open(inputfile) as fp:
        csv_reader = csv.reader(fp, delimiter="\t", quotechar='"')
        for row in csv_reader:
            if line_count > 1:
                # Check the first element to parse
                name = row[0]
                if name.find(">CELL") >= 0:
                    # extract cell info
                    if roi is not None:
                        # we save the roi before starting a new shape
                        roi = svc.saveAndReturnObject(roi)
                        parents[cell_id] = get_last_shape(roi, last_frame)
                    last_frame = -1
                    cell_id = int(row[1])
                    parent_id = int(row[2])
                    end_type = row[6]
                    roi = RoiI()
                    roi.setImage(image._obj)
                    value = "cellID:%s, parent_id: %s" % (cell_id, parent_id)
                    print(value)
                    if parent_id != -1:
                        parent_shape_id = parents[parent_id]
                    else:
                        parent_shape_id = -1
                else:
                    last_frame = process_row(row, x, y, roi, end_type,
                                             parent_shape_id)
                    parent_shape_id = -1
            line_count += 1
Exemplo n.º 7
0
 def __init__(self, roi = None):
     DataObject.__init__(self);
     if(roi==None):
         self.setValue(RoiI());
     else:
         self.setValue(roi);
     self.roiShapes = dict();
     if(roi!=None):
         self.initialise();
Exemplo n.º 8
0
 def __init__(self, roi=None):
     DataObject.__init__(self)
     if(roi is None):
         self.setValue(RoiI())
     else:
         self.setValue(roi)
     self.roiShapes = dict()
     if(roi is not None):
         self.initialise()
Exemplo n.º 9
0
def create_roi(image, shapes):
    updateService = image._conn.getUpdateService()
    roi = RoiI()
    roi.setImage(image._obj)
    for shape in shapes:
        roi.addShape(shape)
    return updateService.saveAndReturnObject(roi)
Exemplo n.º 10
0
 def _parse_mnu_roi(self, columns):
     """Parses out ROI from OmeroTables columns for 'MNU' datasets."""
     log.debug("Parsing %s MNU ROIs..." % (len(columns[0].values)))
     image_ids = columns[self.IMAGE_COL].values
     rois = list()
     # Save our file annotation to the database so we can use an unloaded
     # annotation for the saveAndReturnIds that will be triggered below.
     self.file_annotation = self.update_service.saveAndReturnObject(self.file_annotation)
     unloaded_file_annotation = FileAnnotationI(self.file_annotation.id.val, False)
     batch_no = 1
     batches = dict()
     for i, image_id in enumerate(image_ids):
         unloaded_image = ImageI(image_id, False)
         roi = RoiI()
         shape = PointI()
         shape.theZ = rint(0)
         shape.theT = rint(0)
         values = columns[3].values
         shape.cx = rdouble(float(values[i]))
         values = columns[2].values
         shape.cy = rdouble(float(values[i]))
         roi.addShape(shape)
         roi.image = unloaded_image
         roi.linkAnnotation(unloaded_file_annotation)
         rois.append(roi)
         if len(rois) == self.ROI_UPDATE_LIMIT:
             self.thread_pool.add_task(self.update_rois, rois, batches, batch_no)
             rois = list()
             batch_no += 1
     self.thread_pool.add_task(self.update_rois, rois, batches, batch_no)
     self.thread_pool.wait_completion()
     batch_keys = batches.keys()
     batch_keys.sort()
     for k in batch_keys:
         columns[self.ROI_COL].values += batches[k]
Exemplo n.º 11
0
 def parse_and_populate_roi(self, columns):
     # Remove from interface
     # Using this as a place to set file annotation
     self.file_annotation =\
         self.update_service.saveAndReturnObject(
             self.file_annotation)
     rois = columns[1].values
     for roi in rois:
         link = RoiAnnotationLinkI()
         link.parent = RoiI(roi, False)
         link.child = self.file_annotation.proxy()
         self.update_service\
             .saveObject(link)
Exemplo n.º 12
0
def create_points(conn, df, image):

    columns = [
        "Sequence", "Tagged Protein", "Sequence is unique", "Location_X",
        "Location_Y"
    ]
    df2 = pandas.DataFrame(columns=(['Roi'] + columns))
    index = df['Source Name'] == image.getName()
    for (s, tp, u, x, y) in zip(*map(lambda x: df[index][x], columns)):
        p = PointI()
        p.x = rdouble(float(x))
        p.y = rdouble(float(y))
        p.setTextValue(rstring(tp))
        roi = RoiI()
        roi.addShape(p)
        roi.setName(rstring(tp))
        roi.setImage(ImageI(image.getId(), False))
        roi = conn.getUpdateService().saveAndReturnObject(roi)
        df2.loc[len(df2)] = (roi.getId().getValue(), s, tp, u, x, y)
    return df2
Exemplo n.º 13
0
    def parse(self):
        provider = self.original_file_provider
        data = provider.get_original_file_data(self.original_file)
        try:
            rows = list(csv.reader(data, delimiter=","))
        finally:
            data.close()

        columns = [
            ImageColumn("Image", "", list()),
            RoiColumn("ROI", "", list()),
            StringColumn("Type", "", 12, list()),
        ]

        for row in rows[1:]:
            wellnumber = self.well_name_to_number(row[0])
            image = self.analysis_ctx.\
                image_from_wellnumber(wellnumber)
            #  TODO: what to do with the field?!
            #  field = int(row[1])
            #  image = images[field]
            roi = RoiI()
            shape = PointI()
            shape.cx = rdouble(float(row[2]))
            shape.cy = rdouble(float(row[3]))
            shape.textValue = rstring(row[4])
            roi.addShape(shape)
            roi.image = image.proxy()
            rid = self.update_service\
                .saveAndReturnIds([roi])[0]

            columns[0].values.append(image.id.val)
            columns[1].values.append(rid)
            columns[2].values.append(row[4])

        return MeasurementParsingResult([columns])
Exemplo n.º 14
0
    def parse(self):
        provider = self.original_file_provider
        data = provider.get_original_file_data(self.original_file)
        try:
            rows = list(csv.reader(data, delimiter=","))
        finally:
            data.close()

        columns = [
            ImageColumn("Image", "", list()),
            RoiColumn("ROI", "", list()),
            StringColumn("Type", "", 12, list()),
        ]

        for row in rows[1:]:
            wellnumber = self.well_name_to_number(row[0])
            image = self.analysis_ctx.\
                image_from_wellnumber(wellnumber)
            #  TODO: what to do with the field?!
            #  field = int(row[1])
            #  image = images[field]
            roi = RoiI()
            shape = PointI()
            shape.cx = rdouble(float(row[2]))
            shape.cy = rdouble(float(row[3]))
            shape.textValue = rstring(row[4])
            roi.addShape(shape)
            roi.image = image.proxy()
            rid = self.update_service\
                .saveAndReturnIds([roi])[0]

            columns[0].values.append(image.id.val)
            columns[1].values.append(rid)
            columns[2].values.append(row[4])

        return MeasurementParsingResult([columns])
Exemplo n.º 15
0
def create_roi(conn, img, shapes):
    updateService = conn.getUpdateService()
    roi = RoiI()
    roi.setImage(img._obj)
    for shape in shapes:
        roi.addShape(shape)
    group_id = img.getDetails().getGroup().getId()
    print(group_id)
    ctx = {'omero.group': str(group_id)}
    return updateService.saveAndReturnObject(roi, ctx)
Exemplo n.º 16
0
    def addRoi(self, request, imageid):
        img = self.getImage0(imageid)
        if img is None:
            return None

        data = json.loads(request.body)
        shapes = data['shapes']
        x = y = l = z = t = -1
        for s in shapes:
            for k in s:
                val = s[k]
                if k == "x":
                    x = int(val)
                elif k == "y":
                    y = int(val)
                elif k == "width":
                    l = int(val)
                elif k == "theZ":
                    z = int(val)
                elif k == "theT":
                    t = int(val)
                elif k == "fillColorAsInt":
                    fill = int(val)
                elif k == "strokeColorAsInt":
                    stroke = int(val)
                elif k == "strokeWidth":
                    strokeWidth = int(val)

        if (x < 0 or y < 0 or z < 0 or t < 0 or l <= 0):
            return None

        updateService = self._connection.getUpdateService()
        roi = RoiI()
        roi.setImage(img._obj)
        rect = RectangleI()
        rect.x = rdouble(x)
        rect.y = rdouble(y)
        rect.width = rdouble(l)
        rect.height = rdouble(l)
        rect.theZ = rint(z)
        rect.theT = rint(t)
        rect.setFillColor(rint(fill))
        strokeLen = LengthI()
        strokeLen.setValue(strokeWidth)
        strokeLen.setUnit(UnitsLength.PIXEL)
        rect.setStrokeWidth(strokeLen)
        rect.setStrokeColor(rint(stroke))
        roi.addShape(rect)

        if (updateService.saveAndReturnObject(roi) is None):
            return None
        return self.get_rois(imageid)
Exemplo n.º 17
0
def make_mask(x, y, h, w):
    mask = MaskI()
    mask.x = rdouble(x)
    mask.y = rdouble(y)
    mask.height = rdouble(h)
    mask.width = rdouble(w)
    mask.bytes = make_circle(h, w)

    roi = RoiI()
    roi.description = rstring("created by overlapping-masks.py")
    roi.addShape(mask)
    roi.image = image
    roi = update_service.saveAndReturnObject(roi)
    print(f"Roi:{roi.id.val}")
Exemplo n.º 18
0
 def _parse_neo_roi(self, columns):
     """Parses out ROI from OmeroTables columns for 'NEO' datasets."""
     log.debug("Parsing %s NEO ROIs..." % (len(columns[0].values)))
     image_ids = columns[self.IMAGE_COL].values
     rois = list()
     # Save our file annotation to the database so we can use an unloaded
     # annotation for the saveAndReturnIds that will be triggered below.
     self.file_annotation = \
         self.update_service.saveAndReturnObject(self.file_annotation)
     unloaded_file_annotation = \
         FileAnnotationI(self.file_annotation.id.val, False)
     batch_no = 1
     batches = dict()
     for i, image_id in enumerate(image_ids):
         unloaded_image = ImageI(image_id, False)
         roi = RoiI()
         shape = EllipseI()
         values = columns[6].values
         diameter = rdouble(float(values[i]))
         shape.theZ = rint(0)
         shape.theT = rint(0)
         values = columns[4].values
         shape.cx = rdouble(float(values[i]))
         values = columns[3].values
         shape.cy = rdouble(float(values[i]))
         shape.rx = diameter
         shape.ry = diameter
         roi.addShape(shape)
         roi.image = unloaded_image
         roi.linkAnnotation(unloaded_file_annotation)
         rois.append(roi)
         if len(rois) == self.ROI_UPDATE_LIMIT:
             self.thread_pool.add_task(
                 self.update_rois, rois, batches, batch_no)
             rois = list()
             batch_no += 1
     self.thread_pool.add_task(self.update_rois, rois, batches, batch_no)
     self.thread_pool.wait_completion()
     batch_keys = batches.keys()
     batch_keys.sort()
     for k in batch_keys:
         columns[self.ROI_COL].values += batches[k]
    def test_roi_thumbnail(self, theT, theZ):
        update_service = self.sf.getUpdateService()
        img = self.create_test_image(size_x=125,
                                     size_y=125,
                                     size_z=2,
                                     size_t=2,
                                     session=self.sf)

        for s in self.shapes():
            if theT is not None:
                s.theT = rint(theT)
            if theZ is not None:
                s.theZ = rint(theZ)
            roi = RoiI()
            roi.addShape(s)
            roi.setImage(img)
            roi = update_service.saveAndReturnObject(roi)
            shape = roi.copyShapes()[0]

            # Test ROI thumbnail...
            request_url = reverse('webgateway_render_roi_thumbnail',
                                  kwargs={'roiId': roi.id.val})
            rsp = get(self.django_client, request_url)
            thumb_bytes = BytesIO(rsp.content)
            try:
                thumb = Image.open(thumb_bytes)
            finally:
                thumb_bytes.close()
            assert thumb.size == (250, 166)

            # and Shape thumbnail...
            request_url = reverse('webgateway_render_shape_thumbnail',
                                  kwargs={'shapeId': shape.id.val})
            rsp = get(self.django_client, request_url)
            thumb_bytes = BytesIO(rsp.content)
            try:
                thumb = Image.open(thumb_bytes)
            finally:
                thumb_bytes.close()
            assert thumb.size == (250, 166)
Exemplo n.º 20
0
    def test_save_rois(self, conn, django_client):
        """Save new ROIs to an Image"""
        image = self.make_image(client=conn.c)
        roi = RoiI()
        roi.name = rstring("roi_name")
        roi.setImage(ImageI(image.id.val, False))
        point = PointI()
        point.x = rdouble(1)
        point.y = rdouble(2)

        encoder = get_encoder(point.__class__)
        point_json = encoder.encode(point)
        unsaved_id = "-1:-1"
        point_json['oldId'] = unsaved_id
        persist_url = reverse('omero_iviewer_persist_rois')
        data = {
            'imageId': image.id.val,
            'rois': {
                'count': 1,
                'new': [point_json]
            }
        }
        rsp = post_json(django_client, persist_url, data)
        print('rsp', rsp)
        # {"ids": {"-1:-1": "225504:416603"}}
        assert "ids" in rsp
        new_ids = rsp["ids"].values()
        assert len(new_ids) == 1
        new_id = rsp["ids"][unsaved_id]
        roi_id = int(new_id.split(':')[0])
        shape_id = int(new_id.split(':')[1])

        # Add Tag to ROI and Shape
        tag = TagAnnotationWrapper(conn)
        tag.setValue("ROI/Shape Tag")
        tag.save()
        roi = conn.getObject("Roi", roi_id)
        roi.linkAnnotation(tag)
        shape = conn.getObject("Shape", shape_id)
        shape.linkAnnotation(tag)
        # check...
        assert len(list(conn.getAnnotationLinks(
            "Shape", parent_ids=[shape_id]))) == 1

        # Load Shape
        rois_url = reverse('api_rois', kwargs={'api_version': 0})
        rois_url += '?image=%s' % image.id.val
        rsp = get_json(django_client, rois_url)
        assert len(rsp['data']) == 1

        # Edit Shape
        point_json = rsp['data'][0]['shapes'][0]
        point_json["X"] = 100
        point_json["Y"] = 200
        # iviewer wants to know ROI:Shape ID
        point_json["oldId"] = new_id
        # Unload details
        del point_json["omero:details"]
        data = {
            'imageId': image.id.val,
            'rois': {
                'count': 1,
                'modified': [point_json]
            }
        }
        rsp = post_json(django_client, persist_url, data)
        # IDs shouldn't have changed, e.g.
        # {"ids": {"225504:416603": "225504:416603"}}
        print('post rsp', rsp)
        assert rsp["ids"][new_id] == new_id

        # Check annotations not lost
        roi = conn.getObject("Roi", roi_id)
        assert len(list(roi.listAnnotations())) == 1
        assert len(list(conn.getAnnotationLinks(
            "Shape", parent_ids=[shape_id]))) == 1
Exemplo n.º 21
0
 def parse_and_populate_roi(self, columns_as_list):
     # First sanity check our provided columns
     names = [column.name for column in columns_as_list]
     log.debug('Parsing columns: %r' % names)
     cells_expected = [name in names for name in self.CELLS_CG_EXPECTED]
     nuclei_expected = [name in names for name in self.NUCLEI_CG_EXPECTED]
     if (False in cells_expected) and (False in nuclei_expected):
         log.warn("Missing CGs for InCell dataset: %r" % names)
         log.warn('Removing resultant empty ROI column.')
         for column in columns_as_list:
             if RoiColumn == column.__class__:
                 columns_as_list.remove(column)
         return
     # Reconstruct a column name to column map
     columns = dict()
     for column in columns_as_list:
         columns[column.name] = column
     image_ids = columns['Image'].values
     rois = list()
     # Save our file annotation to the database so we can use an unloaded
     # annotation for the saveAndReturnIds that will be triggered below.
     self.file_annotation = \
         self.update_service.saveAndReturnObject(self.file_annotation)
     unloaded_file_annotation = \
         FileAnnotationI(self.file_annotation.id.val, False)
     # Parse and append ROI
     batch_no = 1
     batches = dict()
     for i, image_id in enumerate(image_ids):
         unloaded_image = ImageI(image_id, False)
         if False in nuclei_expected:
             # Cell centre of gravity
             roi = RoiI()
             shape = PointI()
             shape.theZ = rint(0)
             shape.theT = rint(0)
             shape.cx = rdouble(float(columns['Cell: cgX'].values[i]))
             shape.cy = rdouble(float(columns['Cell: cgY'].values[i]))
             roi.addShape(shape)
             roi.image = unloaded_image
             roi.linkAnnotation(unloaded_file_annotation)
             rois.append(roi)
         elif False in cells_expected:
             # Nucleus centre of gravity
             roi = RoiI()
             shape = PointI()
             shape.theZ = rint(0)
             shape.theT = rint(0)
             shape.cx = rdouble(float(columns['Nucleus: cgX'].values[i]))
             shape.cy = rdouble(float(columns['Nucleus: cgY'].values[i]))
             roi.addShape(shape)
             roi.image = unloaded_image
             roi.linkAnnotation(unloaded_file_annotation)
             rois.append(roi)
         else:
             raise MeasurementError('Not a nucleus or cell ROI')
         if len(rois) == self.ROI_UPDATE_LIMIT:
             thread_pool.add_task(self.update_rois, rois, batches, batch_no)
             rois = list()
             batch_no += 1
     thread_pool.add_task(self.update_rois, rois, batches, batch_no)
     thread_pool.wait_completion()
     batch_keys = batches.keys()
     batch_keys.sort()
     for k in batch_keys:
         columns['ROI'].values += batches[k]
Exemplo n.º 22
0
params.addId(image_id_src)

count = 0

for mask_src in query_service.findAllByQuery(query, params):
    mask_dst = MaskI()
    mask_dst.x = mask_src.x
    mask_dst.y = mask_src.y
    mask_dst.width = mask_src.width
    mask_dst.height = mask_src.height
    mask_dst.theZ = mask_src.theZ
    mask_dst.theC = mask_src.theC
    mask_dst.theT = mask_src.theT
    mask_dst.bytes = mask_src.bytes
    mask_dst.fillColor = mask_src.fillColor
    mask_dst.transform = mask_src.transform
    roi_dst = RoiI()
    roi_dst.description = rstring(
        "created by copy-masks script for original mask #{}".format(
            mask_src.id.val))
    roi_dst.image = ImageI(image_id_dst, False)
    roi_dst.addShape(mask_dst)
    update_service.saveObject(roi_dst)
    count += 1

idr._closeSession()
local._closeSession()

print("from image #{} to #{}, mask count = {}".format(image_id_src,
                                                      image_id_dst, count))
Exemplo n.º 23
0
    def image_rois(self, user1, shapes):
        """Return Image with ROIs."""
        image = ImageI()
        image.name = rstring('Image for ROIs')
        image = get_update_service(user1).saveAndReturnObject(image)

        # ROI with all but one shapes
        rois = []
        roi = RoiI()
        for shape in shapes[:-1]:
            roi.addShape(shape)
        roi.setImage(image)
        rois.append(roi)

        # roi without shapes
        roi = RoiI()
        roi.setImage(image)
        rois.append(roi)

        # roi without image
        roi = RoiI()
        roi.addShape(shapes[-1])
        rois.append(roi)

        rois = get_update_service(user1).saveAndReturnArray(rois)
        rois.sort(key=lambda x: x.id.val)
        return image, rois
Exemplo n.º 24
0
 def parse_and_populate_roi(self, columns_as_list):
     # First sanity check our provided columns
     names = [column.name for column in columns_as_list]
     log.debug('Parsing columns: %r' % names)
     cells_expected = [name in names for name in self.CELLS_CG_EXPECTED]
     nuclei_expected = [name in names for name in self.NUCLEI_CG_EXPECTED]
     if (False in cells_expected) and (False in nuclei_expected):
         log.warn("Missing CGs for InCell dataset: %r" % names)
         log.warn('Removing resultant empty ROI column.')
         for column in columns_as_list:
             if RoiColumn == column.__class__:
                 columns_as_list.remove(column)
         return
     # Reconstruct a column name to column map
     columns = dict()
     for column in columns_as_list:
         columns[column.name] = column
     image_ids = columns['Image'].values
     rois = list()
     # Save our file annotation to the database so we can use an unloaded
     # annotation for the saveAndReturnIds that will be triggered below.
     self.file_annotation = \
         self.update_service.saveAndReturnObject(self.file_annotation)
     unloaded_file_annotation = \
         FileAnnotationI(self.file_annotation.id.val, False)
     # Parse and append ROI
     batch_no = 1
     batches = dict()
     for i, image_id in enumerate(image_ids):
         unloaded_image = ImageI(image_id, False)
         if False in nuclei_expected:
             # Cell centre of gravity
             roi = RoiI()
             shape = PointI()
             shape.theZ = rint(0)
             shape.theT = rint(0)
             shape.cx = rdouble(float(columns['Cell: cgX'].values[i]))
             shape.cy = rdouble(float(columns['Cell: cgY'].values[i]))
             roi.addShape(shape)
             roi.image = unloaded_image
             roi.linkAnnotation(unloaded_file_annotation)
             rois.append(roi)
         elif False in cells_expected:
             # Nucleus centre of gravity
             roi = RoiI()
             shape = PointI()
             shape.theZ = rint(0)
             shape.theT = rint(0)
             shape.cx = rdouble(float(columns['Nucleus: cgX'].values[i]))
             shape.cy = rdouble(float(columns['Nucleus: cgY'].values[i]))
             roi.addShape(shape)
             roi.image = unloaded_image
             roi.linkAnnotation(unloaded_file_annotation)
             rois.append(roi)
         else:
             raise MeasurementError('Not a nucleus or cell ROI')
         if len(rois) == self.ROI_UPDATE_LIMIT:
             self.thread_pool.add_task(
                 self.update_rois, rois, batches, batch_no)
             rois = list()
             batch_no += 1
     self.thread_pool.add_task(self.update_rois, rois, batches, batch_no)
     self.thread_pool.wait_completion()
     batch_keys = batches.keys()
     batch_keys.sort()
     for k in batch_keys:
         columns['ROI'].values += batches[k]