def write_to_omero(self):
     sf = self.client.getSession()
     group = str(self.value_resolver.target_object.details.group.id.val)
     sr = sf.sharedResources()
     update_service = sf.getUpdateService()
     name = 'bulk_annotations'
     table = sr.newTable(1, name, {'omero.group': group})
     if table is None:
         raise MetadataError(
             "Unable to create table: %s" % name)
     original_file = table.getOriginalFile()
     log.info('Created new table OriginalFile:%d' % original_file.id.val)
     table.initialize(self.columns)
     log.info('Table initialized with %d columns.' % (len(self.columns)))
     table.addData(self.columns)
     log.info('Added data column data.')
     table.close()
     file_annotation = FileAnnotationI()
     file_annotation.ns = \
             rstring('openmicroscopy.org/omero/bulk_annotations')
     file_annotation.description = rstring(name)
     file_annotation.file = OriginalFileI(original_file.id.val, False)
     link = self.create_annotation_link()
     link.parent = self.target_object
     link.child = file_annotation
     update_service.saveObject(link, {'omero.group': group})
    def testPopulateRoisPlate(self):
        """
            Create a small csv file, use populate_roi.py to parse and
            attach to Plate. Then query to check table has expected content.
        """

        csvName = self.createCsv(colNames="Well,Field,X,Y,Type",
                                 rowData=("A1,0,15,15,Test", ))

        rowCount = 1
        colCount = 1
        plate = self.createPlate(rowCount, colCount)

        # As opposed to the ParsingContext, here we are expected
        # to link the file ourselves
        ofile = self.client.upload(csvName).proxy()
        ann = FileAnnotationI()
        ann.file = ofile
        link = PlateAnnotationLinkI()
        link.parent = plate.proxy()
        link.child = ann
        link = self.client.sf.getUpdateService()\
            .saveAndReturnObject(link)
        # End linking

        factory = PlateAnalysisCtxFactory(self.client.sf)
        factory.implementations = (MockPlateAnalysisCtx, )
        ctx = factory.get_analysis_ctx(plate.id.val)
        assert 1 == ctx.get_measurement_count()
        meas = ctx.get_measurement_ctx(0)
        meas.parse_and_populate()

        # Get file annotations
        query = """select p from Plate p
            left outer join fetch p.annotationLinks links
            left outer join fetch links.child as ann
            left outer join fetch ann.file as file
            where p.id=%s""" % plate.id.val
        qs = self.client.sf.getQueryService()
        plate = qs.findByQuery(query, None)
        anns = plate.linkedAnnotationList()
        # Only expect a single annotation which is a 'bulk annotation'
        # the other is the original CSV
        assert len(anns) == 2
        files = dict([(a.ns.val, a.file.id.val) for a in anns if a.ns])
        fileid = files[NSMEASUREMENT]

        # Open table to check contents
        r = self.client.sf.sharedResources()
        t = r.openTable(OriginalFileI(fileid), None)
        cols = t.getHeaders()
        rows = t.getNumberOfRows()
        assert rows == 1

        data = t.read(range(len(cols)), 0, 1)
        imag = data.columns[0].values[0]
        rois = self.client.sf.getRoiService()
        anns = rois.getRoiMeasurements(imag, RoiOptions())
        assert anns
def create_file_annotation():
    '''
    Creates a file annotation to represent a set of columns from our
    measurment.
    '''
    file_annotation = FileAnnotationI()
    file_annotation.ns = rstring(NS)
    return file_annotation
Beispiel #4
0
    def test_file_annotation(self):
        """Tests AnnotationWrapper methods return strings"""
        file_name = u'₩€_file_$$'
        f = OriginalFileI()
        f.name = rstring(file_name)
        obj = FileAnnotationI()
        obj.file = f

        file_ann = MockConnection(obj).getObject("Annotation", 1)
        assert file_ann.getFileName() == file_name.encode('utf8')
def create_figure_file(conn, figure_json, figure_name):
    """Create Figure FileAnnotation from json data."""
    if len(figure_json['panels']) == 0:
        raise Exception('No Panels')
    first_img_id = figure_json['panels'][0]['imageId']

    # we store json in description field...
    description = {}
    description['name'] = figure_name
    description['imageId'] = first_img_id

    # Try to set Group context to the same as first image
    conn.SERVICE_OPTS.setOmeroGroup('-1')
    i = conn.getObject("Image", first_img_id)
    gid = i.getDetails().getGroup().getId()
    conn.SERVICE_OPTS.setOmeroGroup(gid)

    json_bytes = json.dumps(figure_json).encode('utf-8')
    file_size = len(json_bytes)
    f = BytesIO()
    try:
        f.write(json_bytes)

        update = conn.getUpdateService()
        orig_file = conn.createOriginalFileFromFileObj(
            f, '', figure_name, file_size, mimetype="application/json")
    finally:
        f.close()
    fa = FileAnnotationI()
    fa.setFile(OriginalFileI(orig_file.getId(), False))
    fa.setNs(rstring(JSON_FILEANN_NS))
    desc = json.dumps(description)
    fa.setDescription(rstring(desc))
    fa = update.saveAndReturnObject(fa, conn.SERVICE_OPTS)
    return fa.getId().getValue()
Beispiel #6
0
 def create_file_annotation(self, set_of_columns):
     """
     Creates a file annotation to represent a set of columns from our
     measurment.
     """
     self.file_annotation = FileAnnotationI()
     self.file_annotation.ns = \
         rstring('openmicroscopy.org/omero/measurement')
     name = self.get_name(set_of_columns)
     self.file_annotation.description = rstring(name)
    def make_file_annotation(self, name=None, binary=None, format=None, client=None, ns=None):
        """
        Creates a new DatasetI instance and returns the persisted object.
        If no name has been provided, a UUID string shall be used.

        :param name: the name of the project
        :param client: The client to use to create the object
        :param ns: The namespace for the annotation
        """

        if client is None:
            client = self.client
        update = client.sf.getUpdateService()

        # file
        if format is None:
            format = "application/octet-stream"
        if binary is None:
            binary = "12345678910"
        if name is None:
            name = str(self.uuid())

        oFile = OriginalFileI()
        oFile.setName(rstring(name))
        oFile.setPath(rstring(str(self.uuid())))
        oFile.setSize(rlong(len(binary)))
        oFile.hasher = ChecksumAlgorithmI()
        oFile.hasher.value = rstring("SHA1-160")
        oFile.setMimetype(rstring(str(format)))
        oFile = update.saveAndReturnObject(oFile)

        # save binary
        store = client.sf.createRawFileStore()
        store.setFileId(oFile.id.val)
        store.write(binary, 0, 0)
        oFile = store.save()  # See ticket:1501
        store.close()

        fa = FileAnnotationI()
        fa.setFile(oFile)
        if ns is not None:
            fa.setNs(rstring(ns))
        return update.saveAndReturnObject(fa)
Beispiel #8
0
    def make_file_annotation(self,
                             name=None,
                             binary=None,
                             format=None,
                             client=None):
        """
        Creates a new DatasetI instance and returns the persisted object.
        If no name has been provided, a UUID string shall be used.

        :param name: the name of the project
        :param client: The client to use to create the object
        """

        if client is None:
            client = self.client
        update = client.sf.getUpdateService()

        # file
        if format is None:
            format = "application/octet-stream"
        if binary is None:
            binary = "12345678910"

        oFile = OriginalFileI()
        oFile.setName(rstring(str(self.uuid())))
        oFile.setPath(rstring(str(self.uuid())))
        oFile.setSize(rlong(len(binary)))
        oFile.hasher = ChecksumAlgorithmI()
        oFile.hasher.value = rstring("SHA1-160")
        oFile.setMimetype(rstring(str(format)))
        oFile = update.saveAndReturnObject(oFile)

        # save binary
        store = client.sf.createRawFileStore()
        store.setFileId(oFile.id.val)
        store.write(binary, 0, 0)
        oFile = store.save()  # See ticket:1501
        store.close()

        fa = FileAnnotationI()
        fa.setFile(oFile)
        return update.saveAndReturnObject(fa)
Beispiel #9
0
    def upload(self, args):
        client = self.ctx.conn(args)
        obj_ids = []
        for local_file in args.file:
            if not path(local_file).exists():
                self.ctx.die(500, "File: %s does not exist" % local_file)
        for local_file in args.file:
            omero_format = UNKNOWN
            if args.mimetype:
                omero_format = args.mimetype
            elif (mimetypes.guess_type(local_file) != (None, None)):
                omero_format = mimetypes.guess_type(local_file)[0]
            if args.data_dir:
                obj = upload_ln_s(client, local_file, args.data_dir,
                                  omero_format)
                obj_id = obj.id
            else:
                obj = client.upload(local_file, type=omero_format)
                obj_id = obj.id.val
            if args.wrap:
                fa = FileAnnotationI()
                fa.setFile(OriginalFileI(obj_id, False))
                if args.namespace:
                    fa.setNs(rstring(args.namespace))
                fa = client.sf.getUpdateService().saveAndReturnObject(fa)
                obj_ids.append(fa.id.val)
            else:
                obj_ids.append(obj_id)
            self.ctx.set("last.upload.id", obj_id)

        obj_ids = self._order_and_range_ids(obj_ids)
        if args.wrap:
            self.ctx.out("FileAnnotation:%s" % obj_ids)
        else:
            self.ctx.out("OriginalFile:%s" % obj_ids)
Beispiel #10
0
def upload_and_link(conn, attachment, project):
    fo = upload_ln_s(conn.c, attachment, OMERO_DATA_DIR, MIMETYPE)
    fa = FileAnnotationI()
    fa.setFile(fo._obj)
    fa.setNs(omero.rtypes.rstring(NAMESPACE))
    fa = conn.getUpdateService().saveAndReturnObject(fa)
    fa = omero.gateway.FileAnnotationWrapper(conn, fa)
    project.linkAnnotation(fa)
def plate_well_table(itest, well_grid_factory, update_service, conn):
    """
    Returns a new OMERO Plate, linked Wells, linked WellSamples, and linked
    Images populated by an L{weblibrary.IWebTest} instance.
    """
    plate = PlateI()
    plate.name = rstring(itest.uuid())
    # Well A1 has one WellSample
    plate.addWell(well_grid_factory({(0, 0): 1})[0])
    plate = update_service.saveAndReturnObject(plate)

    col1 = WellColumn('Well', '', [])
    col2 = StringColumn('TestColumn', '', 64, [])

    columns = [col1, col2]
    tablename = "plate_well_table_test:%s" % str(random())
    table = conn.c.sf.sharedResources().newTable(1, tablename)
    table.initialize(columns)

    wellIds = [w.id.val for w in plate.copyWells()]
    print "WellIds", wellIds

    data1 = WellColumn('Well', '', wellIds)
    data2 = StringColumn('TestColumn', '', 64, ["foobar"])
    data = [data1, data2]
    table.addData(data)
    table.close()

    orig_file = table.getOriginalFile()
    fileAnn = FileAnnotationI()
    fileAnn.ns = rstring('openmicroscopy.org/omero/bulk_annotations')
    fileAnn.setFile(OriginalFileI(orig_file.id.val, False))
    fileAnn = conn.getUpdateService().saveAndReturnObject(fileAnn)
    link = PlateAnnotationLinkI()
    link.setParent(PlateI(plate.id.val, False))
    link.setChild(FileAnnotationI(fileAnn.id.val, False))
    update_service.saveAndReturnObject(link)
    return plate, wellIds
Beispiel #12
0
def upload_csv_to_omero(ctx,
                        file,
                        tablename,
                        target_id,
                        target_type="Project"):
    """Upload the CSV file and attach it to the specified object"""
    print file
    print file.name
    svc = gateway.getFacility(DataManagerFacility)
    file_size = os.path.getsize(file.name)
    original_file = OriginalFileI()
    original_file.setName(rstring(tablename))
    original_file.setPath(rstring(file.name))
    original_file.setSize(rlong(file_size))

    checksum_algorithm = ChecksumAlgorithmI()
    checksum_algorithm.setValue(rstring(ChecksumAlgorithmSHA1160.value))
    original_file.setHasher(checksum_algorithm)
    original_file.setMimetype(rstring("text/csv"))
    original_file = svc.saveAndReturnObject(ctx, original_file)
    store = gateway.getRawFileService(ctx)

    # Open file and read stream
    store.setFileId(original_file.getId().getValue())
    print original_file.getId().getValue()
    try:
        store.setFileId(original_file.getId().getValue())
        with open(file.name, 'rb') as stream:
            buf = 10000
            for pos in range(0, long(file_size), buf):
                block = None
                if file_size - pos < buf:
                    block_size = file_size - pos
                else:
                    block_size = buf
                stream.seek(pos)
                block = stream.read(block_size)
                store.write(block, pos, block_size)

        original_file = store.save()
    finally:
        store.close()

    # create the file annotation
    namespace = "training.demo"
    fa = FileAnnotationI()
    fa.setFile(original_file)
    fa.setNs(rstring(namespace))

    if target_type == "Project":
        target_obj = ProjectData(ProjectI(target_id, False))
    elif target_type == "Dataset":
        target_obj = DatasetData(DatasetI(target_id, False))
    elif target_type == "Image":
        target_obj = ImageData(ImageI(target_id, False))

    svc.attachAnnotation(ctx, FileAnnotationData(fa), target_obj)
Beispiel #13
0
def upload_and_link(conn, target, attachment):
    print("upload_and_link", attachment)
    attachment = os.path.join(FILESETS_DIR, attachment)
    fo = upload_ln_s(conn.c, attachment, OMERO_DATA_DIR, MIMETYPE)
    fa = FileAnnotationI()
    fa.setFile(fo._obj)
    fa.setNs(omero.rtypes.rstring(NAMESPACE))
    fa = conn.getUpdateService().saveAndReturnObject(fa)
    fa = omero.gateway.FileAnnotationWrapper(conn, fa)
    target.linkAnnotation(fa)
def upload_and_link(conn, attachment, image):
    fa = image.getAnnotation(ns=NAMESPACE)
    if fa is not None:
        log.warning("Found file annotation. Skipping upload")
        return
    log.info("Uploading and linking %s to %s" % (attachment, image.getName()))
    fo = upload_ln_s(conn.c, attachment, OMERO_DATA_DIR, MIMETYPE)
    fa = FileAnnotationI()
    fa.setFile(fo._obj)
    fa.setNs(omero.rtypes.rstring(NAMESPACE))
    fa = conn.getUpdateService().saveAndReturnObject(fa)
    fa = omero.gateway.FileAnnotationWrapper(conn, fa)
    image.linkAnnotation(fa)
Beispiel #15
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]
Beispiel #16
0
def save_microscope(request, conn=None, **kwargs):

    body_json = json.loads(request.body)
    microscope_json = body_json['microscope']

    file_name = microscope_json["Name"]

    project = conn.getObject("Project", attributes={'name': PROJECT_NAME})

    curr_gid = conn.SERVICE_OPTS.getOmeroGroup()

    if project is not None:
        gid = project.getDetails().getGroup().getId()
        conn.SERVICE_OPTS.setOmeroGroup(gid)
    else:
        # TODO: create Project
        conn.SERVICE_OPTS.setOmeroGroup(curr_gid)

    update = conn.getUpdateService()

    file_data = json.dumps(microscope_json)
    file_size = len(file_data)
    f = BytesIO()
    f.write(file_data.encode("utf-8"))
    orig_file = conn.createOriginalFileFromFileObj(f,
                                                   '',
                                                   file_name,
                                                   file_size,
                                                   mimetype="application/json")
    fa = FileAnnotationI()
    fa.setFile(OriginalFileI(orig_file.getId(), False))
    fa.setNs(wrap(JSON_FILEANN_NS))
    # fa.setDescription(wrap(desc))
    fa = update.saveAndReturnObject(fa, conn.SERVICE_OPTS)
    file_id = fa.getId().getValue()

    if project is not None:
        fa_wrapper = FileAnnotationWrapper(conn, fa)
        project.linkAnnotation(fa_wrapper)

    return JsonResponse({'file_id': file_id})
Beispiel #17
0
def plate_well_table(itest, well_grid_factory, update_service, conn):
    """
    Returns a new OMERO Plate, linked Wells, linked WellSamples, and linked
    Images populated by an L{omeroweb.testlib.IWebTest} instance.
    """
    plate = PlateI()
    plate.name = rstring(itest.uuid())
    # Well A1 has one WellSample
    plate.addWell(well_grid_factory({(0, 0): 1})[0])
    plate = update_service.saveAndReturnObject(plate)

    col1 = WellColumn('Well', '', [])
    col2 = StringColumn('TestColumn', '', 64, [])

    columns = [col1, col2]
    tablename = "plate_well_table_test:%s" % str(random())
    table = conn.c.sf.sharedResources().newTable(1, tablename)
    table.initialize(columns)

    wellIds = [w.id.val for w in plate.copyWells()]
    print("WellIds", wellIds)

    data1 = WellColumn('Well', '', wellIds)
    data2 = StringColumn('TestColumn', '', 64, ["foobar"])
    data = [data1, data2]
    table.addData(data)

    orig_file = table.getOriginalFile()
    table.close()

    fileAnn = FileAnnotationI()
    fileAnn.ns = rstring('openmicroscopy.org/omero/bulk_annotations')
    fileAnn.setFile(OriginalFileI(orig_file.id.val, False))
    fileAnn = conn.getUpdateService().saveAndReturnObject(fileAnn)
    link = PlateAnnotationLinkI()
    link.setParent(PlateI(plate.id.val, False))
    link.setChild(FileAnnotationI(fileAnn.id.val, False))
    update_service.saveAndReturnObject(link)
    return plate, wellIds
Beispiel #18
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]
import omero.callbacks
from omero.rtypes import rstring
from omero.model import DatasetI, FileAnnotationI, OriginalFileI
from omero.model import DatasetAnnotationLinkI

c = omero.client()
ice_config = c.getProperty("Ice.Config")

try:
    s = c.createSession()
    d = DatasetI()
    d.setName(rstring("FileAnnotationDelete"))
    d = s.getUpdateService().saveAndReturnObject(d)

    file = c.upload(ice_config)
    fa = FileAnnotationI()
    fa.setFile(OriginalFileI(file.id.val, False))
    link = DatasetAnnotationLinkI()
    link.parent = DatasetI(d.id.val, False)
    link.child = fa
    link = s.getUpdateService().saveAndReturnObject(link)
    fa = link.child

    to_delete = {"Annotation": [fa.id.val]}
    delCmd = omero.cmd.Delete2(targetObjects=to_delete)

    handle = s.submit(delCmd)

    callback = None
    try:
        callback = omero.callbacks.CmdCallbackI(c, handle)
Beispiel #20
0
def save_web_figure(conn, json_data):
    """
    Saves 'figureJSON' in POST as an original file. If 'fileId' is specified
    in POST, then we update that file. Otherwise create a new one with
    name 'figureName' from POST.
    """
    image_ids = []
    first_img_id = None
    try:
        for panel in json_data['panels']:
            image_ids.append(panel['imageId'])
        if len(image_ids) > 0:
            first_img_id = int(image_ids[0])
        # remove duplicates
        image_ids = list(set(image_ids))
        # pretty-print json
        figure_json = json.dumps(json_data,
                                 sort_keys=True,
                                 indent=2,
                                 separators=(',', ': '))
    except Exception:
        pass

    # See https://github.com/will-moore/figure/issues/16
    figure_json = figure_json.encode('utf8')

    if 'figureName' in json_data and len(json_data['figureName']) > 0:
        figure_name = json_data['figureName']
    else:
        print("No figure name found")
        return

    # we store json in description field...
    description = {}
    if first_img_id is not None:
        # We duplicate the figure name here for quicker access when
        # listing files
        # (use this instead of file name because it supports unicode)
        description['name'] = figure_name
        description['imageId'] = first_img_id
        if 'baseUrl' in panel:
            description['baseUrl'] = panel['baseUrl']
    desc = json.dumps(description)

    # Create new file
    # Try to set Group context to the same as first image
    curr_gid = conn.SERVICE_OPTS.getOmeroGroup()
    i = None
    if first_img_id:
        i = conn.getObject("Image", first_img_id)
    if i is not None:
        gid = i.getDetails().getGroup().getId()
        conn.SERVICE_OPTS.setOmeroGroup(gid)
    else:
        # Don't leave as -1
        conn.SERVICE_OPTS.setOmeroGroup(curr_gid)
    file_size = len(figure_json)
    f = BytesIO()
    f.write(figure_json)
    orig_file = conn.createOriginalFileFromFileObj(f,
                                                   '',
                                                   figure_name,
                                                   file_size,
                                                   mimetype="application/json")
    fa = FileAnnotationI()
    fa.setFile(OriginalFileI(orig_file.getId(), False))
    fa.setNs(wrap(JSON_FILEANN_NS))
    fa.setDescription(wrap(desc))

    update = conn.getUpdateService()
    fa = update.saveAndReturnObject(fa, conn.SERVICE_OPTS)
    ann_id = fa.getId().getValue()
    return ann_id
    def testPopulateRoisPlate(self):
        """
            Create a small csv file, use populate_roi.py to parse and
            attach to Plate. Then query to check table has expected content.
        """

        csvName = self.createCsv(
            colNames="Well,Field,X,Y,Type",
            rowData=("A1,0,15,15,Test",))

        rowCount = 1
        colCount = 1
        plate = self.createPlate(rowCount, colCount)

        # As opposed to the ParsingContext, here we are expected
        # to link the file ourselves
        ofile = self.client.upload(csvName).proxy()
        ann = FileAnnotationI()
        ann.file = ofile
        link = PlateAnnotationLinkI()
        link.parent = plate.proxy()
        link.child = ann
        link = self.client.sf.getUpdateService()\
            .saveAndReturnObject(link)
        # End linking

        factory = PlateAnalysisCtxFactory(self.client.sf)
        factory.implementations = (MockPlateAnalysisCtx,)
        ctx = factory.get_analysis_ctx(plate.id.val)
        assert 1 == ctx.get_measurement_count()
        meas = ctx.get_measurement_ctx(0)
        meas.parse_and_populate()

        # Get file annotations
        query = """select p from Plate p
            left outer join fetch p.annotationLinks links
            left outer join fetch links.child as ann
            left outer join fetch ann.file as file
            where p.id=%s""" % plate.id.val
        qs = self.client.sf.getQueryService()
        plate = qs.findByQuery(query, None)
        anns = plate.linkedAnnotationList()
        # Only expect a single annotation which is a 'bulk annotation'
        # the other is the original CSV
        assert len(anns) == 2
        files = dict(
            [(a.ns.val, a.file.id.val) for a in anns if a.ns])
        fileid = files[NSMEASUREMENT]

        # Open table to check contents
        r = self.client.sf.sharedResources()
        t = r.openTable(OriginalFileI(fileid), None)
        cols = t.getHeaders()
        rows = t.getNumberOfRows()
        assert rows == 1

        data = t.read(range(len(cols)), 0, 1)
        imag = data.columns[0].values[0]
        rois = self.client.sf.getRoiService()
        anns = rois.getRoiMeasurements(imag, RoiOptions())
        assert anns