Пример #1
0
        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());
        }
Пример #2
0
        public void CreateCorrected(MapHeader originalHeader, Image originalStack)
        {
            if (!Directory.Exists(AverageDir))
                Directory.CreateDirectory(AverageDir);
            if (!Directory.Exists(CTFDir))
                Directory.CreateDirectory(CTFDir);

            if (MainWindow.Options.PostStack && !Directory.Exists(ShiftedStackDir))
                Directory.CreateDirectory(ShiftedStackDir);

            int3 Dims = originalStack.Dims;

            Image ShiftedStack = null;
            if (MainWindow.Options.PostStack)
                ShiftedStack = new Image(Dims);

            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[Dims.ElementsSlice()];
                Helper.ForEachElementFT(new int2(Dims), (x, y, xx, yy) =>
                {
                    float xs = xx / (float)Dims.X;
                    float ys = yy / (float)Dims.Y;
                    float r = (float)Math.Sqrt(xs * xs + ys * ys);
                    float angle = (float)(Math.Atan2(yy, xx) + Math.PI / 2.0);
                    float CurrentPixelSize = PixelSize + PixelDelta * (float)Math.Cos(2f * (angle - PixelAngle));

                    CTFCoordsData[y * (Dims.X / 2 + 1) + x] = new float2(r / CurrentPixelSize, angle);
                });

                CTFCoords = new Image(CTFCoordsData, Dims.Slice(), true);
                CTFCoords.RemapToFT();
            }
            Image CTFFreq = CTFCoords.AsReal();

            CubicGrid CollapsedMovementX = GridMovementX.CollapseXY();
            CubicGrid CollapsedMovementY = GridMovementY.CollapseXY();
            CubicGrid CollapsedCTF = GridCTF.CollapseXY();
            Image AverageFT = new Image(Dims.Slice(), true, true);
            Image AveragePS = new Image(Dims.Slice(), true, false);
            Image Weights = new Image(Dims.Slice(), true, false);
            Weights.Fill(1e-6f);

            float StepZ = 1f / Math.Max(Dims.Z - 1, 1);

            for (int nframe = 0; nframe < Dims.Z; nframe++)
            {

                Image PS = new Image(Dims.Slice(), true);
                PS.Fill(1f);

                // Apply motion blur filter.
                /*{
                    float StartZ = (nframe - 0.5f) * StepZ;
                    float StopZ = (nframe + 0.5f) * StepZ;

                    float2[] Shifts = new float2[21];
                    for (int z = 0; z < Shifts.Length; z++)
                    {
                        float zp = StartZ + (StopZ - StartZ) / (Shifts.Length - 1) * z;
                        Shifts[z] = new float2(CollapsedMovementX.GetInterpolated(new float3(0.5f, 0.5f, zp)),
                                               CollapsedMovementY.GetInterpolated(new float3(0.5f, 0.5f, zp)));
                    }
                    // Center the shifts around 0
                    float2 ShiftMean = MathHelper.Mean(Shifts);
                    Shifts = Shifts.Select(v => v - ShiftMean).ToArray();

                    Image MotionFilter = new Image(IntPtr.Zero, Dims.Slice(), true);
                    GPU.CreateMotionBlur(MotionFilter.GetDevice(Intent.Write), 
                                         MotionFilter.Dims, 
                                         Helper.ToInterleaved(Shifts.Select(v => new float3(v.X, v.Y, 0)).ToArray()), 
                                         (uint)Shifts.Length, 
                                         1);
                    PS.Multiply(MotionFilter);
                    //MotionFilter.WriteMRC("motion.mrc");
                    MotionFilter.Dispose();
                }*/

                // Apply CTF.
                /*if (CTF != null)
                {
                    CTF Altered = CTF.GetCopy();
                    Altered.Defocus = (decimal)CollapsedCTF.GetInterpolated(new float3(0.5f, 0.5f, nframe * StepZ));

                    Image CTFImage = new Image(IntPtr.Zero, Dims.Slice(), true);
                    GPU.CreateCTF(CTFImage.GetDevice(Intent.Write),
                                  CTFCoords.GetDevice(Intent.Read),
                                  (uint)CTFCoords.ElementsSliceComplex, 
                                  new[] { Altered.ToStruct() }, 
                                  false, 
                                  1);

                    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 * (nframe + 0.5f) / (PixelSize * PixelSize);

                    Image DoseImage = new Image(IntPtr.Zero, Dims.Slice(), true);
                    GPU.DoseWeighting(CTFFreq.GetDevice(Intent.Read),
                                      DoseImage.GetDevice(Intent.Write),
                                      (uint)DoseImage.ElementsSliceComplex,
                                      new[] { FrameDose },
                                      NikoConst,
                                      1);
                    PS.Multiply(DoseImage);
                    //DoseImage.WriteMRC("dose.mrc");
                    DoseImage.Dispose();
                }*/

                Image Frame = new Image(originalStack.GetHost(Intent.Read)[nframe], Dims.Slice());
                Frame.ShiftSlicesMassive(new[]
                {
                    new float3(CollapsedMovementX.GetInterpolated(new float3(0.5f, 0.5f, nframe * StepZ)),
                               CollapsedMovementY.GetInterpolated(new float3(0.5f, 0.5f, nframe * StepZ)),
                               0f)
                });
                if (MainWindow.Options.PostStack)
                    ShiftedStack.GetHost(Intent.Write)[nframe] = Frame.GetHost(Intent.Read)[0];

                Image FrameFT = Frame.AsFFT();
                Frame.Dispose();

                //Image PSSign = new Image(PS.GetDevice(Intent.Read), Dims.Slice(), true);
                //Image PSSign = new Image(Dims.Slice(), true);
                //PSSign.Fill(1f);
                //PSSign.Sign();

                // Do phase flipping before averaging.
                //FrameFT.Multiply(PSSign);
                //PS.Multiply(PSSign);
                //PSSign.Dispose();

                //FrameFT.Multiply(PS);
                AverageFT.Add(FrameFT);
                Weights.Add(PS);

                //PS.WriteMRC("ps.mrc");

                PS.Multiply(PS);
                AveragePS.Add(PS);

                PS.Dispose();
                FrameFT.Dispose();

            }
            CTFCoords.Dispose();
            CTFFreq.Dispose();

            //AverageFT.Divide(Weights);
            //AverageFT.WriteMRC("averageft.mrc");
            //Weights.WriteMRC("weights.mrc");
            AveragePS.Divide(Weights);
            Weights.Dispose();

            Image Average = AverageFT.AsIFFT();
            AverageFT.Dispose();

            MapHeader Header = originalHeader;
            Header.Dimensions = Dims.Slice();

            Average.WriteMRC(AveragePath);
            Average.Dispose();

            AveragePS.WriteMRC(CTFPath);
            AveragePS.Dispose();

            TempAverageImage = null;
            OnPropertyChanged("AverageImage");

            using (TextWriter Writer = File.CreateText(AverageDir + RootName + "_ctffind3.log"))
            {
                decimal Mag = (MainWindow.Options.CTFDetectorPixel * 10000M / CTF.PixelSize);

                Writer.WriteLine("CS[mm], HT[kV], AmpCnst, XMAG, DStep[um]");
                Writer.WriteLine($"{CTF.Cs} {CTF.Voltage} {CTF.Amplitude} {Mag} {MainWindow.Options.CTFDetectorPixel}");

                float BestQ = 0;
                float2[] Q = CTFQuality;
                if (Q != null)
                    foreach (var q in Q)
                    {
                        if (q.Y < 0.3f)
                            break;
                        BestQ = q.X * 2f;
                    }

                Writer.WriteLine($"{(CTF.Defocus + CTF.DefocusDelta / 2M) * 1e4M} {(CTF.Defocus - CTF.DefocusDelta / 2M) * 1e4M} {CTF.DefocusAngle} {BestQ} {CTF.PhaseShift * 180M} Final Values");
            }

            if (MainWindow.Options.PostStack)
                ShiftedStack.WriteMRC(ShiftedStackPath);
        }