def rotate_stack(stack_in, stack_out=None, r=0, render=None): """Rotate stack by an arbitrary rotation Parameters ---------- stack_in : str Input stack name stack_out : str (optional) Output stack name Overwrites input stack if not provided r : float rotation angle [rad] """ # Create DataFrame for input stack df_stack = create_stack_DataFrame(stack=stack_in, render=render) # Create scaling transform T = AffineMPL().rotate(r) A = AffineRender() A.M = T.get_matrix() # Add rotation transform to DataFrame for i, tile in df_stack.iterrows(): df_stack.at[i, 'tforms'] += [A] # Set output stack name stack_out = stack_out if stack_out is not None else stack_in # Create scaled stack create_stack_from_DataFrame(df=df_stack, name=stack_out, render=render)
def translate_stack(stack_in, stack_out=None, tx=0.0, ty=0.0, render=None): """Translate stack by an arbitrary translation Parameters ---------- stack_in : str Input stack name stack_out : str (optional) Output stack name Overwrites input stack if not provided tx : float x translation [px] ty : float y translation [px] """ # Create DataFrame for input stack df_stack = create_stack_DataFrame(stack=stack_in, render=render) # Create scaling transform T = AffineMPL().translate(tx, ty) A = AffineRender() A.M = T.get_matrix() # Add translation transform to DataFrame for i, tile in df_stack.iterrows(): df_stack.at[i, 'tforms'] += [A] # Set output stack name stack_out = stack_out if stack_out is not None else stack_in # Create scaled stack create_stack_from_DataFrame(df=df_stack, name=stack_out, render=render)
def consolidate_transforms(tforms, logger, makePolyDegree=0): tform_total = AffineModel() start_index = 0 total_affines = 0 new_tform_list = [] for i, tform in enumerate(tforms): if 'AffineModel2D' in tform.className: total_affines += 1 tform_total = tform.concatenate(tform_total) #tform_total.M=tform.M.dot(tform_total.M) else: logger.debug('consolidate_transforms: non affine {}'.format(tform)) if total_affines > 0: if makePolyDegree > 0: polyTform = Polynomial2DTransform()._fromAffine( tform_total) polyTform = polyTform.asorder(makePolyDegree) new_tform_list.append(polyTform) else: new_tform_list.append(tform_total) tform_total = AffineModel() total_affines = 0 new_tform_list.append(tform) if total_affines > 0: if makePolyDegree > 0: polyTform = Polynomial2DTransform()._fromAffine(tform_total) polyTform = polyTform.asorder(makePolyDegree) new_tform_list.append(polyTform) else: new_tform_list.append(tform_total) return new_tform_list
def scale_stack(stack_in, stack_out=None, sx=1.0, sy=1.0, render=None): """Scale stack by an arbitrary scale factor Parameters ---------- stack_in : str Input stack name stack_out : str (optional) Output stack name Overwrites input stack if not provided sx : float x scale factor sy : float y scale factor """ # Create DataFrame for input stack df_stack = create_stack_DataFrame(stack=stack_in, render=render) # Create scaling transform T = AffineMPL().scale(sx, sy) A = AffineRender() A.M = T.get_matrix() # Add scale transform to DataFrame for i, tile in df_stack.iterrows(): df_stack.at[i, 'tforms'] += [A] # Set output stack name stack_out = stack_out if stack_out is not None else stack_in # Create scaled stack create_stack_from_DataFrame(df=df_stack, name=stack_out, render=render)
def create_patch_xml(tile_spec): """Generate xml data for a given patch (tile)""" # Abbreviate tile specification ts = tile_spec # Generate oid x, y = [int(i) for i in re.findall(r'\d+', ts.tileId)[-2:]] oid = f"{ts.z:.0f}{x:02d}{y:02d}" # Get total transform AT = AffineModel() for tform in ts.tforms: AT = tform.concatenate(AT) # Create xml data for patch patch = f""" <t2_patch oid="{oid}" width="{ts.width}" height="{ts.height}" transform="matrix({AT.M00},{AT.M10},{AT.M01},{AT.M11},{AT.B0},{AT.B1})" links="" type="1" file_path="{ts.ip[0].imageUrl.split('://')[1]}" title="{ts.tileId}" style="fill-opacity:1.0;stroke:#ffff00;" o_width="{ts.width:.0f}" o_height="{ts.height:.0f}" min="{ts.minint}" max="{ts.maxint}" mres="32" > </t2_patch>""" return patch
def consolidate_transforms(tforms, ref_tforms=[], logger=logging.getLogger(), makePolyDegree=0, keep_ref_tforms=False): # first flatten and dereference this transform list tforms = (flatten_and_dereference_tforms(tforms, ref_tforms) if not keep_ref_tforms else flatten_tforms(tforms)) tform_total = AffineModel() start_index = 0 total_affines = 0 new_tform_list = [] for i, tform in enumerate(tforms): try: isaffine = 'AffineModel2D' in tform.className except AttributeError: isaffine = False if isaffine: total_affines += 1 tform_total = tform.concatenate(tform_total) # tform_total.M=tform.M.dot(tform_total.M) else: logger.debug('consolidate_transforms: non affine {}'.format(tform)) if total_affines > 0: if makePolyDegree > 0: polyTform = Polynomial2DTransform().fromAffine(tform_total) polyTform = polyTform.asorder(makePolyDegree) new_tform_list.append(polyTform) else: new_tform_list.append(tform_total) tform_total = AffineModel() total_affines = 0 new_tform_list.append(tform) if total_affines > 0: if makePolyDegree > 0: polyTform = Polynomial2DTransform().fromAffine(tform_total) polyTform = polyTform.asorder(makePolyDegree) new_tform_list.append(polyTform) else: new_tform_list.append(tform_total) return new_tform_list
def import_trakem2_project(stack, xml_filepath, render): """Import render stack from TrakEM2 xml file""" # Soupify TrakEM2 xml file soup = Soup(xml_filepath.read_bytes(), 'lxml') # Iterate through layers to collect tile specifications tile_specs = [] out = f"Creating tile specifications for \033[1m{stack}\033[0m..." print(out) for layer in tqdm(soup.find_all('t2_layer')): # Iterate through patches for patch in layer.find_all('t2_patch'): # Get patch data as dict d = patch.attrs # Parse transform data M00, M10, M01, M11, B0, B1 = [ float(i) for i in re.findall(r'-?[\d.]+(?:[Ee]-?\d+)?', d['transform']) ] A = AffineModel(M00, M01, M10, M11, B0, B1) # Define layout z = float(layer.attrs['z']) col, row = [int(i) for i in re.findall(r'\d+', d['title'])][-2:] layout = Layout(sectionId=f'S{int(z):03d}', imageRow=row, imageCol=col) # Create tile specification ts = TileSpec(tileId=d['title'], z=z, width=d['width'], height=d['height'], imageUrl=d['file_path'], minint=d['min'], maxint=d['max'], layout=layout, tforms=[A]) # Collect tile specification tile_specs.append(ts) # Create stack create_stack(stack=stack, render=render) # Import TileSpecs to render out = f"Importing tile specifications to \033[1m{stack}\033[0m..." print(out) import_tilespecs(stack=stack, tilespecs=tile_specs, render=render) # Close stack set_stack_state(stack=stack, state='COMPLETE', render=render) out = f"Stack \033[1m{stack}\033[0m created successfully." print(out)
def run(self): print mod.args self.logger.error( 'WARNING NEEDS TO BE TESTED, TALK TO FORREST IF BROKEN') if not os.path.isdir(self.args['outputXMLdir']): os.makedirs(self.args['outputXMLdir']) xmlDir = self.args['outputXMLdir'] #fill in missing bounds with the input stack bounds bounds = self.render.run(renderapi.stack.get_stack_bounds, self.args['inputStack']) for key in bounds.keys(): self.args[key] = self.args.get(key, bounds[key]) EMz = renderapi.stack.get_z_values_for_stack(self.args['inputStack'], render=self.render) tilespecsfiles = [] shiftTransform = AffineModel(B0=self.args['minX'], B1=self.args['minY']) for z in EMz: infile = os.path.join(xmlDir, '%05d.xml' % z) outfile = os.path.join(xmlDir, '%05d.json' % z) newoutfile = os.path.join(xmlDir, '%05d-new.json' % z) self.convert_trakem2_project(infile, xmlDir, outfile) newtilejson = json.load(open(outfile, 'r')) newEMtilespecs = [TileSpec(json=tsj) for tsj in newtilejson] EMtilespecs = renderapi.tilespec.get_tile_specs_from_minmax_box( self.args['inputStack'], z, self.args['minX'], self.args['maxX'], self.args['minY'], self.args['maxY'], render=self.render) for ts in EMtilespecs: nts = next(t for t in newEMtilespecs if t.tileId == ts.tileId) ts.tforms = nts.tforms ts.tforms.append(shiftTransform) tilespecsfiles.append(newoutfile) renderapi.utils.renderdump(EMtilespecs, open(newoutfile, 'w')) sv = renderapi.stack.get_stack_metadata(self.args['inputStack'], render=self.render) renderapi.stack.create_stack(self.args['outputStack'], render=self.render) renderapi.stack.set_stack_metadata(self.args['outputStack'], sv, render=self.render) renderapi.client.import_jsonfiles_parallel(self.args['outputStack'], tilespecsfiles, render=self.render)
def transform_stack(stack_in, stack_out=None, T=None, render=None): """Transform stack by an arbitrary affine transformation Parameters ---------- stack_in : str Input stack name stack_out : str (optional) Output stack name Overwrites input stack if not provided T : 3x3 array, `AffineMPL`, or `AffineRender` object Affine transform """ # Create DataFrame for input stack df_stack = create_stack_DataFrame(stack=stack_in, render=render) # Create `AffineRender` transform object from given transform A = AffineRender() if isinstance(T, AffineMPL): A.M = T.get_matrix() elif isinstance(T, np.ndarray) and (T.shape == (3, 3)): A.M = T elif isinstance(T, AffineRender): pass else: raise ValueError("Improper form for transform.") # Add scale transform to DataFrame for i, tile in df_stack.iterrows(): df_stack.at[i, 'tforms'] += [A] # Set output stack name stack_out = stack_out if stack_out is not None else stack_in # Create scaled stack create_stack_from_DataFrame(df=df_stack, name=stack_out, render=render)
def make_tilespec(tileDirectory,tilespecdir,outputProject,outputOwner,outputStack,minval=0,maxval=50000): imagefiles = glob.glob(tileDirectory + "/*.tif") imagefiles.sort() z = 0 tilespecpaths = [] tilespeclist = [] for f in imagefiles: #print f filepath=f sectionId="SEC%04d"%z tileId = "%04d"%z frameId = "FRAME%04d"%z width = 1388 height = 1040 fileparts=filepath.split(os.path.sep)[1:] if not os.path.isdir(tilespecdir): os.makedirs(tilespecdir) layout = Layout(sectionId=sectionId, scopeId='Leica', cameraId='zyla', imageRow=0, imageCol=0, stageX = 0.0, stageY = 0.0, rotation = 0.0, pixelsize = 0.103) tform = AffineModel(M00=1.0,M01 = 0.0, M10 = 0.0, M11 = 1.0, B0 = 0.0, B1 = 0.0) mipmap0 = MipMapLevel(level=0,imageUrl=filepath) mipmaplevels=[mipmap0] #tilespeclist.append(TileSpec(tileId=tileId,frameId = frameId, z=z, width=width, height=height, tforms=[tform],minint=minval,maxint=maxval,layout= layout)) t = TileSpec(tileId=tileId,frameId = frameId, z=z, width=width, height=height, mipMapLevels=mipmaplevels, tforms=[tform],minint=minval,maxint=maxval,layout= layout) tilespeclist.append(t) json_file = os.path.join(tilespecdir,outputProject+'_'+outputOwner+'_'+outputStack+'_%04d.json'%z) fd=open(json_file, "w") renderapi.utils.renderdump([t],fd) fd.close() tilespecpaths.append(json_file) z = z+1 return tilespecpaths,tilespeclist
def run(self): #get the z values in the stack zvalues = self.render.run(renderapi.stack.get_z_values_for_stack, self.args['input_stack']) zvalues = np.array(zvalues) print(zvalues) zmin = self.args.get('zmin', np.min(zvalues)) zmax = self.args.get('zmax', np.max(zvalues)) zvalues = zvalues[zvalues >= zmin] zvalues = zvalues[zvalues <= zmax] #output_stack defaults to input_stack input_stack = self.args['input_stack'] output_stack = self.args.get('output_stack', input_stack) tformid = '{}_to_{}'.format(input_stack, output_stack) #define the affine transform to apply everywhere global_tform = AffineModel(M00=self.args['M00'], M10=self.args['M10'], M01=self.args['M01'], M11=self.args['M11'], B0=self.args['B0'], B1=self.args['B1']) #global_tform_ref = ReferenceTransform(refId=tformid) if (self.args['input_stack'] != output_stack): self.render.run(renderapi.stack.create_stack, output_stack) print "made stack" ds = ",".join(global_tform.dataString.split(" ")) renderapi.client.transformSectionClient(input_stack, self.args['transformId'], global_tform.className, ds, list(zvalues), targetStack=output_stack, replaceLast=False, render=self.render) sv = renderapi.stack.get_stack_metadata(input_stack, render=self.render) renderapi.stack.set_stack_metadata(output_stack, sv, render=self.render) renderapi.stack.set_stack_state(output_stack, 'COMPLETE', render=self.render)
def process_z(render, input_stack, z, delete_after=False): #get the tilespecs for this Z tilespecs = render.run(renderapi.tilespec.get_tile_specs_from_z, input_stack, z) #loop over the tilespes adding the transform for ts in tilespecs: #slide this tile up according to its minimumX slide_up = AffineModel(B1=-2 * ts.minY) ts.tforms.append(slide_up) #get the old minimum mipmaplevel mml = ts.ip.mipMapLevels[0] old_url = mml.imageUrl old_path = fix_url(old_url) new_url = mml.imageUrl[0:-4] + '_flip.png' new_path = fix_url(new_url) #construct the imagemagick command cmd = ['convert', old_path, '-flip', new_path] mml.imageUrl = new_url ts.ip.update(mml) #execute the imagemagick subprocess proc = subprocess.Popen(cmd) proc.wait() if delete_after: #remove me to delete os.remove(old_path) #open a temporary file tid, tfile = tempfile.mkstemp(suffix='.json') file = open(tfile, 'w') #write the file to disk renderapi.utils.renderdump(tilespecs, file) os.close(tid) #return the filepath return tfile
def run(self): print mod.args self.logger.error('WARNING NEEDS TO BE TESTED, TALK TO FORREST IF BROKEN') if not os.path.isdir(self.args['outputXMLdir']): os.makedirs(self.args['outputXMLdir']) xmlDir = self.args['outputXMLdir'] EMz = renderapi.stack.get_z_values_for_stack(self.args['EMstack'],render=self.render) tilespecsfiles = [] shiftTransform = AffineModel(B0=args['minX'],B1=args['minY']) for z in EMz: infile = os.path.join(xmlDir,'%05d.xml'%z) outfile = os.path.join(xmlDir,'%05d.json'%z) newoutfile = os.path.join(xmlDir,'%05d-new.json'%z) self.convert_trakem2_project(self,infile,xmlDir,outfile) newtilejson = json.load(open(outfile,'r')) newEMtilespecs = [TileSpec(json=tsj) for tsj in newtilejson] EMtilespecs = renderapi.tilespec.get_tile_specs_from_minmax_box( EMstack, z, self.args['minX'], self.args['maxX'], self.args['minY'], self.args['maxY'], render=self.render) for ts in EMtilespecs: nts = next(t for t in newEMtilespecs if t.tileId == ts.tileId ) ts.tforms=nts.tforms ts.tforms.append(shiftTransform) tilespecsfiles.append(newoutfile) renderapi.utils.renderdump(EMtilespecs,open(newoutfile,'w')) renderapi.stack.delete_stack(self.args['outputEMStack'],render=self.render) renderapi.stack.create_stack(self.args['outputEMStack'],render=self.render) renderapi.client.import_jsonfiles_parallel(self.args['outputEMStack'],tilespecsfiles,render=self.render)
def make_tilespec_from_llp (rootdir,outputProject,outputOwner,outputStack,minval=0,maxval=50000): mipmap_args = [] tilespecpaths = [] basename ='LLP' #cwd = os.getcwd() #load database db = sqlite3.connect('llp.sqlite') c=db.cursor() c.execute('SELECT * FROM image_item') keys = [description[0] for description in c.description] imdb = list() mags = list() # import data for row in c.execute('SELECT * FROM image_item ORDER BY image_id'): im_item = dict() for idx,key in enumerate(keys): im_item[key] = row[idx] mags.append(row[3]) imdb.append(im_item) mags=np.array(mags) # histogram information for intensity scaling c.execute('SELECT histgramRangeMax FROM histgram') h_max = c.fetchall()[1][0] c.execute('SELECT histgramRangeMin FROM histgram') h_min = c.fetchall()[1][0] c.execute('SELECT histgramAverage FROM histgram') h_av = c.fetchall()[1][0] c.execute('SELECT histgramStdev FROM histgram') h_sd = c.fetchall()[1][0] db.close() #minmax iwill be based on average value, otherwise use given values # if int_av: # h_max = int(min(65535,h_av + int_width * h_sd)) # h_min = int(max(0,h_av - int_width * h_sd)) # process each mag separately for thismag in np.unique(mags): # thismag=1000 # if thismag==1000: itemname = basename + '_'+str(thismag)+'x' # outfile = os.path.join(dirname,itemname) # outfile = outfile + outformat im_idx = np.where(mags==thismag) setup_id=0 tile_id=0 numslices = np.shape(im_idx)[1] digits = len(str(numslices)) tilespeclist=[] z=0 for tile_id,imx in enumerate(im_idx[0]): # thisview=dict() tile = imdb[imx] # im = io.imread(thisim['filename']) f1 = os.path.realpath(tile['filename']) fbase = os.path.splitext(os.path.basename(f1))[0] tilespecdir = os.path.join('processed','tilespec') filepath= groupsharepath(f1) #print tilespecdir if not os.path.isdir(tilespecdir): os.makedirs(tilespecdir) downdir = os.path.join("processed","downsamp_images") #print "This is the Down Sampled Directory: %s"%downdir if not os.path.exists(downdir): os.makedirs(downdir) downdir1 = groupsharepath(os.path.realpath(downdir)) pxs = 1/tile['pixel_per_nm'] #construct command for creating mipmaps for this tilespec #downcmd = ['python','create_mipmaps.py','--inputImage',filepath,'--outputDirectory',downdir,'--mipmaplevels','1','2','3'] #cmds.append(downcmd) mipmap_args.append((f1,os.path.realpath(downdir))) layout = Layout(sectionId=z, scopeId='JEOL', cameraId='Matataki', imageRow=0, imageCol=0, stageX = tile['location_x_nm'], stageY = tile['location_y_nm'], rotation = tile['stage_x_axis_rotation_degree_'], pixelsize = pxs) mipmap0 = MipMapLevel(level=0,imageUrl='file://' + filepath) mipmaplevels=[mipmap0] for i in range(1,4): scUrl = 'file://' + os.path.join(downdir1,fbase) + '_mip0%d.jpg'%i mml = MipMapLevel(level=i,imageUrl=scUrl) mipmaplevels.append(mml) # transformation # 1) The scale and rotation information th = np.radians(thisim['image_degree']) ct = np.cos(th) st = np.sin(th) rotmat = pxs * np.array([[ct,-st,0],[st,ct,0],[0,0,1]]) # 2) The translation matrix to position the object in space (lower left corner) # mat_t = np.concatenate((np.eye(2),[[0,thisim['location_x_nm']/1000],[0,thisim['location_y_nm']/1000]]),axis=1) # mat_t = np.concatenate((mat_t,[[0,0,1,0],[0,0,0,1]])) # tf_tr = tf.matrix_to_transformation(mat_t).tolist() tform = AffineModel(M00=rotmat[0,0], M01=rotmat[0,0], M10=rotmat[0,0], M11=rotmat[0,0], B0=thisim['location_x_nm'], B1=thisim['location_y_nm']) tilespeclist.append(TileSpec(tileId=itemname+'_t'+('{:0'+str(digits)+'}').format(tile_id), frameId = itemname, z=z, width=tile['image_width_px'], height=tile['image_height_px'], mipMapLevels=mipmaplevels, tforms=[tform], minint=minval, maxint=maxval, layout= layout)) json_file = os.path.realpath(os.path.join(tilespecdir,outputProject+'_'+outputOwner+'_'+outputStack+'_%04d.json'%z)) fd=open(json_file, "w") renderapi.utils.renderdump(tilespeclist,fd,sort_keys=True, indent=4, separators=(',', ': ')) fd.close() tilespecpaths.append(json_file) return tilespecpaths,mipmap_args # ---------------------- if not os.path.exists('meta'): print('Change to proper directory!');exit() mfile0 = os.path.join('meta','logs','imagelist_') mfiles = glob.glob(mfile0+'*') tiles = list() views = list() idx = 0 for mfile in mfiles: with open(mfile) as mf: ml = mf.read().splitlines() mdfile = os.path.join('meta','logs','metadata'+mfile[mfile.rfind('_'):]) with open(mdfile) as mdf: mdl = mdf.read().splitlines() conffile = os.path.join('meta','logs','config'+mfile[mfile.rfind('_'):]) with open(conffile) as cf: cl = cf.read().splitlines() config = parse_adoc(cl) pxs = float(config['grab_frame_pixel_size'][0])#/1000 # in um z_thick = float(config['slice_thickness'][0])#/1000 # in um # generate the individual transformation matrices # 1) The scale and rotation information form the map item mat = np.diag((pxs,pxs,z_thick)) mat_s = np.concatenate((mat,[[0],[0],[0]]),axis=1) mat_s = np.concatenate((mat_s,[[0,0,0,1]])) for line in mdl: if line.startswith('TILE: '): tile = bdv.str2dict(line[line.find('{'):]) tiles.append(tile) # 2) The translation matrix to position the object in space (lower left corner) mat_t = np.concatenate((np.eye(3),[[tile['glob_x']],[tile['glob_y']],[tile['glob_z']]]),axis=1) mat_t = np.concatenate((mat_t,[[0,0,0,1]]))
def make_tilespec_from_sbemimage(rootdir, outputProject, outputOwner, outputStack, minval=0, maxval=50000): mipmap_args = [] tilespecpaths = [] if not os.path.exists('meta'): print('Change to proper directory!') exit() mfile0 = os.path.join('meta', 'logs', 'imagelist_') mfiles = glob.glob(mfile0 + '*') tiles = list() views = list() idx = 0 for mfile in mfiles: with open(mfile) as mf: ml = mf.read().splitlines() mdfile = os.path.join('meta', 'logs', 'metadata' + mfile[mfile.rfind('_'):]) with open(mdfile) as mdf: mdl = mdf.read().splitlines() conffile = os.path.join('meta', 'logs', 'config' + mfile[mfile.rfind('_'):]) with open(conffile) as cf: cl = cf.read().splitlines() config = parse_adoc(cl) pxs = float(config['grab_frame_pixel_size'][0]) #/1000 # in um z_thick = float(config['slice_thickness'][0]) #/1000 # in um # generate the individual transformation matrices # 1) The scale and rotation information form the map item mat = np.diag((pxs, pxs, z_thick)) mat_s = np.concatenate((mat, [[0], [0], [0]]), axis=1) mat_s = np.concatenate((mat_s, [[0, 0, 0, 1]])) tilespeclist = [] z = 0 for line in mdl: if line.startswith('TILE: '): tile = bdv.str2dict(line[line.find('{'):]) tiles.append(tile) # 2) The translation matrix to position the object in space (lower left corner) mat_t = np.concatenate( (np.eye(3), [[tile['glob_x']], [tile['glob_y']], [tile['glob_z']]]), axis=1) mat_t = np.concatenate((mat_t, [[0, 0, 0, 1]])) f1 = os.path.realpath(tile['filename']) fbase = os.path.splitext(os.path.basename(f1))[0] tilespecdir = os.path.join('processed', 'tilespec') filepath = groupsharepath(f1) #print tilespecdir if not os.path.isdir(tilespecdir): os.makedirs(tilespecdir) downdir = os.path.join("processed", "downsamp_images") #print "This is the Down Sampled Directory: %s"%downdir if not os.path.exists(downdir): os.makedirs(downdir) downdir1 = groupsharepath(os.path.realpath(downdir)) #construct command for creating mipmaps for this tilespec #downcmd = ['python','create_mipmaps.py','--inputImage',filepath,'--outputDirectory',downdir,'--mipmaplevels','1','2','3'] #cmds.append(downcmd) mipmap_args.append((f1, os.path.realpath(downdir))) layout = Layout(sectionId=tile['slice_counter'], scopeId='3View', cameraId='3View', imageRow=0, imageCol=0, stageX=tile['glob_x'] / 10, stageY=tile['glob_y'] / 10, rotation=0.0, pixelsize=pxs) mipmap0 = MipMapLevel(level=0, imageUrl='file://' + filepath) mipmaplevels = [mipmap0] filename = tile['tileid'] for i in range(1, 4): scUrl = 'file://' + os.path.join(downdir1, fbase) + '_mip0%d.jpg' % i mml = MipMapLevel(level=i, imageUrl=scUrl) mipmaplevels.append(mml) tform = AffineModel(M00=1, M01=0, M10=0, M11=1, B0=tile['glob_x'] / 10, B1=tile['glob_y'] / 10) tilespeclist.append( TileSpec(tileId=tile['tileid'], frameId=tile['tileid'][:tile['tileid'].find('.')], z=tile['glob_z'], width=tile['tile_width'], height=tile['tile_height'], mipMapLevels=mipmaplevels, tforms=[tform], minint=minval, maxint=maxval, layout=layout)) z = tile['glob_z'] json_file = os.path.realpath( os.path.join( tilespecdir, outputProject + '_' + outputOwner + '_' + outputStack + '_%04d.json' % z)) fd = open(json_file, "w") renderapi.utils.renderdump(tilespeclist, fd, sort_keys=True, indent=4, separators=(',', ': ')) fd.close() tilespecpaths.append(json_file) return tilespecpaths, mipmap_args
def run(self): zvalues = self.render.run(renderapi.stack.get_z_values_for_stack, self.args['inputStack']) minZ = self.args.get('minZ', int(np.min(zvalues))) maxZ = self.args.get('maxZ', int(np.max(zvalues))) if self.args['doChunk']: allchunks = createchunks(minZ, maxZ, self.args['chunkSize']) raise Exception('do chunk output not yet implemented') else: allchunks = [] ck = Chunk() ck.first = minZ ck.last = maxZ ck.dir = str(ck.first) + "-" + str(ck.last) allchunks.append(ck) for x in allchunks: indir = os.path.join(self.args['outputXMLdir'], x.dir) infile = os.path.join(indir, 'project.xml') outfile = os.path.join(indir, 'tilespec.json') self.convert_trakem2_project(infile, indir, outfile) with open(outfile, 'r') as fp: tsjson = json.load(fp) output_tilespecs = [TileSpec(json=tsj) for tsj in tsjson] shiftTransform = AffineModel(B0=self.args['minX'], B1=self.args['minY']) jsonfiles = [] for layerid in range(x.first, x.last + 1): self.logger.debug('layerid {}'.format(x.first)) jsonfilename = os.path.join(self.args['outputXMLdir'], '%05d.json' % layerid) output_tilespec_list = [] tilespecs_original = renderapi.tilespec.get_tile_specs_from_minmax_box( self.args['inputStack'], layerid, self.args['minX'], self.args['maxX'], self.args['minY'], self.args['maxY'], render=self.render) for tso in tilespecs_original: #tileid4 = "%04d"%(int(output_tilespecs[0].tileId)) #matches = [ts for ts in output_tilespecs if ts.tileId==tso.tileId] #print "This is tileid : ", tileid4 #print tso.tileId matches = [ ts for ts in output_tilespecs if int(ts.tileId) == int(tso.tileId) ] if len(matches) > 0: tsm = matches[0] tso.tforms = tsm.tforms tso.tforms.append(shiftTransform) output_tilespec_list.append(tso) with open(jsonfilename, 'w') as fp: renderapi.utils.renderdump(output_tilespec_list, fp, indent=4) jsonfiles.append(jsonfilename) if not self.args['doChunk']: #outfile = os.path.join(indir,'tilespec_old.json') #renderapi.stack.delete_stack(self.args['outputStack'],render=r) sv = renderapi.stack.get_stack_metadata( self.args['inputStack'], render=self.render) renderapi.stack.create_stack(self.args['outputStack'], render=self.render) renderapi.stack.set_stack_metadata(self.args['outputStack'], sv, render=self.render) print outfile renderapi.client.import_jsonfiles_parallel( self.args['outputStack'], jsonfiles, render=self.render)
def process_siteset(render,siteset, sectionset, doc, project_path,lm_dataset='test',lm_stack='ACQDAPI_1'): project = doc['F-BioSEM-Project']['BioSemProject'] # find the light dataset name dataset = find_node_by_field(doc, 'Name', lm_dataset) imported_data = find_node_by_field(doc, 'Name', 'Imported Data') # get the important transforms from atlas file # transform from EM data>root at = AtlasTransform(dataset['ParentTransform']) # transform from LMdata > root id_at = AtlasTransform(imported_data['ParentTransform']) project_dir, project_file = os.path.split(project_path) project_base = os.path.splitext(project_file)[0] ribnum = project_path.split(os.path.sep)[-2] ribnum = int(ribnum.lower().replace('ribbon', '')) nodes, paths=find_nodes_by_field(project, 'Name', siteset['Name']) ods=[ods for ods, p in zip(nodes, paths) if 'OrderedDataSet' in p] sitename=siteset['Name'].replace(' ', '') json_files = [] if len(ods) > 0: # print "found it" ods=ods[0] outdir=os.path.join(os.path.join(project_dir, 'TEM2_import_files')) if not os.path.isdir(outdir): os.makedirs(outdir) for site in siteset['Site']: sitefile=os.path.join( outdir, site['Name'].replace(' ', '') + '.csv') # print sitefile df=pd.DataFrame(columns=('Path', 'M00', 'M01', 'M10', 'M11', 'dx', 'dy')) section=[section for section in sectionset['Section'] if section['UID'] == site['LinkedToUID']][0] if type(ods['PlaceableMosaic']) is not type([]): ods['PlaceableMosaic']=[ods['PlaceableMosaic']] mosaic=[pm for pm in ods['PlaceableMosaic'] if pm['UID'] == site['AcquisitionSpec']['AcquiredDataUID']] if len(mosaic) == 0: continue else: mosaic=mosaic[0] # print mosaic['Name'] # this is the transform that describes how to transform from the coodinate system of the EM stage # to the new coordiante transform of this mosaic site mt=AtlasTransform(mosaic['ParentTransform']) center=np.array([[0.5, 0.5]]) center_stage=mt.tform(center) # these are now the light microscopy stage coordinates that correspond with this site lm_coords=at.inverse_tform(center_stage) # print mt # print 'center_stage',center_stage # print 'lm coords',lm_coords # print 'at',at # print site['AcquisitionSpec'].keys() pid=site['AcquisitionSpec']['WorkingProtocolUID'] pixsize, width, height=get_protocol_metadata(pid, project) # print site['Name'],',',section['Name'],',',siteset['Name'],',',mosaic['Name'] # print site['AcquisitionSpec']['AcquiredDataUID'] relpath=mosaic['FileName'][mosaic['FileName'].find( project_base):] # print relpath unixpath=relpath.replace('\\', '/') unixpath=os.path.join(project_dir, unixpath) basedir=os.path.split(unixpath)[0] base=os.path.splitext(unixpath)[0] updatespath=base + '.ve-updates' with open(updatespath) as fd: mosaicdoc=xmltodict.parse(fd.read())['ATLAS-Stitch-Info'] rootdir=mosaicdoc['OriginalRoot'] if type(mosaicdoc['Tile']) is not type([]): mosaicdoc['Tile']=[mosaicdoc['Tile']] sectnum=int(section['SectionIndex']) #print 'section number',sectnum sectionId='%d' % (1000 * ribnum + sectnum) sectionZ=renderapi.stack.get_section_z_value( lm_stack, sectionId, render=render) tilespecs=renderapi.tilespec.get_tile_specs_from_z( lm_stack, sectionZ, render=render) LMtile_xy=np.array( [[ts.layout.stageX, ts.layout.stageY] for ts in tilespecs]) #print 'sectionZ',sectionZ image_corners=np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) # print "at" # print at # print "mt" # print mt tilespeclist=[] for i, tile in enumerate(mosaicdoc['Tile']): distances=np.zeros(len(tilespecs)) imagepath=os.path.join(basedir, tile['Name']) maskpath=os.path.join( basedir, tile['Name'][0:-4] + '_mask.tif') flippath=os.path.join( basedir, tile['Name'][0:-4] + '_flip.jpg') tform=AtlasTransform(tile['ParentTransform']) # shift = np.array([[150,-80]]) shift=np.array([[0, 0]]) # tranform the EM tile through the transforms to get LM stage coordinates of corners EMtile_corners_lm_stage=at.inverse_tform( id_at.inverse_tform(mt.tform(tform.tform(image_corners) + shift))) # EMtile_corners_lm_stage[:,1]+=(2048*.107) # EMtile_corners_lm_stage[:,1]*=-1 #print "EMtile_corners_lm_stage",EMtile_corners_lm_stage # tranform the EM tile through the transforms to get LM stage coordinates of center # print tform EMtile_center_lm_stage=at.inverse_tform( id_at.inverse_tform(mt.tform(tform.tform(center) + shift))) # EMtile_center_lm_stage[:,1]+=(2048*.107) #print 'EMtile_center_lm_stage',EMtile_center_lm_stage # EMtile_center_lm_stage[:,1]*=-1 # print [(ts['layout']['stageX']-tile_lm_stage[0,0])**2+(ts['layout']['stageY']+tile_lm_stage[0,1])**2 for ts in tilespecs] # EMtile_xy = np.array([tile_lm_stage[0,0],-tile_lm_stage[0,1]]) # figure out which of the LM tiles is closest to this EM tile in terms of stage coordinates # the distance vector dist_xy=LMtile_xy - \ np.tile(EMtile_center_lm_stage, (len(tilespecs), 1)) # the euclidean distance in microns d=np.sqrt(np.sum(dist_xy**2, axis=1)) LMtile_i=np.argmin(d) # pick out the index of the smallest # this is the tilespec of the closest tile close_spec=tilespecs[LMtile_i] # print 'tile ',LMtile_i,'id',close_spec['tileId'], 'closest at ','%4.2f'%d[LMtile_i],' um' #print close_spec.tileId # this calculates the delta from the EM stage coordinates to the LM stage coordinates # and divides by the size of LM pixels, to get delta in pixels from the center of the LM tile # to each of the corners of the EM tile # note hardcoded LM pixel size delt=(EMtile_corners_lm_stage - \ LMtile_xy[LMtile_i, :]) / 0.107 delt_center=(EMtile_center_lm_stage - \ LMtile_xy[LMtile_i, :]) / 0.107 # this is the location in terms of pixels within the LM tile of the EM corners # this is with pixel 0,0 in the upper left, and assuming that the stage coordinates # are in such a manner that positive y is down, and positive x is to the right EMtile_corners_local_pixels=delt + \ np.array( [[close_spec.width / 2.0, close_spec.height / 2.0]]) EMtile_center_local_pixels=delt_center + \ np.array( [[close_spec.width / 2.0, close_spec.height / 2.0]]) # use renderapi to map these local pixel coordinates to the global space EMtile_corners_world_coords=renderapi.transform.estimate_dstpts(close_spec.tforms,EMtile_corners_local_pixels) EMtile_center_world_coords=renderapi.transform.estimate_dstpts(close_spec.tforms,EMtile_center_local_pixels) #print lm_stack #print "localmap",renderapi.transform.estimate_dstpts(close_spec.tforms,EMtile_center_local_pixels) #print "EMtile_center_local_pixels",EMtile_center_local_pixels #print "EMtile_center_world_coords",EMtile_center_world_coords # these are the local coordinates of the corners of the EM tile # listed in the same order as the "corners" variable, but noting # that the definition in what is 0,0 is different from ATLAS definition # this transformation of the tile needs to account for this EMpixel_corners=np.array([ [0.0, float(tile['Height'])], [0.0, 0.0], [float(tile['Width']), float(tile['Height'])], [float(tile['Width']), 0] ]) # print "from\n",EMpixel_corners # print "to\n",EMtile_corners_world_coords emtform=cv2.getAffineTransform(np.float32( EMpixel_corners[0:3, :]), np.float32(EMtile_corners_world_coords[0:3, :])) atlas_emt=AtlasTransform() atlas_emt.load_from_openCV(emtform) # print atlas_emt.tform(np.array([[0,0],[5000,5000],[0,5000],[5000,0]])) s=np.sqrt(-np.linalg.det(atlas_emt.M[0:2, 0:2])) # print atlas_emt.M[0:2,0:2]/s row, col=tile['Name'].split('_')[1].split('-') row=int(row[1:]) col=int(col[1:]) layout=Layout(sectionId=sectionId, scopeId="Gemini", cameraId='SEM3nm5K', imageRow=row, imageCol=col, stageX=tform.tform(center)[0, 0], stageY=tform.tform(center)[0, 1], rotation=0.0, pixelsize=0.03) # flip=AffineModel(M00=1, # M01=0, # M10=0, # M11=1, # B0=5000 * (col - 1), # B1=-5000 * (row - 1)) # am=AffineModel(M00=emtform[0, 0], # M01=emtform[0, 1], # M10=emtform[1, 0], # M11=emtform[1, 1], # B0=emtform[0, 2], # B1=emtform[1, 2]) amf=AffineModel(M00=emtform[0, 0], M01=emtform[0, 1], M10=-emtform[1, 0], M11=-emtform[1, 1], B0=emtform[0, 2], B1=emtform[1, 2]) tilespec=TileSpec(tileId=tile['UID'], z=sectionZ, width=int(tile['Width']), height=int(tile['Height']), imageUrl='file:' + \ flippath.replace(" ", "%20"), frameId=tile['UID'], maskUrl='file:' + \ maskpath.replace(" ", "%20"), tforms=[amf], minint=0, maxint=255, layout=layout) tilespeclist.append(tilespec) # row= (str(path),) + tform.to_tuple() # df.loc[i]=row # print tilespec.to_dict() # for tile in mosaicdoc['Tiles']['Tile']: # print tile['UID'],tile['@row'],tile['@col'],tile['StageX'],tile['StageY'] # df.to_csv(sitefile,index=False,header=False) tilespec_path = os.path.join(project_dir,'tilespecs') if not os.path.isdir(tilespec_path): os.makedirs(tilespec_path) json_file=os.path.join( tilespec_path, 'EM_rib%04dsect%04d_%s.json' % (ribnum, sectnum, sitename)) with open(json_file,'w') as fp: renderapi.utils.renderdump(tilespeclist,fp) json_files.append(json_file) return json_files
def make_tilespec_from_statetable (df,rootdir,outputProject,outputOwner,outputStack,minval=0,maxval=50000): df = df[df['zstack']==0] #ribbons = df.groupby('ribbon') #zoffset=0 #for ribbnum,ribbon in ribbons: # ribbon.loc[ribbon.index,'z']=ribbon['section']+zoffset # zoffset += ribbon['section'].max()+1 # df.loc[ribbon.index,'z']=ribbon['z'].values mipmap_args = [] tilespecpaths = [] for ((ch,sess),chgroup) in df.groupby(['ch_name','session']): print ch,sess for ((rib,sect),group) in chgroup.groupby(['ribbon','section']): tilespeclist=[] z=0 for ind,row in group.iterrows(): filepath=row.full_path fileparts=filepath.split(os.path.sep)[1:] tilespecdir = rootdir + "/processed/downsamp_tilespec/"+fileparts[5]+"/"+fileparts[6]+"/"+fileparts[7] #print tilespecdir if not os.path.isdir(tilespecdir): os.makedirs(tilespecdir) downdir = rootdir+"/processed/downsamp_images/"+fileparts[5]+"/"+fileparts[6]+"/"+fileparts[7] #print "This is the Down Sampled Directory: %s"%downdir if not os.path.exists(downdir): os.makedirs(downdir) #construct command for creating mipmaps for this tilespec #downcmd = ['python','create_mipmaps.py','--inputImage',filepath,'--outputDirectory',downdir,'--mipmaplevels','1','2','3'] #cmds.append(downcmd) mipmap_args.append((filepath,downdir)) layout = Layout(sectionId=row.ribbon*1000+row.section, scopeId='Leica', cameraId='zyla', imageRow=0, imageCol=0, stageX = row.xstage, stageY = row.ystage, rotation = 0.0, pixelsize = row.scale_x) mipmap0 = MipMapLevel(level=0,imageUrl=row.full_path) mipmaplevels=[mipmap0] filename = "%s_S%04d_F%04d_Z%02d.tif"%(row.ch_name,row.section,row.frame,0) for i in range(1,4): scUrl = 'file:' + os.path.join(downdir,filename[0:-4]+'_mip0%d.jpg'%i) mml = MipMapLevel(level=i,imageUrl=scUrl) mipmaplevels.append(mml) tform = AffineModel(M00=row.a00, M01=row.a01, M10=row.a10, M11=row.a11, B0=row.a02, B1=row.a12) tilespeclist.append(TileSpec(tileId=row.tileID, frameId = row.frame, z=row.z, width=row.width, height=row.height, mipMapLevels=mipmaplevels, tforms=[tform], minint=minval, maxint=maxval, layout= layout)) z = row.z json_text=json.dumps([t.to_dict() for t in tilespeclist],indent=4) json_file = os.path.join(tilespecdir,outputProject+'_'+outputOwner+'_'+outputStack+'_%04d.json'%z) fd=open(json_file, "w") fd.write(json_text) fd.close() tilespecpaths.append(json_file) return tilespecpaths,mipmap_args
def createpatch(tilespecs, lines, patchid, layerid, shiftx=0.0, shifty=0.0, affineOnly=False): import numpy as np ts = tilespecs[patchid] #fp = tilespecs[patchid]['mipmapLevels']['0']['imageUrl'] #print fp #fp = fp.replace("raw/data","processed/flatfieldcorrecteddata") #fp = fp.replace("session","Session000") fp = ts.ip.get(0)['imageUrl'] #left,right = fp.split('_F',1) #num,rright = right.split('_',1) #lenspeclist = len(tilespecs[patchid]['transforms']['specList']) lenspeclist = len(ts.tforms) #tString = tilespecs[patchid]['transforms']['specList'][lenspeclist-1]['dataString'] #print tilespecs[patchid].tforms[lenspeclist-1] if affineOnly: tform_total = AffineModel() for tform in ts.tforms: tform_total = tform.concatenate(tform_total) M00 = str(tform_total.M00) M10 = str(tform_total.M01) M01 = str(tform_total.M10) M11 = str(tform_total.M11) B0 = str(tform_total.B0 + shiftx) B1 = str(tform_total.B1 + shifty) else: B0 = str(ts.minX + shiftx) B1 = str(ts.minY + shifty) M00 = str(1.0) M01 = str(0.0) M10 = str(0.0) M11 = str(1.0) #B0 = str(0) #B1 = str(0) # local_corners = np.array([[0,0],[0,ts.height],[ts.width,ts.height],[ts.width,0],[0,0]]) # world_corners = render.local_to_world_coordinates_array() #world_corners = tform_total.tform(local_corners) #mins= np.min(world_corners,axis=0) fname = fp.split('/') filename_only = fp filename_only = filename_only.replace('file:', '').replace('%20', ' ') lines.append("\t<t2_patch\n") #lines.append("\toid='" + str(patchid+(1000*layerid)) + "'\n") lines.append("\toid= '" + ts.tileId + "'\n") lines.append("\twidth='" + str(ts.width) + "'\n") lines.append("\theight='" + str(ts.height) + "'\n") #lines.append("\ttransform='matrix(" + t[0] + "," + t[1] + "," + t[2] + "," + t[3] + "," + t[4] + "," + t[5] + ")'\n") lines.append("\ttransform='matrix(" + M00 + "," + M01 + "," + M10 + "," + M11 + "," + B0 + "," + B1 + ")'\n") lines.append("\tlinks=''\n") lines.append("\ttype='1'\n") lines.append("\tfile_path='" + filename_only + "'\n") lines.append("\ttitle= '" + ts.tileId + "'\n") lines.append("\tstyle='fill-opacity:1.0;stroke:#ffff00;'\n") lines.append("\to_width='" + str(int(ts.width)) + "'\n") lines.append("\to_height='" + str(int(ts.height)) + "'\n") lines.append("\tmin= '" + str(ts.minint) + "'\n") lines.append("\tmax= '" + str(ts.maxint) + "'\n") lines.append("\tmres='32'\n") lines.append("\t>\n") if not affineOnly: lines.append("\t<ict_transform_list>\n") for tform in ts.tforms: tformdict = tform.to_dict() lines.append("\t\t<iict_transform class='%s' data='%s' />\n" % (tformdict['className'], tformdict['dataString'])) lines.append("\t</ict_transform_list>\n") lines.append("\t</t2_patch>\n")
def process_z(r, prealignedstack, postalignedstack, sourcestack, outstack, z, num_points=4): ts_source = r.run(renderapi.tilespec.get_tile_specs_from_z, sourcestack, z) final_list = [] start_index = 0 index_dict = {} #loop over the source tilespecs to figure out where they each go for ts in ts_source: #define a grid of local coordinates across the source tile xy_local_source = define_local_grid(ts, num_points) #map those local coordinates to the registered world coordinates xy_local_source_json = renderapi.coordinate.package_point_match_data_into_json( xy_local_source, ts.tileId, 'local') #package them into a list of lists for batch processing for elem in xy_local_source_json: final_list.append([elem]) end_index = start_index + len(xy_local_source_json) #keep track of where in the final_list these coordinates are to pull out later index_dict[ts.tileId] = { 'start_index': start_index, 'end_index': end_index } start_index = end_index #final_list.append(temp_list) #map all those local coordinates into world coordinates of the registered source stack xy_world_reg = r.run( renderapi.coordinate.local_to_world_coordinates_clientside, sourcestack, final_list, z, number_of_threads=3) #map those world coordinates to the local coordinates of the prealigned stack xy_local_prealigned_json = r.run( renderapi.coordinate.world_to_local_coordinates_clientside, prealignedstack, xy_world_reg, z, number_of_threads=3) #map those local coordinates to the world coordinates of the postaligned stack xy_world_postaligned_json = r.run( renderapi.coordinate.local_to_world_coordinates_clientside, postalignedstack, xy_local_prealigned_json, z, number_of_threads=3) #replace the transform for this tile with that transformation for ts in ts_source: xy_local_source = define_local_grid(ts, num_points) start = index_dict[ts.tileId]['start_index'] end = index_dict[ts.tileId]['end_index'] #pull out the correct elements of the list registered_world_coords = xy_world_reg[start:end] aligned_world_coords_json = xy_world_postaligned_json[start:end] #packaged them into an numpy array good_aligned_world_coords = [ c for c in aligned_world_coords_json if 'error' not in c.keys() ] aligned_world_coords = renderapi.coordinate.unpackage_local_to_world_point_match_from_json( good_aligned_world_coords) #fit a polynomial tranformation tform = AffineModel() notError = np.array([('error' not in d.keys()) for d in aligned_world_coords_json]) tform.estimate(xy_local_source[notError, :], aligned_world_coords) ts.tforms = [tform] logger.debug('from,to') for frompt, topt in zip(registered_world_coords, aligned_world_coords_json): logger.debug((frompt, topt)) #break r.run(renderapi.client.import_tilespecs, outstack, ts_source) return None
def AffineMPL_2_AffineRender(T): """Convert `AffineMPL` object to `AffineRender` object""" A = AffineRender() A.M = T.get_matrix() return A