if k < min(nLayers, currentWrittenLayer + nLayersAtATime): IJ.log('Start exporting layer ' + str(k) + ' currentWrittenLayer - ' + str(currentWrittenLayer)) fc.exportFlat(project, exportFolder, 1/float(LMEMFactor), baseName = 'alignedDownsampledEM', bitDepth = 8, layers = [k]) namePlugin = 'export_alignedEMForRegistration' MagCFolder = fc.startPlugin(namePlugin) ControlWindow.setGUIEnabled(False) MagCParams = fc.readMagCParameters(MagCFolder) nLayersAtATime = MagCParams[namePlugin]['nLayersAtATime'] nThreads = MagCParams[namePlugin]['nThreads'] LMEMFactor = fc.getLMEMFactor(MagCFolder) IJ.log('Exporting with LMEMFactor = ' + str(LMEMFactor)) projectPath = fc.findFilesFromTags(MagCFolder,['EM', 'Project'])[0] exportFolder = fc.mkdir_p(os.path.join(os.path.dirname(projectPath), namePlugin)) project, loader, layerset, nLayers = fc.openTrakemProject(projectPath) temporaryFolder = fc.mkdir_p(os.path.join(os.path.dirname(projectPath), 'temporary_LMEMRegistration')) # to save contrasted images # currentLayerPath stores in a file the current layer being processed by the script which is run several times currentLayerPath = os.path.join(os.path.dirname(projectPath), 'currentLayer_' + namePlugin + '.txt') currentWrittenLayer = fc.incrementCounter(currentLayerPath, increment = nLayersAtATime) atom = AtomicInteger(currentWrittenLayer) fc.startThreads(exportLayer, wait = 0, nThreads = nThreads) # project.save() # why do I save the project here ? time.sleep(3) fc.shouldRunAgain(namePlugin, currentWrittenLayer, nLayers, MagCFolder, project, increment = nLayersAtATime)
str(toAlignPatchPath)) aff = AffineTransform( [float(transforms[a]) for a in range(i + 2, i + 8)]) patch = Patch.createPatch(project, toAlignPatchPath) layer = layerset.getLayers().get(l) layer.add(patch) patch.setAffineTransform(aff) patch.updateBucket() time.sleep(1) IJ.log('Readjusting display') fc.resizeDisplay(layerset) IJ.log('Blending all layers') Blending.blendLayerWise(layerset.getLayers(), True, None) IJ.log('Exporting') for scaleFactor in scaleFactors: theBaseName = 'exported_downscaled_' + str(int( 1 / float(scaleFactor))) + '_' + channel outputFolder = fc.mkdir_p( os.path.join(os.path.dirname(transformsPath), theBaseName)) fc.exportFlat(project, outputFolder, scaleFactor, baseName=theBaseName, bitDepth=8, flipX=flipX) fc.closeProject(project) fc.terminatePlugin(namePlugin, MagCFolder)
normLocalContrastSize = MagCParameters[namePlugin][ 'normLocalContrastSize'] # size of the neighborhood for local contrast for the brightfield channel overlap = MagCParameters[namePlugin][ 'overlap'] # overlap between tiles, typically 0.1 refChannelIdentifier = str(MagCParameters[namePlugin]['refChannelIdentifier']) normLocalContrastSizeFluo = MagCParameters[namePlugin][ 'normLocalContrastSizeFluo'] # for contrasting the fluo channels minMaxFluo = MagCParameters[namePlugin][ 'minMaxFluo'] # for thresholding the fluo channels flipHorizontally = MagCParameters[namePlugin][ 'flipHorizontally'] # flip horizontally the LM tiles # initialize folders LMDataFolder = os.path.join(MagCFolder, 'LMDataReordered') LMFolder = fc.mkdir_p(os.path.join(MagCFolder, 'MagC_LM')) # read metadata LMMetadataPath = os.path.join(LMDataFolder, 'LM_Metadata.txt') width, height, nChannels, xGrid, yGrid, scaleX, scaleY, channels = fc.readSessionMetadata( MagCFolder) # get reference channel name IJ.log('The reference channel identifier is: ' + refChannelIdentifier) refChannel = filter(lambda x: refChannelIdentifier in x, channels)[0] IJ.log('channels ' + str(channels)) IJ.log('refChannel: ' + refChannel) # Preprocess the reference brightfield channel: 8-bit with mean sensible range pulled from all images # find thresholding range IJ.log('Reading all images of the channel to find a good intensity range: ' +
registrationFolder = os.path.join(os.path.dirname(projectPath), 'LMEMRegistration') f = open(os.path.join(registrationFolder, 'lowResEMBounds'), 'r') widthEM, heightEM = pickle.load(f) f.close() pZ, loaderZ, layersetZ, nLayersZ = fc.getProjectUtils( fc.initTrakem(registrationFolder, 1)) layersetZ.setDimensions(0, 0, widthEM * 5, heightEM * 5) layerZ = layersetZ.getLayers().get(0) # create the folders for channel in channels: affineCroppedFolder = fc.mkdir_p( os.path.join(LMFolder, 'affineCropped_' + channel)) for l in range(nLayers): layerFolder = os.path.join(registrationFolder, 'layer_' + str(l).zfill(4)) registeredFolder = os.path.join(layerFolder, 'registered') affTransformPath = os.path.join(registeredFolder, 'affineSerialized') if os.path.isfile(affTransformPath): affTransform = loaderZ.deserialize(affTransformPath) for channel in channels: affineCroppedFolder = os.path.join(LMFolder, 'affineCropped_' + channel) LMMosaicsPath = fc.cleanLinuxPath( os.path.join( LMFolder, 'exported_downscaled_1_' + channel,
def computeRegistration(): while atomicI.get() < nSections: l = atomicI.getAndIncrement() if l < nSections: IJ.log('Computing EM/LM registration for layer ' + str(l).zfill(4)) layerFolder = fc.mkdir_p( os.path.join(registrationFolder, 'layer_' + str(l).zfill(4))) toRegisterFolder = fc.mkdir_p( os.path.join(layerFolder, 'toRegister')) registeredFolder = fc.mkdir_p( os.path.join(layerFolder, 'registered')) # Applying appropriate filters to make lowresEM and LM look similar for layer l imLM = IJ.openImage(imPaths['LM'][l]) imLM = fc.localContrast(imLM) imLMPath = os.path.join(toRegisterFolder, 'imLM_' + str(l).zfill(4) + '.tif') IJ.save(imLM, imLMPath) imEM = IJ.openImage(imPaths['EM'][l]) imEM = fc.localContrast(imEM) imEM = fc.blur(imEM, 2) imEMPath = os.path.join(toRegisterFolder, 'imEM_' + str(l).zfill(4) + '.tif') IJ.save(imEM, imEMPath) # Compute first a simple affine registration on the non-cropped images IJ.log( 'Computing affine and moving least squares alignment for layer ' + str(l).zfill(4)) firstStepRegistered = False # registration at first step with 1step/octave (less features) pLowRes = getSIFTMatchingParameters(nOctaves[0], 1.6, 16, 4000, 8, 4) featuresLM = getFeatures(imLMPath, pLowRes) featuresEM = getFeatures(imEMPath, pLowRes) matchingResults = getMatchingResults(featuresLM, featuresEM) if matchingResults is None: IJ.log( 'No registration matching at low resolution matching step 1 in layer ' + str(l).zfill(4)) else: model, inliers = matchingResults distance = PointMatch.meanDistance( inliers ) # mean displacement of the remaining matching features IJ.log('---Layer ' + str(l).zfill(4) + ' distance ' + str(distance) + ' px with ' + str(len(inliers)) + ' inliers') if distance > matchingThreshold[0]: IJ.log( 'Matching accuracy is lower than the threshold at the low resolution step 1 - ' + str(l).zfill(4) + ' - distance - ' + str(distance)) else: affTransform = model.createAffine() s1, s2 = getScalingFactors(affTransform) IJ.log('Layer ' + str(l).zfill(4) + ' scaling factors - step 1 - ' + str(s1) + ' - ' + str(s2) + '--' + str(s1 * s2) + ' affDeterminant ' + str(affTransform.getDeterminant()) + ' nInliers ' + str(len(inliers))) if (abs(s1 - 1) < 0.2) and ( abs(s2 - 1) < 0.2 ): # scaling in both directions should be close to 1 IJ.log('First step ok - layer ' + str(l).zfill(4)) firstStepRegistered = True loaderZ.serialize( affTransform, os.path.join(registeredFolder, 'affineSerialized')) if not firstStepRegistered: IJ.log( 'First step registration in layer ' + str(l).zfill(4) + ' with few features has failed. Trying with more features.' ) # registration at first step with 3steps/octave (more features) pLowRes = getSIFTMatchingParameters(3, 1.6, 64, 4000, 8, 4) #pLowRes = getSIFTMatchingParameters(nOctaves[0], 1.6, 16, 4000, 8, 4) # for BIB featuresLM = getFeatures(imLMPath, pLowRes) featuresEM = getFeatures(imEMPath, pLowRes) matchingResults = getMatchingResults(featuresLM, featuresEM) if matchingResults is None: IJ.log( 'No registration matching at low resolution matching step 1bis in layer ' + str(l).zfill(4)) else: model, inliers = matchingResults distance = PointMatch.meanDistance( inliers ) # mean displacement of the remaining matching features IJ.log('---Layer ' + str(l).zfill(4) + ' distance ' + str(distance) + ' px with ' + str(len(inliers)) + ' inliers') if distance > matchingThreshold[0]: IJ.log( 'Matching accuracy is lower than the threshold at the high resolution step 1bis - ' + str(l).zfill(4) + ' - distance - ' + str(distance)) else: affTransform = model.createAffine() s1, s2 = getScalingFactors(affTransform) IJ.log('Layer ' + str(l).zfill(4) + ' scaling factors - step 1bis - ' + str(s1) + ' - ' + str(s2) + '--' + str(s1 * s2) + ' affDeterminant ' + str(affTransform.getDeterminant()) + ' nInliers ' + str(len(inliers))) if (abs(s1 - 1) < 0.2) and ( abs(s2 - 1) < 0.2 ): # scaling in both directions should be close to 1 IJ.log('First step 1bis ok - layer ' + str(l).zfill(4)) firstStepRegistered = True loaderZ.serialize( affTransform, os.path.join(registeredFolder, 'affineSerialized')) if not firstStepRegistered: IJ.log('The two first step trials in layer ' + str(l).zfill(4) + ' have failed') else: # Affine transform and crop the LM, and compute a high res MLS matching with lock: # only one trakem working at a time # apply affTransform patch = Patch.createPatch(pZ, imLMPath) layerZ.add(patch) patch.setAffineTransform(affTransform) patch.updateBucket() # crop and export bb = Rectangle(0, 0, widthEM, heightEM) affineCroppedIm = loaderZ.getFlatImage( layerZ, bb, 1, 0x7fffffff, ImagePlus.GRAY8, Patch, layerZ.getAll(Patch), True, Color.black, None) affineCroppedImPath = os.path.join( toRegisterFolder, 'affineCroppedLM_' + str(l).zfill(4) + '.tif') IJ.save(affineCroppedIm, affineCroppedImPath) affineCroppedIm.close() layerZ.remove(patch) layerZ.recreateBuckets() pHighRes = getSIFTMatchingParameters(nOctaves[1], 1.6, 64, 4096, 8, 4) featuresLM = getFeatures(affineCroppedImPath, pHighRes) featuresEM = getFeatures(imEMPath, pHighRes) # get the MLS matchingResults = getMatchingResults(featuresLM, featuresEM) if matchingResults is None: IJ.log( 'It cannot be, there should be a good match given that an affine was computed. Layer ' + str(l).zfill(4)) else: model, inliers = matchingResults affTransform = model.createAffine() s1, s2 = getScalingFactors(affTransform) IJ.log('Second step determinant - layer ' + str(l).zfill(4) + ' - determinant - ' + str(affTransform.getDeterminant()) + ' nInliers ' + str(len(inliers)) + 'Scaling factors - step 2 - ' + str(s1) + ' - ' + str(s2)) if (abs(s1 - 1) < 0.2) and (abs(s2 - 1) < 0.2) and len( inliers ) > 50: # scaling in both directions should be close to 1 distance = PointMatch.meanDistance( inliers ) # mean displacement of the remaining matching features if distance > matchingThreshold[1]: IJ.log( 'Weird: matching accuracy is lower than the threshold at the high resolution step 2 - ' + str(l).zfill(4) + ' - distance - ' + str(distance)) else: mlst = MovingLeastSquaresTransform() mlst.setModel(AffineModel2D) mlst.setAlpha(1) mlst.setMatches(inliers) xmlMlst = mlst.toXML('\t') with open( os.path.join(registeredFolder, 'MLST.xml'), 'w') as f: f.write(xmlMlst) loaderZ.serialize( mlst, os.path.join(registeredFolder, 'mlstSerialized')) registrationStats.append( [l, distance, len(inliers)])
filePaths.append(imPath) with open(filePathsPath,'w') as f: for path in filePaths: f.write(path + '\n') # pickle.dump(filePaths,f) else: filePaths = [] with open(filePathsPath,'r') as f: lines = f.readlines() for line in lines: filePaths.append(line.replace('\n', '')) # filePaths = pickle.load(f) #Create all the subfolders downSampledEMFolder = fc.mkdir_p(os.path.join(MagCEMFolder, 'MagC_EM_' + factorString, '')) for sectionFolderName in os.walk(EMDataFolder).next()[1]: fc.mkdir_p(os.path.join(downSampledEMFolder, sectionFolderName)) normLocalContrastSize = MagCParameters[namePlugin]['normLocalContrastSize'] # downsample in parallel threads = [] currentLayerPath = os.path.join(MagCEMFolder, 'currentLayer_' + namePlugin + '.txt') currentWrittenLayer = fc.incrementCounter(currentLayerPath, increment = nTilesAtATime) IJ.log(namePlugin + ' layer ' + str(currentWrittenLayer)) atomicI = AtomicInteger(currentWrittenLayer) fc.startThreads(resizeAndSave, fractionCores = 0.9, wait = 0, arguments = (filePaths, atomicI)) # terminate or rerun if more tiles to be processed time.sleep(1) fc.shouldRunAgain(namePlugin, atomicI.get(), len(filePaths), MagCFolder, '')
MLSTransform = CoordinateTransformXML().parse(MLSTPath) affineCroppedImPath = os.path.join( affineCroppedFolder, 'affineCropped_' + channel + '_' + str(l).zfill(4) + '.tif') patch = Patch.createPatch(p, affineCroppedImPath) layer.add(patch) patch.setCoordinateTransform( MLSTransform ) # does the order matter ? apparently yes, but I have to be sure that it is not an offset problem IJ.log('Setting the mlsTransform in layer ' + str(l) + ' ' + str(MLSTransform)) patch.updateBucket() if idChannel < len(channels) - 2: # if it is a fluochannel MLSTransformedFolder = fc.mkdir_p( os.path.join(LMFolder, 'MLS_Transformed_' + str(channel), '')) imp = loader.getFlatImage(layer, roiExport, 1, 0x7fffffff, ImagePlus.GRAY8, Patch, layer.getAll(Patch), True, Color.black, None) impPath = os.path.join( MLSTransformedFolder, 'MLSTransformed_' + channel + '_' + str(l).zfill(4) + '.tif') IJ.save(imp, impPath) IJ.log('Project ' + channel + ' assembled') # # Warning ! Should I resize or not ? does this not create an offset ? # fc.resizeDisplay(layerset)
#locations x = float( line.replace('\n', '').split(';')[2].split(',')[0].split('(')[1]) y = float( line.replace('\n', '').split(';')[2].split(',')[1].split(')')[0]) allPatchCoordinates.append([path, [x, y], k]) namePlugin = 'assembly_lowEM' MagCFolder = fc.startPlugin(namePlugin) ControlWindow.setGUIEnabled(False) MagC_EM_Folder = fc.mkdir_p(os.path.join(MagCFolder, 'MagC_EM', '')) MagCParameters = fc.readMagCParameters(MagCFolder) downsamplingFactor = MagCParameters['downsample_EM']['downsamplingFactor'] factorString = str(int(1000000 * downsamplingFactor)).zfill(8) # read some metadata EMMetadataPath = fc.findFilesFromTags(MagCFolder, ['EM', 'Metadata'])[0] EMMetadata = fc.readParameters(EMMetadataPath) numTilesX = EMMetadata['numTilesX'] numTilesY = EMMetadata['numTilesY'] xPatchEffectiveSize = EMMetadata['xPatchEffectiveSize'] yPatchEffectiveSize = EMMetadata['yPatchEffectiveSize'] tileOverlapX = EMMetadata['tileOverlapX'] tileOverlapY = EMMetadata['tileOverlapY'] nbLayers = EMMetadata['nSections']
regModel = MagCParameters[namePlugin]['regModel'] inputFolder = fc.findFoldersFromTags(MagCFolder, ['export_stitchedEMForAlignment'])[0] imagePaths = filter( lambda x: os.path.splitext(x)[1] == '.tif', fc.naturalSort( [os.path.join(inputFolder, x) for x in os.listdir(inputFolder)])) regParams = Register_Virtual_Stack_MT.Param() regParams.minInlierRatio = 0 regParams.registrationModelIndex = regModel # 1-Rigid, 2-Similarity, 3-Affine regParams.featuresModelIndex = regModel exportForRigidAlignmentFolder = inputFolder resultRigidAlignmentFolder = fc.mkdir_p( os.path.join(MagC_EM_Folder, 'resultRigidAlignment')) ################################################ # rigid alignment outside trakem2 with register virtual stack plugin because bug in trakem2 transformsPath = os.path.join( MagC_EM_Folder, 'rigidAlignmentTransforms_' + namePlugin + '.txt') referenceName = fc.naturalSort(os.listdir(exportForRigidAlignmentFolder))[0] use_shrinking_constraint = 0 if len(os.listdir(resultRigidAlignmentFolder)) != 2 * len( os.listdir(inputFolder)): IJ.log('Rigid alignment with register virtual stack') Register_Virtual_Stack_MT.exec(exportForRigidAlignmentFolder, resultRigidAlignmentFolder, resultRigidAlignmentFolder, referenceName, regParams, use_shrinking_constraint)
if k < min(nLayers, currentWrittenLayer + nLayersAtATime): IJ.log('Start exporting layer ' + str(k) + ' currentWrittenLayer - ' + str(currentWrittenLayer)) fc.exportFlat(project, exportFolder, 1/float(downsamplingFactor), baseName = 'stitchedDownsampledEM', bitDepth = 8, layers = [k]) namePlugin = 'export_stitchedEMForAlignment' MagCFolder = fc.startPlugin(namePlugin) ControlWindow.setGUIEnabled(False) MagCParams = fc.readMagCParameters(MagCFolder) nLayersAtATime = min (MagCParams[namePlugin]['nLayersAtATime'], Runtime.getRuntime().availableProcessors()) nThreads = MagCParams[namePlugin]['nThreads'] # getting downsamplingFactor downsamplingFactor = MagCParams['downsample_EM']['downsamplingFactor'] projectPath = fc.cleanLinuxPath(fc.findFilesFromTags(MagCFolder,['EM', 'Project'])[0]) exportFolder = fc.mkdir_p(os.path.join(os.path.dirname(projectPath), namePlugin)) project, loader, layerset, nLayers = fc.openTrakemProject(projectPath) fc.resizeDisplay(layerset) # has been done in previous script but in case ... currentLayerPath = os.path.join(os.path.dirname(projectPath), 'currentLayer_' + namePlugin + '.txt') currentWrittenLayer = fc.incrementCounter(currentLayerPath, increment = nLayersAtATime) atom = AtomicInteger(currentWrittenLayer) fc.startThreads(exportLayer, wait = 0, nThreads = nThreads) # project.save() # why do I save the project here ? To save mipmaps for subsequent faster processing ? Probably not needed ... time.sleep(3) fc.shouldRunAgain(namePlugin, currentWrittenLayer, nLayers, MagCFolder, project, increment = nLayersAtATime)