def load_raw_slide_to_cache(slide_id, resource): # Get the data for this slide sr = get_slide_ref(slide_id) if sr is not None: sr.get_local_copy(resource) else: print('Slide %s not found' % (slide_id, ))
def api_get_slide_random_patch(task_id, slide_id, width): db = get_db() # Find out which machine the slide is currently being served from # Get the tiff image from which to sample the region of interest sr = get_slide_ref(slide_id) # Get the identifiers for the slide # TODO: what to do with project here? (project, specimen, block, slide_name, slide_ext) = sr.get_id_tuple() # Are we de this slide to a different node? del_url = find_delegate_for_slide(slide_id) # If local, call the method directly rawbytes = None if del_url is None: rawbytes = get_random_patch(project, specimen, block, 'raw', slide_name, slide_ext, 0, width, 'png').data else: url = '%s/dzi/random_patch/%s/%s/%s/raw/%s.%s/%d/%d.png' % ( del_url, project, specimen, block, slide_name, slide_ext, 0, width) pr = sr.get_project_ref() post_data = urllib.urlencode( {'project_data': json.dumps(pr.get_dict())}) rawbytes = urllib2.urlopen(url, post_data).read() # Send the patch resp = make_response(rawbytes) resp.mimetype = 'image/png' return resp
def export_annot_vtk(task, slide_id, out_file): """ Export annotations on a slide to VTK file """ # Find the annotation in the database db = get_db() rc = db.execute('SELECT json FROM annot WHERE slide_id=? AND task_id=?', (slide_id, task)).fetchone() if rc is not None: # Get the annotation data = json.loads(rc['json']) # Get the raw slide dimensions sr = get_slide_ref(slide_id) dims = get_slide_raw_dims(sr) if dims is None: sys.exit("Missing slide dimensions information") # Get the set of points pts = annot_sample_path_curves(data, 5000) # Join all the point arrays all_pts = [item for sublist in pts for item in sublist] # Length of each polyline segment plen = [len(sublist) for sublist in pts] # Write a VTK file based on points out_file.write("# vtk DataFile Version 4.2\n") out_file.write("vtk output\n") out_file.write("ASCII\n") out_file.write("DATASET POLYDATA\n") out_file.write("POINTS %d float\n" % len(all_pts)) # Write all the points for p in all_pts: out_file.write('%f %f %f\n' % (p[0], p[1], 0.0)) out_file.write("LINES %d %d\n" % (len(pts), len(pts) + sum(plen))) idx = 0 for q in pts: out_file.write( '%d %s\n' % (len(q), ' '.join([str(x) for x in range(idx, idx + len(q))]))) idx = idx + len(q)
def api_slide_job_status(task_id, slide_id, jobid): db = get_db() sr = get_slide_ref(slide_id) (project, specimen, block, slide_name, slide_ext) = sr.get_id_tuple() # Are we de this slide to a different node? del_url = find_delegate_for_slide(slide_id) # If local, call the method directly if del_url is None: return dzi_job_status(project, slide_name, jobid) else: url = '%s/dzi/job/%s/%s/%s/status' % ( del_url, project, slide_name, jobid) pr = sr.get_project_ref() post_data = urllib.urlencode({'project_data': json.dumps(pr.get_dict())}) return urllib2.urlopen(url, post_data).read()
def generate_sample_patch(slide_id, sample_id, rect, dims=(512, 512), level=0): # Find out which machine the slide is currently being served from # Get the tiff image from which to sample the region of interest db = get_db() sr = get_slide_ref(slide_id) # Get the identifiers for the slide # TODO: what to do with project here? (project, specimen, block, slide_name, slide_ext) = sr.get_id_tuple() # Are we de this slide to a different node? del_url = find_delegate_for_slide(slide_id) # Compute the parameters ctr_x = int((rect[0] + rect[2]) / 2.0 + 0.5) ctr_y = int((rect[1] + rect[3]) / 2.0 + 0.5) (w, h) = dims x = ctr_x - ((w - int(w / 2.0)) - 1) y = ctr_y - ((h - int(h / 2.0)) - 1) # If local, call the method directly rawbytes = None if del_url is None: rawbytes = get_patch(project, specimen, block, 'raw', slide_name, slide_ext, level, ctr_x, ctr_y, w, h, 'png').data else: url = '%s/dzi/patch/%s/%s/%s/raw/%s.%s/%d/%d_%d_%d_%d.png' % ( del_url, project, specimen, block, slide_name, slide_ext, level, ctr_x, ctr_y, w, h) pr = sr.get_project_ref() post_data = urllib.urlencode( {'project_data': json.dumps(pr.get_dict())}) rawbytes = urllib2.urlopen(url, post_data).read() # Save as PNG with open(get_sample_patch_filename(sample_id), 'wb') as f: f.write(rawbytes) # Record that patch has been written db.execute('UPDATE training_sample SET have_patch=1 where id=?', (sample_id, )) db.commit()
def update_slide_derived_data(slide_id, check_hash=True): # Get the slide reference sr = get_slide_ref(slide_id) # Get the remote thumbnail file f_thumb = sr.get_local_copy("thumb", check_hash=check_hash) # Get the local thumbnail thumb_dir = os.path.join(current_app.instance_path, 'thumb') thumb_fn = os.path.join(thumb_dir, "thumb%08d.png" % (slide_id, )) # If the thumb has been downloaded successfully, derive a HTML-usable thumb if f_thumb is not None: x = Image.open(f_thumb) m = max(x.size[0] / 256., x.size[1] / 192.) x = x.resize(map(int, (x.size[0] / m, x.size[1] / m))) if not os.path.exists(thumb_dir): os.makedirs(thumb_dir) x.save(thumb_fn)
def get_sample_custom_png(id, level, w, h): # Get the slide reference db = get_db() sample = db.execute('SELECT * FROM training_sample WHERE id=?', (id, )).fetchone() slide_id = sample['slide'] sr = get_slide_ref(slide_id) # Get the identifiers for the slide # TODO: what to do with project name here (project, specimen, block, slide_name, slide_ext) = sr.get_id_tuple() # Are we delegating this slide to a different node? del_url = find_delegate_for_slide(slide_id) # Compute the parameters ctr_x = int((sample['x0'] + sample['x1']) / 2.0 + 0.5) ctr_y = int((sample['y0'] + sample['y1']) / 2.0 + 0.5) x = ctr_x - ((w - int(w / 2.0)) - 1) y = ctr_y - ((h - int(h / 2.0)) - 1) # If local, call the method directly rawbytes = None if del_url is None: rawbytes = get_patch(project, specimen, block, 'raw', slide_name, slide_ext, level, ctr_x, ctr_y, w, h, 'png').data else: url = '%s/dzi/patch/%s/%s/%s/raw/%s.%s/%d/%d_%d_%d_%d.png' % ( del_url, project, specimen, block, slide_name, slide_ext, level, ctr_x, ctr_y, w, h) pr = sr.get_project_ref() post_data = urllib.urlencode( {'project_data': json.dumps(pr.get_dict())}) rawbytes = urllib2.urlopen(url, post_data).read() resp = make_response(rawbytes) resp.mimetype = 'image/%s' % format return resp
def get_affine_matrix_by_slideid(slide_id, mode, resolution='raw'): sr = get_slide_ref(slide_id) return get_affine_matrix(sr, mode, resolution)
def extract_svg(task, slide_id, stroke_width, strip_width, font_size, font_color): # The return value svg = None # Find the annotation in the database db = get_db() rc = db.execute('SELECT json FROM annot WHERE slide_id=? AND task_id=?', (slide_id, task)).fetchone() if rc is not None: # Get the annotation data = json.loads(rc['json']) # Get the raw slide dimensions sr = get_slide_ref(slide_id) dims = get_slide_raw_dims(sr) if dims is None: raise ValueError("Missing slide dimensions information") # Start writing svg svg = svgwrite.Drawing(size=(dims[0], dims[1])) # Write the paths if 'children' in data[0][1]: for x in data[0][1]['children']: # Handle paths if not check_annot_child(x): print('Bad element:', x) continue try: if x[0] == 'Path': seg = x[1]['segments'] if len(seg) < 1 or seg[0][0][0] is None or seg[0][0][ 1] is None: continue # Default mode is to draw curves if strip_width is None or strip_width == 0: # List of commands for SVG path cmd = [] # Record the initial positioning cmd.append('M%f,%f' % (seg[0][0][0], seg[0][0][1])) # Record the control points for i in range(1, len(seg)): # Get the handles from the control point P1 = seg[i - 1][0] P2 = seg[i][0] D = [P2[0] - P1[0], P2[1] - P1[1]] V1 = seg[i - 1][2] V2 = seg[i][1] cmd.append('c%f,%f %f,%f %f,%f' % (V1[0], V1[1], D[0] + V2[0], D[1] + V2[1], D[0], D[1])) # Add the path to the SVG svg.add( svg.path(d=''.join(cmd), stroke="#000", fill="none", stroke_width=stroke_width)) # Alternative mode is to draw parallel strips else: # Record the control points for i in range(1, len(seg)): # Get the handles from the control point P1 = seg[i - 1][0] P2 = seg[i][0] D = [P2[0] - P1[0], P2[1] - P1[1]] V1 = seg[i - 1][2] V2 = seg[i][1] # Get the tangent vectors nV1 = math.sqrt(V1[0] * V1[0] + V1[1] * V1[1]) nV2 = math.sqrt(V2[0] * V2[0] + V2[1] * V2[1]) T1 = [x / nV1 for x in V1] if nV1 > 0 else V1 T2 = [x / nV2 for x in V2] if nV2 > 0 else V2 Q2 = [ P2[0] + strip_width * T2[1], P2[1] - strip_width * T2[0] ] Q1 = [ P1[0] - strip_width * T1[1], P1[1] + strip_width * T1[0] ] DQ = [Q1[0] - Q2[0], Q1[1] - Q2[1]] R2 = [ P2[0] - strip_width * T2[1], P2[1] + strip_width * T2[0] ] R1 = [ P1[0] + strip_width * T1[1], P1[1] - strip_width * T1[0] ] DR = [R1[0] - R2[0], R1[1] - R2[1]] # Draw the path (part curve, part line) svg.add( svg.path( d="M%f,%f c%f,%f %f,%f %f,%f L%f,%f c%f,%f %f,%f, %f,%f L%f,%f" % (P1[0], P1[1], V1[0], V1[1], D[0] + V2[0], D[1] + V2[1], D[0], D[1], Q2[0], Q2[1], V2[0], V2[1], DQ[0] + V1[0], DQ[1] + V1[1], DQ[0], DQ[1], P1[0], P1[1]), stroke="none", fill="#ddd", stroke_width=0)) # Draw the path (part curve, part line) svg.add( svg.path( d="M%f,%f c%f,%f %f,%f %f,%f L%f,%f c%f,%f %f,%f, %f,%f L%f,%f" % (P1[0], P1[1], V1[0], V1[1], D[0] + V2[0], D[1] + V2[1], D[0], D[1], R2[0], R2[1], V2[0], V2[1], DR[0] + V1[0], DR[1] + V1[1], DR[0], DR[1], P1[0], P1[1]), stroke="none", fill="#aaa", stroke_width=0)) #svg.add(svg.path( # d="M%f,%f c%f,%f %f,%f %f,%f L%f,%f L%f,%f L%f,%f" % ( # P1[0],P1[1], # V1[0],V1[1],D[0]+V2[0],D[1]+V2[1],D[0],D[1], # P2[0]+strip_width*T2[1],P2[1]-strip_width*T2[0], # P1[0]-strip_width*T1[1],P1[1]+strip_width*T1[0], # P1[0],P1[1]), stroke="#000", fill="#ddd", stroke_width=48)) elif x[0] == 'PointText': tpos = x[1]['matrix'][4:6] text = x[1]['content'] svg.add( svg.text(text, insert=tpos, fill=font_color, stroke=font_color, font_size=font_size)) # ["PointText", # {"applyMatrix": false, "matrix": [1, 0, 0, 1, 1416.62777, 2090.96831], "content": "CA2", # "fontWeight": "bold", "fontSize": 44, "leading": 52.8, "justification": "center"}] except TypeError: raise ValueError("Unreadable path %s in slide %d task %d" % (x, slide_id, task)) return svg