async void UpdateMask()
        {
            if (!IsInitialized)
            {
                return;
            }

            bool  DoNew          = (bool)RadioMaskNew.IsChecked;
            bool  UseHalfmap2    = (bool)RadioHalfmap2File.IsChecked && Halfmap2 != null;
            float Threshold      = (float)MaskThreshold;
            float LowpassNyquist = (float)HalfmapPixelSize * 2 / (float)MaskLowpass;

            ProgressMask.Visibility = Visibility.Visible;

            await Task.Run(() =>
            {
                MaskFinal?.Dispose();
                MaskFinal = null;

                if (!DoNew && Mask != null)
                {
                    MaskFinal = Mask.GetCopyGPU();
                    MaskFinal.Binarize(Threshold);
                }
                else if (DoNew)
                {
                    MaskFinal = Halfmap1.GetCopyGPU();
                    if (UseHalfmap2)
                    {
                        MaskFinal.Add(Halfmap2);
                        MaskFinal.Multiply(0.5f);
                    }

                    MaskFinal.Bandpass(0, LowpassNyquist, true);
                    MaskFinal.Binarize(Threshold);
                }

                Dispatcher.Invoke(() =>
                {
                    RendererMask.Volume = MaskFinal;
                });
            });

            ProgressMask.Visibility = Visibility.Hidden;
            RevalidateTab();
        }
Ejemplo n.º 2
0
        public static (Image[] Halves1, Image[] Halves2, float2[] Stats) TrainOnVolumes(NoiseNet3D network,
                                                                                        Image[] halves1,
                                                                                        Image[] halves2,
                                                                                        Image[] masks,
                                                                                        float angpix,
                                                                                        float lowpass,
                                                                                        float upsample,
                                                                                        bool dontFlatten,
                                                                                        bool performTraining,
                                                                                        int niterations,
                                                                                        float startFrom,
                                                                                        int batchsize,
                                                                                        int gpuprocess,
                                                                                        Action <string> progressCallback)
        {
            if (batchsize != 4)
            {
                niterations = niterations * 4 / batchsize;
                Debug.WriteLine($"Adjusting the number of iterations to {niterations} to match different batch size.\n");
            }

            GPU.SetDevice(gpuprocess);

            #region Mask

            Debug.Write("Preparing mask... ");
            progressCallback?.Invoke("Preparing mask... ");

            int3[] BoundingBox = Helper.ArrayOfFunction(i => new int3(-1), halves1.Length);
            if (masks != null)
            {
                for (int i = 0; i < masks.Length; i++)
                {
                    Image Mask = masks[i];

                    Mask.TransformValues((x, y, z, v) =>
                    {
                        if (v > 0.5f)
                        {
                            BoundingBox[i].X = Math.Max(BoundingBox[i].X, Math.Abs(x - Mask.Dims.X / 2) * 2);
                            BoundingBox[i].Y = Math.Max(BoundingBox[i].Y, Math.Abs(y - Mask.Dims.Y / 2) * 2);
                            BoundingBox[i].Z = Math.Max(BoundingBox[i].Z, Math.Abs(z - Mask.Dims.Z / 2) * 2);
                        }

                        return(v);
                    });

                    if (BoundingBox[i].X < 2)
                    {
                        throw new Exception("Mask does not seem to contain any non-zero values.");
                    }

                    BoundingBox[i] += 64;

                    BoundingBox[i].X = Math.Min(BoundingBox[i].X, Mask.Dims.X);
                    BoundingBox[i].Y = Math.Min(BoundingBox[i].Y, Mask.Dims.Y);
                    BoundingBox[i].Z = Math.Min(BoundingBox[i].Z, Mask.Dims.Z);
                }
            }

            Console.WriteLine("done.\n");

            #endregion

            #region Load and prepare data

            Console.WriteLine("Preparing data:");

            List <Image> Maps1 = new List <Image>();
            List <Image> Maps2 = new List <Image>();

            List <Image>  HalvesForDenoising1 = new List <Image>();
            List <Image>  HalvesForDenoising2 = new List <Image>();
            List <float2> StatsForDenoising   = new List <float2>();

            for (int imap = 0; imap < halves1.Length; imap++)
            {
                Debug.Write($"Preparing map {imap}... ");
                progressCallback?.Invoke($"Preparing map {imap}... ");

                Image Map1 = halves1[imap];
                Image Map2 = halves2[imap];

                float MapPixelSize = Map1.PixelSize / upsample;

                if (!dontFlatten)
                {
                    Image Average = Map1.GetCopy();
                    Average.Add(Map2);

                    if (masks != null)
                    {
                        Average.Multiply(masks[imap]);
                    }

                    float[] Spectrum = Average.AsAmplitudes1D(true, 1, (Average.Dims.X + Average.Dims.Y + Average.Dims.Z) / 6);
                    Average.Dispose();

                    int   i10A   = Math.Min((int)(angpix * 2 / 10 * Spectrum.Length), Spectrum.Length - 1);
                    float Amp10A = Spectrum[i10A];

                    for (int i = 0; i < Spectrum.Length; i++)
                    {
                        Spectrum[i] = i < i10A ? 1 : (Amp10A / Math.Max(1e-10f, Spectrum[i]));
                    }

                    Image Map1Flat = Map1.AsSpectrumMultiplied(true, Spectrum);
                    Map1.FreeDevice();
                    Map1 = Map1Flat;
                    Map1.FreeDevice();

                    Image Map2Flat = Map2.AsSpectrumMultiplied(true, Spectrum);
                    Map2.FreeDevice();
                    Map2 = Map2Flat;
                    Map2.FreeDevice();
                }

                if (lowpass > 0)
                {
                    Map1.Bandpass(0, angpix * 2 / lowpass, true, 0.01f);
                    Map2.Bandpass(0, angpix * 2 / lowpass, true, 0.01f);
                }

                if (upsample != 1f)
                {
                    Image Map1Scaled = Map1.AsScaled(Map1.Dims * upsample / 2 * 2);
                    Map1.FreeDevice();
                    Map1 = Map1Scaled;
                    Map1.FreeDevice();

                    Image Map2Scaled = Map2.AsScaled(Map2.Dims * upsample / 2 * 2);
                    Map2.FreeDevice();
                    Map2 = Map2Scaled;
                    Map2.FreeDevice();
                }

                Image ForDenoising1 = Map1.GetCopy();
                Image ForDenoising2 = Map2.GetCopy();

                if (BoundingBox[imap].X > 0)
                {
                    Image Map1Cropped = Map1.AsPadded(BoundingBox[imap]);
                    Map1.FreeDevice();
                    Map1 = Map1Cropped;
                    Map1.FreeDevice();

                    Image Map2Cropped = Map2.AsPadded(BoundingBox[imap]);
                    Map2.FreeDevice();
                    Map2 = Map2Cropped;
                    Map2.FreeDevice();
                }

                float2 MeanStd = MathHelper.MeanAndStd(Helper.Combine(Map1.GetHostContinuousCopy(), Map2.GetHostContinuousCopy()));

                Map1.TransformValues(v => (v - MeanStd.X) / MeanStd.Y);
                Map2.TransformValues(v => (v - MeanStd.X) / MeanStd.Y);

                ForDenoising1.TransformValues(v => (v - MeanStd.X) / MeanStd.Y);
                ForDenoising2.TransformValues(v => (v - MeanStd.X) / MeanStd.Y);

                HalvesForDenoising1.Add(ForDenoising1);
                HalvesForDenoising2.Add(ForDenoising2);
                StatsForDenoising.Add(MeanStd);

                GPU.PrefilterForCubic(Map1.GetDevice(Intent.ReadWrite), Map1.Dims);
                Map1.FreeDevice();
                Maps1.Add(Map1);

                GPU.PrefilterForCubic(Map2.GetDevice(Intent.ReadWrite), Map2.Dims);
                Map2.FreeDevice();
                Maps2.Add(Map2);

                Debug.WriteLine(" Done.");
            }

            if (masks != null)
            {
                foreach (var mask in masks)
                {
                    mask.FreeDevice();
                }
            }

            #endregion

            int Dim = network.BoxDimensions.X;

            progressCallback?.Invoke($"0/{niterations}");

            if (performTraining)
            {
                GPU.SetDevice(gpuprocess);

                #region Training

                Random Rand = new Random(123);

                int NMaps         = Maps1.Count;
                int NMapsPerBatch = Math.Min(128, NMaps);
                int MapSamples    = batchsize;

                Image[] ExtractedSource = Helper.ArrayOfFunction(i => new Image(new int3(Dim, Dim, Dim * MapSamples)), NMapsPerBatch);
                Image[] ExtractedTarget = Helper.ArrayOfFunction(i => new Image(new int3(Dim, Dim, Dim * MapSamples)), NMapsPerBatch);

                for (int iter = (int)(startFrom * niterations); iter < niterations; iter++)
                {
                    int[] ShuffledMapIDs = Helper.RandomSubset(Helper.ArrayOfSequence(0, NMaps, 1), NMapsPerBatch, Rand.Next(9999));

                    for (int m = 0; m < NMapsPerBatch; m++)
                    {
                        int MapID = ShuffledMapIDs[m];

                        Image Map1 = Maps1[MapID];
                        Image Map2 = Maps2[MapID];

                        int3 DimsMap = Map1.Dims;

                        int3 Margin = new int3((int)(Dim / 2 * 1.5f));
                        //Margin.Z = 0;
                        float3[] Position = Helper.ArrayOfFunction(i => new float3((float)Rand.NextDouble() * (DimsMap.X - Margin.X * 2) + Margin.X,
                                                                                   (float)Rand.NextDouble() * (DimsMap.Y - Margin.Y * 2) + Margin.Y,
                                                                                   (float)Rand.NextDouble() * (DimsMap.Z - Margin.Z * 2) + Margin.Z), MapSamples);

                        float3[] Angle = Helper.ArrayOfFunction(i => new float3((float)Rand.NextDouble() * 360,
                                                                                (float)Rand.NextDouble() * 360,
                                                                                (float)Rand.NextDouble() * 360) * Helper.ToRad, MapSamples);

                        {
                            ulong[] Texture = new ulong[1], TextureArray = new ulong[1];
                            GPU.CreateTexture3D(Map1.GetDevice(Intent.Read), Map1.Dims, Texture, TextureArray, true);
                            //Map1.FreeDevice();

                            GPU.Rotate3DExtractAt(Texture[0],
                                                  Map1.Dims,
                                                  ExtractedSource[m].GetDevice(Intent.Write),
                                                  new int3(Dim),
                                                  Helper.ToInterleaved(Angle),
                                                  Helper.ToInterleaved(Position),
                                                  (uint)MapSamples);

                            //ExtractedSource[MapID].WriteMRC("d_extractedsource.mrc", true);

                            GPU.DestroyTexture(Texture[0], TextureArray[0]);
                        }

                        {
                            ulong[] Texture = new ulong[1], TextureArray = new ulong[1];
                            GPU.CreateTexture3D(Map2.GetDevice(Intent.Read), Map2.Dims, Texture, TextureArray, true);
                            //Map2.FreeDevice();

                            GPU.Rotate3DExtractAt(Texture[0],
                                                  Map2.Dims,
                                                  ExtractedTarget[m].GetDevice(Intent.Write),
                                                  new int3(Dim),
                                                  Helper.ToInterleaved(Angle),
                                                  Helper.ToInterleaved(Position),
                                                  (uint)MapSamples);

                            //ExtractedTarget.WriteMRC("d_extractedtarget.mrc", true);

                            GPU.DestroyTexture(Texture[0], TextureArray[0]);
                        }

                        //Map1.FreeDevice();
                        //Map2.FreeDevice();
                    }

                    float[] PredictedData = null, Loss = null;

                    {
                        float CurrentLearningRate = 0.0001f * (float)Math.Pow(10, -iter / (float)niterations * 2);

                        for (int m = 0; m < ShuffledMapIDs.Length; m++)
                        {
                            int MapID = m;

                            bool Twist = Rand.Next(2) == 0;

                            if (Twist)
                            {
                                network.Train(ExtractedSource[MapID].GetDevice(Intent.Read),
                                              ExtractedTarget[MapID].GetDevice(Intent.Read),
                                              CurrentLearningRate,
                                              0,
                                              out PredictedData,
                                              out Loss);
                            }
                            else
                            {
                                network.Train(ExtractedTarget[MapID].GetDevice(Intent.Read),
                                              ExtractedSource[MapID].GetDevice(Intent.Read),
                                              CurrentLearningRate,
                                              0,
                                              out PredictedData,
                                              out Loss);
                            }
                        }
                    }

                    Debug.WriteLine($"{iter + 1}/{niterations}");
                    progressCallback?.Invoke($"{iter + 1}/{niterations}");
                }

                Debug.WriteLine("\nDone training!\n");

                #endregion
            }

            return(HalvesForDenoising1.ToArray(), HalvesForDenoising2.ToArray(), StatsForDenoising.ToArray());
        }
Ejemplo n.º 3
0
        public void ExportParticles(Star tableIn, Star tableOut, MapHeader originalHeader, Image originalStack, int size, float particleradius, decimal scaleFactor)
        {
            if (!tableIn.HasColumn("rlnAutopickFigureOfMerit"))
                tableIn.AddColumn("rlnAutopickFigureOfMerit");

            List<int> RowIndices = new List<int>();
            string[] ColumnMicrographName = tableIn.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);

            int3 Dims = originalHeader.Dimensions;
            int3 DimsRegion = new int3(size, size, 1);
            int3 DimsPadded = new int3(size * 2, size * 2, 1);
            int NParticles = RowIndices.Count;

            float PixelSize = (float)CTF.PixelSize;
            float PixelDelta = (float)CTF.PixelSizeDelta;
            float PixelAngle = (float)CTF.PixelSizeAngle * Helper.ToRad;
            /*Image CTFCoords;
            Image CTFFreq;
            {
                float2[] CTFCoordsData = new float2[(DimsRegion.X / 2 + 1) * DimsRegion.Y];
                float[] CTFFreqData = new float[(DimsRegion.X / 2 + 1) * DimsRegion.Y];
                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 / DimsRegion.X, angle);
                        CTFFreqData[y * (DimsRegion.X / 2 + 1) + x] = r / CurrentPixelSize;
                    }

                CTFCoords = new Image(CTFCoordsData, DimsRegion.Slice(), true);
                CTFFreq = new Image(CTFFreqData, DimsRegion.Slice(), true);
            }*/

            string[] ColumnPosX = tableIn.GetColumn("rlnCoordinateX");
            string[] ColumnPosY = tableIn.GetColumn("rlnCoordinateY");
            string[] ColumnOriginX = tableIn.GetColumn("rlnOriginX");
            string[] ColumnOriginY = tableIn.GetColumn("rlnOriginY");
            int3[] Origins = new int3[NParticles];
            float3[] ResidualShifts = new float3[NParticles];

            for (int i = 0; i < NParticles; i++)
            {
                float2 Pos = new float2(float.Parse(ColumnPosX[RowIndices[i]], CultureInfo.InvariantCulture),
                                        float.Parse(ColumnPosY[RowIndices[i]], CultureInfo.InvariantCulture)) * 1.00f;
                float2 Shift = new float2(float.Parse(ColumnOriginX[RowIndices[i]], CultureInfo.InvariantCulture),
                                          float.Parse(ColumnOriginY[RowIndices[i]], CultureInfo.InvariantCulture)) * 1.00f;

                Origins[i] = new int3((int)(Pos.X - Shift.X),
                                      (int)(Pos.Y - Shift.Y),
                                      0);
                ResidualShifts[i] = new float3(-MathHelper.ResidualFraction(Pos.X - Shift.X),
                                               -MathHelper.ResidualFraction(Pos.Y - Shift.Y),
                                               0f);

                tableIn.SetRowValue(RowIndices[i], "rlnCoordinateX", Origins[i].X.ToString());
                tableIn.SetRowValue(RowIndices[i], "rlnCoordinateY", Origins[i].Y.ToString());
                tableIn.SetRowValue(RowIndices[i], "rlnOriginX", "0.0");
                tableIn.SetRowValue(RowIndices[i], "rlnOriginY", "0.0");
            }

            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(DimsPadded.X, DimsPadded.Y, NParticles));

            float StepZ = 1f / Math.Max(Dims.Z - 1, 1);
            for (int z = 0; z < Dims.Z; z++)
            {
                float CoordZ = z * StepZ;

                if (originalStack != null)
                    GPU.Extract(originalStack.GetDeviceSlice(z, Intent.Read),
                                FrameParticles.GetDevice(Intent.Write),
                                Dims.Slice(),
                                DimsPadded,
                                Helper.ToInterleaved(Origins.Select(v => new int3(v.X - DimsPadded.X / 2, v.Y - DimsPadded.Y / 2, 0)).ToArray()),
                                (uint)NParticles);

                // Shift particles
                {
                    float3[] Shifts = new float3[NParticles];

                    for (int i = 0; i < NParticles; i++)
                    {
                        float3 Coords = new float3((float)Origins[i].X / Dims.X, (float)Origins[i].Y / Dims.Y, CoordZ);
                        Shifts[i] = ResidualShifts[i] + new float3(GetShiftFromPyramid(Coords)) * 1.00f;
                    }
                    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.

                #region Motion blur weighting

                /*{
                    const int Samples = 11;
                    float StartZ = (z - 0.5f) * StepZ;
                    float StopZ = (z + 0.5f) * StepZ;

                    float2[] Shifts = new float2[Samples * NParticles];
                    for (int p = 0; p < NParticles; p++)
                    {
                        float NormX = (float)Origins[p].X / Dims.X;
                        float NormY = (float)Origins[p].Y / Dims.Y;

                        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] = GetShiftFromPyramid(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();
                }*/

                #endregion

                // Apply CTF.

                #region CTF weighting

                /*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(Origins[p].X / Dims.X,
                                                                                      Origins[p].Y / 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();
                }*/

                #endregion

                // Apply dose.

                #region 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();
                }*/
                #endregion

                //Image PSAbs = new Image(PS.GetDevice(Intent.Read), new int3(DimsRegion.X, DimsRegion.Y, NParticles), true);
                //PSAbs.Abs();

                //FrameParticlesFT.Multiply(PS);
                AverageFT.Add(FrameParticlesFT);

                //Weights.Add(PSAbs);

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

                //PS.Dispose();
                FrameParticlesFT.Dispose();
                //PSAbs.Dispose();
            }
            FrameParticles.Dispose();
            //CTFCoords.Dispose();

            //AverageFT.Divide(Weights);
            //AveragePS.Divide(Weights);
            //AverageFT.Multiply(AveragePS);
            Weights.Dispose();

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

            Image AverageParticles = AverageParticlesUncorrected.AsAnisotropyCorrected(new int2(DimsRegion),
                                                                                       (float)(CTF.PixelSize + CTF.PixelSizeDelta / 2M),
                                                                                       (float)(CTF.PixelSize - CTF.PixelSizeDelta / 2M),
                                                                                       (float)CTF.PixelSizeAngle * Helper.ToRad,
                                                                                       8);
            AverageParticlesUncorrected.Dispose();

            GPU.NormParticles(AverageParticles.GetDevice(Intent.Read),
                              AverageParticles.GetDevice(Intent.Write),
                              DimsRegion,
                              (uint)(particleradius / (PixelSize / 1.00f)),
                              true,
                              (uint)NParticles);

            HeaderMRC ParticlesHeader = new HeaderMRC
            {
                Pixelsize = new float3(PixelSize, PixelSize, PixelSize)
            };

            AverageParticles.WriteMRC(ParticlesPath, ParticlesHeader);
            AverageParticles.Dispose();

            //AveragePS.WriteMRC(ParticleCTFPath, ParticlesHeader);
            AveragePS.Dispose();

            float[] DistanceWeights = new float[NParticles];
            for (int p1 = 0; p1 < NParticles - 1; p1++)
            {
                float2 Pos1 = new float2(Origins[p1].X, Origins[p1].Y);

                for (int p2 = p1 + 1; p2 < NParticles; p2++)
                {
                    float2 Pos2 = new float2(Origins[p2].X, Origins[p2].Y);
                    float2 Diff = Pos2 - Pos1;
                    float Dist = Diff.X * Diff.X + Diff.Y * Diff.Y;
                    Dist = 1f / Dist;

                    DistanceWeights[p1] += Dist;
                    DistanceWeights[p2] += Dist;
                }
            }

            for (int i = 0; i < NParticles; i++)
            {
                string ParticlePath = (i + 1).ToString("D6") + "@particles/" + RootName + "_particles.mrcs";
                tableIn.SetRowValue(RowIndices[i], "rlnImageName", ParticlePath);

                //string ParticleCTFsPath = (i + 1).ToString("D6") + "@particlectf/" + RootName + "_particlectf.mrcs";
                //tableIn.SetRowValue(RowIndices[i], "rlnCtfImage", ParticleCTFsPath);

                tableIn.SetRowValue(RowIndices[i], "rlnAutopickFigureOfMerit", DistanceWeights[i].ToString(CultureInfo.InvariantCulture));
            }
        }
Ejemplo n.º 4
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());
        }
Ejemplo n.º 5
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);
        }