public void ExportParticlesMovieOld(Star table, int size) { List<int> RowIndices = new List<int>(); string[] ColumnMicrographName = table.GetColumn("rlnMicrographName"); for (int i = 0; i < ColumnMicrographName.Length; i++) if (ColumnMicrographName[i].Contains(RootName)) RowIndices.Add(i); if (RowIndices.Count == 0) return; if (!Directory.Exists(ParticlesDir)) Directory.CreateDirectory(ParticlesDir); if (!Directory.Exists(ParticleCTFDir)) Directory.CreateDirectory(ParticleCTFDir); MapHeader OriginalHeader = MapHeader.ReadFromFile(Path, new int2(MainWindow.Options.InputDatWidth, MainWindow.Options.InputDatHeight), MainWindow.Options.InputDatOffset, ImageFormatsHelper.StringToType(MainWindow.Options.InputDatType)); /*Image OriginalStack = StageDataLoad.LoadMap(Path, new int2(MainWindow.Options.InputDatWidth, MainWindow.Options.InputDatHeight), MainWindow.Options.InputDatOffset, ImageFormatsHelper.StringToType(MainWindow.Options.InputDatType));*/ //OriginalStack.Xray(20f); int3 Dims = OriginalHeader.Dimensions; int3 DimsRegion = new int3(size, size, 1); int NParticles = RowIndices.Count / Dimensions.Z; float PixelSize = (float)(MainWindow.Options.CTFPixelMin + MainWindow.Options.CTFPixelMax) * 0.5f; float PixelDelta = (float)(MainWindow.Options.CTFPixelMax - MainWindow.Options.CTFPixelMin) * 0.5f; float PixelAngle = (float)MainWindow.Options.CTFPixelAngle / (float)(180.0 / Math.PI); Image CTFCoords; { float2[] CTFCoordsData = new float2[DimsRegion.ElementsSlice()]; //Helper.ForEachElementFT(new int2(DimsRegion), (x, y, xx, yy) => for (int y = 0; y < DimsRegion.Y; y++) for (int x = 0; x < DimsRegion.X / 2 + 1; x++) { int xx = x; int yy = y < DimsRegion.Y / 2 + 1 ? y : y - DimsRegion.Y; float xs = xx / (float)DimsRegion.X; float ys = yy / (float)DimsRegion.Y; float r = (float)Math.Sqrt(xs * xs + ys * ys); float angle = (float)(Math.Atan2(yy, xx)); float CurrentPixelSize = PixelSize + PixelDelta * (float)Math.Cos(2f * (angle - PixelAngle)); CTFCoordsData[y * (DimsRegion.X / 2 + 1) + x] = new float2(r / CurrentPixelSize, angle); } //); CTFCoords = new Image(CTFCoordsData, DimsRegion.Slice(), true); //CTFCoords.RemapToFT(); } Image CTFFreq = CTFCoords.AsReal(); Image CTFStack = new Image(new int3(size, size, NParticles * Dimensions.Z), true); int CTFStackIndex = 0; string[] ColumnPosX = table.GetColumn("rlnCoordinateX"); string[] ColumnPosY = table.GetColumn("rlnCoordinateY"); int3[] Origins = new int3[NParticles]; for (int i = 0; i < NParticles; i++) Origins[i] = new int3((int)double.Parse(ColumnPosX[RowIndices[i]]) - DimsRegion.X * 2 / 2, (int)double.Parse(ColumnPosY[RowIndices[i]]) - DimsRegion.Y * 2 / 2, 0); int IndexOffset = RowIndices[0]; string[] ColumnOriginX = table.GetColumn("rlnOriginX"); string[] ColumnOriginY = table.GetColumn("rlnOriginY"); string[] ColumnPriorX = table.GetColumn("rlnOriginXPrior"); string[] ColumnPriorY = table.GetColumn("rlnOriginYPrior"); float2[] ShiftPriors = new float2[NParticles]; for (int i = 0; i < NParticles; i++) ShiftPriors[i] = new float2(float.Parse(ColumnPriorX[IndexOffset + i]), float.Parse(ColumnPriorY[IndexOffset + i])); float2[][] ParticleTracks = new float2[NParticles][]; for (int i = 0; i < NParticles; i++) { ParticleTracks[i] = new float2[Dimensions.Z]; for (int z = 0; z < Dimensions.Z; z++) ParticleTracks[i][z] = new float2(float.Parse(ColumnOriginX[IndexOffset + z * NParticles + i]) - ShiftPriors[i].X, float.Parse(ColumnOriginY[IndexOffset + z * NParticles + i]) - ShiftPriors[i].Y); } Image AverageFT = new Image(new int3(DimsRegion.X, DimsRegion.Y, NParticles), true, true); Image AveragePS = new Image(new int3(DimsRegion.X, DimsRegion.Y, NParticles), true); Image Weights = new Image(new int3(DimsRegion.X, DimsRegion.Y, NParticles), true); Weights.Fill(1e-6f); Image FrameParticles = new Image(IntPtr.Zero, new int3(DimsRegion.X * 2, DimsRegion.Y * 2, NParticles)); float StepZ = 1f / Math.Max(Dims.Z - 1, 1); for (int z = 0; z < Dims.Z; z++) { float CoordZ = z * StepZ; /*GPU.Extract(OriginalStack.GetDeviceSlice(z, Intent.Read), FrameParticles.GetDevice(Intent.Write), Dims.Slice(), new int3(DimsRegion.X * 2, DimsRegion.Y * 2, 1), Helper.ToInterleaved(Origins), (uint)NParticles);*/ // Shift particles { float3[] Shifts = new float3[NParticles]; for (int i = 0; i < NParticles; i++) { float NormX = Math.Max(0.15f, Math.Min((float)Origins[i].X / Dims.X, 0.85f)); float NormY = Math.Max(0.15f, Math.Min((float)Origins[i].Y / Dims.Y, 0.85f)); float3 Coords = new float3(NormX, NormY, CoordZ); Shifts[i] = new float3(GridMovementX.GetInterpolated(Coords) + ParticleTracks[i][z].X, GridMovementY.GetInterpolated(Coords) + ParticleTracks[i][z].Y, 0f); } FrameParticles.ShiftSlices(Shifts); } Image FrameParticlesCropped = FrameParticles.AsPadded(new int2(DimsRegion)); Image FrameParticlesFT = FrameParticlesCropped.AsFFT(); FrameParticlesCropped.Dispose(); Image PS = new Image(new int3(DimsRegion.X, DimsRegion.Y, NParticles), true); PS.Fill(1f); // Apply motion blur filter. { const int Samples = 11; float StartZ = (z - 0.75f) * StepZ; float StopZ = (z + 0.75f) * StepZ; float2[] Shifts = new float2[Samples * NParticles]; for (int p = 0; p < NParticles; p++) { float NormX = Math.Max(0.15f, Math.Min((float)Origins[p].X / Dims.X, 0.85f)); float NormY = Math.Max(0.15f, Math.Min((float)Origins[p].Y / Dims.Y, 0.85f)); for (int zz = 0; zz < Samples; zz++) { float zp = StartZ + (StopZ - StartZ) / (Samples - 1) * zz; float3 Coords = new float3(NormX, NormY, zp); Shifts[p * Samples + zz] = new float2(GridMovementX.GetInterpolated(Coords), GridMovementY.GetInterpolated(Coords)); } } Image MotionFilter = new Image(IntPtr.Zero, new int3(DimsRegion.X, DimsRegion.Y, NParticles), true); GPU.CreateMotionBlur(MotionFilter.GetDevice(Intent.Write), DimsRegion, Helper.ToInterleaved(Shifts.Select(v => new float3(v.X, v.Y, 0)).ToArray()), Samples, (uint)NParticles); PS.Multiply(MotionFilter); //MotionFilter.WriteMRC("motion.mrc"); MotionFilter.Dispose(); } // Apply CTF. if (CTF != null) { CTFStruct[] Structs = new CTFStruct[NParticles]; for (int p = 0; p < NParticles; p++) { CTF Altered = CTF.GetCopy(); Altered.Defocus = (decimal)GridCTF.GetInterpolated(new float3(float.Parse(ColumnPosX[RowIndices[p]]) / Dims.X, float.Parse(ColumnPosY[RowIndices[p]]) / Dims.Y, z * StepZ)); Structs[p] = Altered.ToStruct(); } Image CTFImage = new Image(IntPtr.Zero, new int3(DimsRegion.X, DimsRegion.Y, NParticles), true); GPU.CreateCTF(CTFImage.GetDevice(Intent.Write), CTFCoords.GetDevice(Intent.Read), (uint)CTFCoords.ElementsSliceComplex, Structs, false, (uint)NParticles); //CTFImage.Abs(); PS.Multiply(CTFImage); //CTFImage.WriteMRC("ctf.mrc"); CTFImage.Dispose(); } // Apply dose weighting. /*{ float3 NikoConst = new float3(0.245f, -1.665f, 2.81f); // Niko's formula expects e-/A2/frame, we've got e-/px/frame -- convert! float FrameDose = (float)MainWindow.Options.CorrectDosePerFrame * (z + 0.5f) / (PixelSize * PixelSize); Image DoseImage = new Image(IntPtr.Zero, DimsRegion, true); GPU.DoseWeighting(CTFFreq.GetDevice(Intent.Read), DoseImage.GetDevice(Intent.Write), (uint)DoseImage.ElementsSliceComplex, new[] { FrameDose }, NikoConst, 1); PS.MultiplySlices(DoseImage); //DoseImage.WriteMRC("dose.mrc"); DoseImage.Dispose(); }*/ // Copy custom CTF into the CTF stack GPU.CopyDeviceToDevice(PS.GetDevice(Intent.Read), new IntPtr((long)CTFStack.GetDevice(Intent.Write) + CTFStack.ElementsSliceReal * NParticles * z * sizeof (float)), CTFStack.ElementsSliceReal * NParticles); Image PSAbs = new Image(PS.GetDevice(Intent.Read), new int3(DimsRegion.X, DimsRegion.Y, NParticles), true); PSAbs.Abs(); FrameParticlesFT.Multiply(PSAbs); AverageFT.Add(FrameParticlesFT); Weights.Add(PSAbs); PS.Multiply(PSAbs); AveragePS.Add(PS); PS.Dispose(); FrameParticlesFT.Dispose(); PSAbs.Dispose(); // Write paths to custom CTFs into the .star for (int i = 0; i < NParticles; i++) { string ParticleCTFPath = (CTFStackIndex + 1).ToString("D6") + "@particlectf/" + RootName + ".mrcs"; table.SetRowValue(RowIndices[NParticles * z + i], "rlnCtfImage", ParticleCTFPath); CTFStackIndex++; } } FrameParticles.Dispose(); CTFCoords.Dispose(); CTFFreq.Dispose(); AverageFT.Divide(Weights); AveragePS.Divide(Weights); Weights.Dispose(); Image AverageParticles = AverageFT.AsIFFT(); AverageFT.Dispose(); GPU.NormParticles(AverageParticles.GetDevice(Intent.Read), AverageParticles.GetDevice(Intent.Write), DimsRegion, (uint)(90f / PixelSize), true, (uint)NParticles); HeaderMRC ParticlesHeader = new HeaderMRC { Pixelsize = new float3(PixelSize, PixelSize, PixelSize) }; AverageParticles.WriteMRC(ParticlesPath, ParticlesHeader); AverageParticles.Dispose(); //OriginalStack.Dispose(); CTFStack.WriteMRC(DirectoryName + "particlectf/" + RootName + ".mrcs"); CTFStack.Dispose(); /*for (int i = 0; i < NParticles; i++) { string ParticlePath = (i + 1).ToString("D6") + "@particles/" + RootName + "_particles.mrcs"; table.SetRowValue(RowIndices[i], "rlnImageName", ParticlePath); }*/ AveragePS.Dispose(); //table.RemoveRows(RowIndices.Skip(NParticles).ToArray()); }
public Image AsRegion(int3 origin, int3 dimensions) { if (origin.X + dimensions.X >= Dims.X || origin.Y + dimensions.Y >= Dims.Y || origin.Z + dimensions.Z >= Dims.Z) throw new IndexOutOfRangeException(); float[][] Source = GetHost(Intent.Read); float[][] Region = new float[dimensions.Z][]; int3 RealSourceDimensions = DimsEffective; if (IsComplex) RealSourceDimensions.X *= 2; int3 RealDimensions = new int3((IsFT ? dimensions.X / 2 + 1 : dimensions.X) * (IsComplex ? 2 : 1), dimensions.Y, dimensions.Z); for (int z = 0; z < RealDimensions.Z; z++) { float[] SourceSlice = Source[z + origin.Z]; float[] Slice = new float[RealDimensions.ElementsSlice()]; unsafe { fixed (float* SourceSlicePtr = SourceSlice) fixed (float* SlicePtr = Slice) for (int y = 0; y < RealDimensions.Y; y++) { int YOffset = y + origin.Y; for (int x = 0; x < RealDimensions.X; x++) SlicePtr[y * RealDimensions.X + x] = SourceSlicePtr[YOffset * RealSourceDimensions.X + x + origin.X]; } } Region[z] = Slice; } return new Image(Region, dimensions, IsFT, IsComplex, IsHalf); }