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]
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 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]
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
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]