def test_new_format_new_method(self): xy_list = points_string_to_xy_list(("1,2 3,4 5,6")) assert xy_list == [(1, 2), (3, 4), (5, 6)]
def test_old_format_new_method(self): xy_list = points_string_to_xy_list(("points[1,2, 3,4, 5,6] ")) assert xy_list == [(1, 2), (3, 4), (5, 6)]
def test_bbox(self): xy_list = points_string_to_xy_list(("points[1,2, 3,4, 5,6] ")) bbox = xyListToBbox(xy_list) assert bbox == (1, 2, 4, 4)
def process_images(conn, script_params): file_anns = [] message = "" # Get the images images, log_message = script_utils.get_objects(conn, script_params) message += log_message if not images: return None, message # Check for line and polyline ROIs and filter images list images = [ image for image in images if image.getROICount(["Polyline", "Line"]) > 0 ] if not images: message += "No ROI containing line or polyline was found." return None, message csv_data = [] for image in images: if image.getSizeT() > 1: message += "%s ID: %s appears to be a time-lapse Image," \ " not a kymograph." % (image.getName(), image.getId()) continue roi_service = conn.getRoiService() result = roi_service.findByImage(image.getId(), None) secs_per_pixel_y = image.getPixelSizeY() microns_per_pixel_x = image.getPixelSizeX() if secs_per_pixel_y and microns_per_pixel_x: microns_per_sec = microns_per_pixel_x / secs_per_pixel_y else: microns_per_sec = None # for each line or polyline, create a row in csv table: y(t), x, # dy(dt), dx, x/t (line), x/t (average) col_names = "\nt_start (pixels), x_start (pixels), t_end (pixels)," \ " x_end (pixels), dt (pixels), dx (pixels), x/t, speed(um/sec)," \ "avg x/t, avg speed(um/sec)" table_data = "" for roi in result.rois: for s in roi.copyShapes(): if s is None: continue # seems possible in some situations if type(s) == omero.model.LineI: table_data += "\nLine ID: %s" % s.getId().getValue() x1 = s.getX1().getValue() x2 = s.getX2().getValue() y1 = s.getY1().getValue() y2 = s.getY2().getValue() dx = abs(x1 - x2) dy = abs(y1 - y2) dx_per_y = float(dx) / dy speed = "" if microns_per_sec: speed = dx_per_y * microns_per_sec table_data += "\n" table_data += ",".join([ str(x) for x in (y1, x1, y2, x2, dy, dx, dx_per_y, speed) ]) elif type(s) == omero.model.PolylineI: table_data += "\nPolyline ID: %s" % s.getId().getValue() v = s.getPoints().getValue() points = roi_utils.points_string_to_xy_list(v) x_start, y_start = points[0] for i in range(1, len(points)): x1, y1 = points[i - 1] x2, y2 = points[i] dx = abs(x1 - x2) dy = abs(y1 - y2) dx_per_y = float(dx) / dy av_x_per_y = abs(float(x2 - x_start) / (y2 - y_start)) speed = "" avg_speed = "" if microns_per_sec: speed = dx_per_y * microns_per_sec avg_speed = av_x_per_y * microns_per_sec table_data += "\n" table_data += ",".join([ str(x) for x in (y1, x1, y2, x2, dy, dx, dx_per_y, speed, av_x_per_y, avg_speed) ]) # write table data to csv... if len(table_data) > 0: table_string = "Image ID:, %s," % image.getId() table_string += "Name:, %s" % image.getName() table_string += "\nsecsPerPixelY: %s" % secs_per_pixel_y table_string += '\nmicronsPerPixelX: %s' % microns_per_pixel_x table_string += "\n" table_string += col_names table_string += table_data csv_data.append(table_string) iids = [str(i.getId()) for i in images] to_link_csv = [i.getId() for i in images if i.canAnnotate()] csv_file_name = 'kymograph_velocities_%s.csv' % "-".join(iids) with open(csv_file_name, 'w') as csv_file: csv_file.write("\n \n".join(csv_data)) file_ann = conn.createFileAnnfromLocalFile(csv_file_name, mimetype="text/csv") fa_message = "Created Line Plot csv (Excel) file" links = [] if len(to_link_csv) == 0: fa_message += " but could not attach to images." for iid in to_link_csv: link = ImageAnnotationLinkI() link.parent = ImageI(iid, False) link.child = file_ann._obj links.append(link) if len(links) > 0: links = conn.getUpdateService().saveAndReturnArray(links) if file_ann: file_anns.append(file_ann) if not file_anns: fa_message = "No Analysis files created. See 'Info' or 'Error'" \ " for more details" elif len(file_anns) > 1: fa_message = "Created %s csv (Excel) files" % len(file_anns) message += fa_message return file_anns, message
def process_images(conn, script_params): line_width = script_params['Line_Width'] new_kymographs = [] message = "" # Get the images images, log_message = script_utils.get_objects(conn, script_params) message += log_message if not images: return None, message # Check for line and polyline ROIs and filter images list images = [ image for image in images if image.getROICount(["Polyline", "Line"]) > 0 ] if not images: message += "No ROI containing line or polyline was found." return None, message for image in images: if image.getSizeT() == 1: continue new_images = [] # kymographs derived from the current image. c_names = [] colors = [] for ch in image.getChannels(): c_names.append(ch.getLabel()) colors.append(ch.getColor().getRGB()) size_t = image.getSizeT() pixels = image.getPrimaryPixels() dataset = image.getParent() if dataset is not None and not dataset.canLink(): dataset = None roi_service = conn.getRoiService() result = roi_service.findByImage(image.getId(), None) # kymograph strategy - Using Line and Polyline ROIs: # NB: Use ALL time points unless >1 shape AND 'use_all_timepoints' = # False # If > 1 shape per time-point (per ROI), pick one! # 1 - Single line. Use this shape for all time points # 2 - Many lines. Use the first one to fix length. Subsequent lines to # update start and direction # 3 - Single polyline. Use this shape for all time points # 4 - Many polylines. Use the first one to fix length. for roi in result.rois: lines = {} # map of theT: line polylines = {} # map of theT: polyline for s in roi.copyShapes(): if s is None: continue the_t = unwrap(s.getTheT()) the_z = unwrap(s.getTheZ()) z = 0 t = 0 if the_t is not None: t = the_t if the_z is not None: z = the_z # TODO: Add some filter of shapes. E.g. text? / 'lines' only # etc. if type(s) == omero.model.LineI: x1 = s.getX1().getValue() x2 = s.getX2().getValue() y1 = s.getY1().getValue() y2 = s.getY2().getValue() lines[t] = { 'theZ': z, 'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2 } elif type(s) == omero.model.PolylineI: v = s.getPoints().getValue() points = roi_utils.points_string_to_xy_list(v) polylines[t] = {'theZ': z, 'points': points} if len(lines) > 0: new_img = lines_kymograph(conn, script_params, image, lines, line_width, dataset) new_images.append(new_img) lines = [] elif len(polylines) > 0: new_img = polyline_kymograph(conn, script_params, image, polylines, line_width, dataset) new_images.append(new_img) # look-up the interval for each time-point t_interval = None infos = list(pixels.copyPlaneInfo(theC=0, theT=size_t - 1, theZ=0)) if len(infos) > 0 and infos[0].getDeltaT() is not None: duration = infos[0].getDeltaT(units="SECOND").getValue() if size_t == 1: t_interval = duration else: t_interval = duration / (size_t - 1) elif pixels.timeIncrement is not None: t_interval = pixels.timeIncrement elif "Time_Increment" in script_params: t_interval = script_params["Time_Increment"] pixel_size = None if pixels.physicalSizeX is not None: pixel_size = pixels.physicalSizeX elif "Pixel_Size" in script_params: pixel_size = script_params['Pixel_Size'] # Save channel names and colors for each new image for img in new_images: for i, c in enumerate(img.getChannels()): lc = c.getLogicalChannel() lc.setName(c_names[i]) lc.save() r, g, b = colors[i] # need to reload channels to avoid optimistic lock on update c_obj = conn.getQueryService().get("Channel", c.id) c_obj.red = omero.rtypes.rint(r) c_obj.green = omero.rtypes.rint(g) c_obj.blue = omero.rtypes.rint(b) c_obj.alpha = omero.rtypes.rint(255) conn.getUpdateService().saveObject(c_obj) img.resetRDefs() # reset based on colors above # If we know pixel sizes, set them on the new image if pixel_size is not None or t_interval is not None: px = conn.getQueryService().get("Pixels", img.getPixelsId()) microm = getattr(omero.model.enums.UnitsLength, "MICROMETER") if pixel_size is not None: pixel_size = omero.model.LengthI(pixel_size, microm) px.setPhysicalSizeX(pixel_size) if t_interval is not None: t_per_pixel = t_interval / line_width t_per_pixel = omero.model.LengthI(t_per_pixel, microm) px.setPhysicalSizeY(t_per_pixel) conn.getUpdateService().saveObject(px) new_kymographs.extend(new_images) if not new_kymographs: message += "No kymograph created. See 'Error' or 'Info' for details." else: if not dataset: link_message = " but could not be attached" else: link_message = "" if len(new_images) == 1: message += "New kymograph created%s: %s." \ % (link_message, new_images[0].getName()) elif len(new_images) > 1: message += "%s new kymographs created%s." \ % (len(new_images), link_message) return new_kymographs, message
def process_images(conn, script_params): line_width = script_params['Line_Width'] file_anns = [] message = "" # Get the images images, log_message = script_utils.get_objects(conn, script_params) message += log_message if not images: return None, message # Check for line and polyline ROIs and filter images list images = [image for image in images if image.getROICount(["Polyline", "Line"]) > 0] if not images: message += "No ROI containing line or polyline was found." return None, message for image in images: c_names = [] colors = [] for ch in image.getChannels(): c_names.append(ch.getLabel()) colors.append(ch.getColor().getRGB()) size_c = image.getSizeC() if 'Channels' in script_params: script_params['Channels'] = [i-1 for i in script_params['Channels']] else: script_params['Channels'] = range(size_c) roi_service = conn.getRoiService() result = roi_service.findByImage(image.getId(), None) lines = [] polylines = [] for roi in result.rois: roi_id = roi.getId().getValue() for s in roi.copyShapes(): the_t = unwrap(s.getTheT()) the_z = unwrap(s.getTheZ()) z = 0 t = 0 if the_t is not None: t = the_t if the_z is not None: z = the_z # TODO: Add some filter of shapes e.g. text? / 'lines' only # etc. if type(s) == omero.model.LineI: x1 = s.getX1().getValue() x2 = s.getX2().getValue() y1 = s.getY1().getValue() y2 = s.getY2().getValue() lines.append({'id': roi_id, 'theT': t, 'theZ': z, 'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2}) elif type(s) == omero.model.PolylineI: v = s.getPoints().getValue() points = roi_utils.points_string_to_xy_list(v) polylines.append({'id': roi_id, 'theT': t, 'theZ': z, 'points': points}) if len(lines) == 0 and len(polylines) == 0: continue # prepare column headers, including line-id if we are going to output # raw data. line_id = script_params['Sum_or_Average'] == 'Average, with raw data' \ and 'Line, ' or "" col_header = 'Image_ID, ROI_ID, Z, T, C, %sLine data %s of Line" \ " Width %s\n' % (line_id, script_params['Sum_or_Average'], script_params['Line_Width']) # prepare a csv file to write our data to... file_name = "Plot_Profile_%s.csv" % image.getId() with open(file_name, 'w') as f: f.write(col_header) if len(lines) > 0: process_lines(conn, script_params, image, lines, line_width, f) if len(polylines) > 0: process_polylines( conn, script_params, image, polylines, line_width, f) file_ann, fa_message = script_utils.create_link_file_annotation( conn, file_name, image, output="Line Plot csv (Excel) file", mimetype="text/csv", description=None) if file_ann: file_anns.append(file_ann) if not file_anns: fa_message = "No Analysis files created. See 'Info' or 'Error' for"\ " more details" elif len(file_anns) > 1: fa_message = "Created %s csv (Excel) files" % len(file_anns) message += fa_message return file_anns, message