Ejemplo n.º 1
0
 private void buttonStop_Click(object sender, EventArgs e)
 {
     Crystal.Bethe.CancelCBED();
     buttonExecute.Text = "Execute";
     pseudoBmp          = null;
     CBED_Image         = null;
     buttonStop.Visible = false;
 }
Ejemplo n.º 2
0
        private void generateImage(bool resetSrc = true, bool resetDest = true)
        {
            if (FormDiffractionSimulator == null || Crystal == null || Crystal.Bethe.Disks == null)
            {
                return;
            }
            setImagePixelSize();
            if (resetSrc)
            {
                SrcImage = getSrcImage();
            }
            if (SrcImage == null)
            {
                return;
            }
            if (resetDest)
            {
                DestImage = getDestImage(SrcImage);
            }
            if (DestImage == null)
            {
                return;
            }
            pseudoBmp          = new PseudoBitmap(DestImage, numericBoxImageSize.ValueInteger);
            pseudoBmp.MaxValue = pseudoBmp.SrcValuesGrayOriginal.Max() * trackBarIntensityBrightnessMax.Value / trackBarIntensityBrightnessMax.Maximum;// * 1.5;
            pseudoBmp.MinValue = pseudoBmp.SrcValuesGrayOriginal.Max() * trackBarIntensityBrightnessMin.Value / trackBarIntensityBrightnessMin.Maximum;
            if (comboBoxScale.SelectedIndex == 0)
            {
                pseudoBmp.SetScaleGray();
            }
            else
            {
                pseudoBmp.SetScaleColdWarm();
            }

            pseudoBmp.IsNegative = comboBoxGradient.SelectedIndex == 1;
            CBED_Image           = pseudoBmp.GetImage();
            FormDiffractionSimulator.Draw();
            Application.DoEvents();
        }
        private void execute(string filename = "")
        {
            var n            = 0;
            var initialRot   = new Matrix3D(FormDiffractionSimulator.formMain.Crystal.RotationMatrix);
            var originalAxes = new Matrix3D(OriginalCrystal.A_Axis * 10, OriginalCrystal.B_Axis * 10, OriginalCrystal.C_Axis * 10);

            //データ数を減らす
            var numMax = 4;
            var ptTemp = graphControl.Profile.Pt;
            var pt     = new List <PointD>();

            for (int i = 0; i < ptTemp.Count; i += numMax)
            {
                var num = Math.Min(numMax, ptTemp.Count - i);
                var p   = new PointD();
                for (int j = i; j < i + num; j++)
                {
                    p += ptTemp[j];
                }
                pt.Add(p / num);
            }

            //var pt = graphControl.Profile.Pt;

            var states = new List <(double depth, double pressure, double thickness)>();

            for (int i = 0; i < pt.Count - 1; i++)
            {
                states.Add(((pt[i].X + pt[i + 1].X) / 2, (pt[i].Y + pt[i + 1].Y) / 2, pt[i + 1].X - pt[i].X));
            }

            int count = checkBoxOmegaStep.Checked ? numericBoxOmegaTimes.ValueInteger : 1;

            toolStripProgressBar.Maximum = states.Count * count;
            toolStripProgressBar.Value   = 0;


            //無回転の時の圧縮面の法線ベクトル
            int cH = numericBoxShockedPlaneH.ValueInteger, cK = numericBoxShockedPlaneK.ValueInteger, cL = numericBoxShockedPlaneL.ValueInteger;
            var compressedPlane = (cH * OriginalCrystal.A_Star + cK * OriginalCrystal.B_Star + cL * OriginalCrystal.C_Star).Normarize();
            //無回転の時の圧縮面の法線ベクトルを(1,0,0)方向に向ける回転ベクトル
            var m1 = Matrix3D.Rot(Vector3DBase.VectorProduct(compressedPlane, new Vector3DBase(1, 0, 0)), Math.Acos(compressedPlane.X));

            //無回転時の圧縮面と平行なベクトル
            (int h, int k, int l, Vector3DBase vec)v1 = (-cK, cH, 0, (-cK * OriginalCrystal.A_Axis + cH * OriginalCrystal.B_Axis).Normarize());
            (int h, int k, int l, Vector3DBase vec)v2 = (0, -cL, cK, (-cL * OriginalCrystal.B_Axis + cK * OriginalCrystal.C_Axis).Normarize());
            if (v1.vec.Length2 < 0.1)
            {
                v1 = (-cL, 0, cH, (-cL * OriginalCrystal.A_Axis + cH * OriginalCrystal.C_Axis).Normarize());
            }
            if (v2.vec.Length2 < 0.1)
            {
                v2 = (-cL, 0, cH, (-cL * OriginalCrystal.A_Axis + cH * OriginalCrystal.C_Axis).Normarize());
            }

            //回転状態の圧縮面の法線ベクトル
            var shockDirection = initialRot * compressedPlane;

            //無回転の時のスリップ面の法線ベクトル
            var slipPlane = (numericBoxSlipPlaneH.Value * OriginalCrystal.A_Star + numericBoxSlipPlaneK.Value * OriginalCrystal.B_Star + numericBoxSlipPlaneL.Value * OriginalCrystal.C_Star).Normarize();
            //回転時のスリップ面と圧縮面の外積ベクトル
            var rotationAxis2019 = Vector3DBase.AngleBetVectors(slipPlane, compressedPlane) < Math.PI / 2 ?
                                   initialRot * Vector3DBase.VectorProduct(slipPlane, compressedPlane) :
                                   initialRot *Vector3DBase.VectorProduct(compressedPlane, slipPlane);

            //(0,0,1)方向をrotationAxis2019に向ける回転ベクトル
            var m2 = Matrix3D.Rot(Vector3DBase.VectorProduct(new Vector3DBase(0, 0, 1), rotationAxis2019), Math.Acos(rotationAxis2019.Z));

            //2018モデル。結晶は圧縮軸に垂直な方向を回転軸として回転すると仮定。その回転軸のリストを設定
            List <Vector3DBase> rotationAxes2018 = new List <Vector3DBase>();
            var div1 = numericBoxDivisionOfRotationAxis.ValueInteger;//回転軸を分割する数
            var initialNormalDirection = Math.Abs(shockDirection.Z) < 0.5 ? new Vector3DBase(shockDirection.Y, -shockDirection.X, 0) : new Vector3DBase(0, -shockDirection.Z, shockDirection.Y);

            for (int rot = 0; rot < div1; rot++)
            {
                rotationAxes2018.Add(Matrix3D.Rot(shockDirection, 2 * Math.PI * rot / div1) * initialNormalDirection);
            }

            var div2 = numericBoxDivisionOfRotationAngle.ValueInteger;//回転量を分割する数

            double front = graphControl.LineList[0].X, back = graphControl.LineList[1].X;
            double omegaC = numericBoxCompressedOmega.RadianValue, sigmaOmegaC = numericBoxCompressedOmegaSigma.RadianValue;
            double omegaR = numericBoxReleasedOmega.RadianValue, sigmaOmegaR = numericBoxReleasedOmegaSigma.RadianValue;
            double thetaC_A = numericBoxCompressedThetaA.RadianValue, thetaC_B = numericBoxCompressedThetaB.RadianValue;
            double thetaR_A = numericBoxReleasedThetaA.RadianValue, thetaR_B = numericBoxReleasedThetaB.RadianValue;
            var    absorption    = 1.0;
            var    compiledImage = new double[FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorWidth * FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorHeight];
            var    spots         = new List <SpotInformation>();
            long   beforeSec     = 0;

            //メインループ開始
            for (int i = 0; i < states.Count; i++)
            {
                FormDiffractionSimulator.SkipDrawing = FormDiffractionSimulator.formMain.SkipDrawing = checkBoxSkipDrawing.Checked;
                var rotationList = new List <(Matrix3D rot, double weight)>();

                if (states[i].depth < front)//Uncompressedの時
                {
                    rotationList.Add((Matrix3D.IdentityMatrix, 1));
                }
                else
                {
                    var time1 = states[i].depth < back ? (states[i].depth - front) / numericBoxUp.Value : (back - front) / numericBoxUp.Value;
                    var time2 = states[i].depth < back ? 0.0 : (states[i].depth - back) / numericBoxUr.Value;
                    var omega = omegaC * time1 + omegaR * time2;
                    var range = 2.0;

                    if (radioButton2018Model.Checked)//2018モデルの時
                    {
                        var sigmaOmega = Math.Sqrt(time1 * sigmaOmegaC * time1 * sigmaOmegaC + time2 * sigmaOmegaR * time2 * sigmaOmegaR);

                        double start = Math.Max(0, omega - range * sigmaOmega), end = omega + range * sigmaOmega, step = (end - start) / div2;
                        var    rotationAngles = new List <PointD>();
                        for (var speed = start; speed <= end + step / 2; speed += step)
                        {
                            rotationAngles.Add(new PointD(speed, Math.Exp(-(speed - omega) * (speed - omega) / 2 / sigmaOmega / sigmaOmega)));
                        }
                        foreach (var axis in rotationAxes2018)
                        {
                            foreach (var angle in rotationAngles)
                            {
                                rotationList.Add((Matrix3D.Rot(axis, angle.X), angle.Y));
                            }
                        }
                    }
                    else//2019モデルの時
                    {
                        double sigmaTheta = states[i].depth < back ? thetaC_A + thetaC_B * time1 : thetaC_A * time1 + thetaR_A + thetaR_B * time2, sigmaTheta2 = sigmaTheta * sigmaTheta;
                        double sigmaOmega = sigmaOmegaC * time1 + sigmaOmegaR * time2, sigmaOmega2 = sigmaOmega * sigmaOmega;

                        double stepTheta = (range * sigmaTheta) / ((int)Math.Sqrt(div1) + 1);
                        double startR = Math.Max(0, omega - range * sigmaOmega), endR = omega + range * sigmaOmega, stepR = (endR - startR) / div2;
                        double stepPhi = (2 * Math.PI) / ((int)Math.Sqrt(div1) + 1);
                        if (stepTheta == 0)
                        {
                            stepTheta = double.PositiveInfinity;
                        }
                        if (stepR == 0)
                        {
                            stepR = double.PositiveInfinity;
                        }

                        for (var theta = stepTheta / 2; theta <= range * sigmaTheta; theta += stepTheta)
                        {
                            for (var phi = 0.0; phi < 2 * Math.PI; phi += stepPhi)
                            {
                                for (var r = startR; r <= endR; r += stepR)
                                {
                                    var v = new Vector3DBase(Math.Sin(theta) * Math.Cos(phi), Math.Sin(theta) * Math.Sin(phi), Math.Cos(theta));
                                    rotationList.Add((Matrix3D.Rot(m2 * v, r), Math.Exp(-(r - omega) * (r - omega) / 2 / sigmaOmega2 - theta * theta / 2 / sigmaTheta2) * r * r * Math.Sin(theta)));
                                }
                            }
                        }
                    }
                }
                var sum = rotationList.Sum(r => r.weight);
                rotationList = rotationList.Select(r => (r.rot, r.weight / sum)).ToList();

                //ここから、圧縮による格子定数の変化
                Matrix3D newAxes = originalAxes;
                if (states[i].depth >= front)
                {
                    var volume = EOS.InverseThirdBirchMurnaghan(numericBoxEOS_K0.Value, numericBoxEOS_Kprime.Value, states[i].pressure * 100);
                    if ((states[i].depth < back && radioButtonCompressedUniaxial.Checked) || (states[i].depth >= back && radioButtonReleasedUniaxial.Checked))
                    {
                        newAxes = m1.Inverse() * new Matrix3D(1 / volume, 0, 0, 0, 1, 0, 0, 0, 1) * m1 * originalAxes;
                    }
                    else
                    {
                        newAxes = new Matrix3D(Math.Pow(1 / volume, 1.0 / 3.0), 0, 0, 0, Math.Pow(1 / volume, 1.0 / 3.0), 0, 0, 0, Math.Pow(1 / volume, 1.0 / 3.0)) * originalAxes;
                    }
                }
                var a = new Vector3DBase(newAxes.E11, newAxes.E21, newAxes.E31);
                var b = new Vector3DBase(newAxes.E12, newAxes.E22, newAxes.E32);
                var c = new Vector3DBase(newAxes.E13, newAxes.E23, newAxes.E33);
                FormDiffractionSimulator.SkipDrawing = FormDiffractionSimulator.formMain.SkipDrawing = true;
                CrystalControl.CellConstants         = (a.Length, b.Length, c.Length, Vector3DBase.AngleBetVectors(b, c), Vector3DBase.AngleBetVectors(c, a), Vector3DBase.AngleBetVectors(a, b));

                var corrRot = newAxes * new Matrix3D(CrystalControl.Crystal.A_Axis * 10, CrystalControl.Crystal.B_Axis * 10, CrystalControl.Crystal.C_Axis * 10).Inverse();

                // ここまで

                //候補となるgの絞り込み
                FormDiffractionSimulator.SetVector(true);
                List <Vector3D> gVector = new List <Vector3D>();
                foreach (var g in FormDiffractionSimulator.formMain.Crystal.VectorOfG.Where(g => g.Flag && g.RelativeIntensity > 1E-6))
                {
                    var vec = initialRot * corrRot * g;
                    vec.Y = -vec.Y; vec.Z = -vec.Z;                           //ここでベクトルのY,Zの符号を反転
                    if (-sinTau * vec.Y + cosTau * (vec.Z + ewaldRadius) > 0) //(vec.X, vec.Y, vec.Z + EwaldRadius) と(0, -sinTau, cosTau) の内積が0より大きい)
                    {
                        //2020/02/03の変更対処済み
                        var point = Geometriy.GetCrossPoint(0, -sinTau, cosTau, cameraLength2, new Vector3D(0, 0, 0), new Vector3D(vec.X, vec.Y, vec.Z + ewaldRadius));
                        if (IsDetectorArea(new PointD(point.X, point.Y * cosTau + point.Z * sinTau)))
                        {
                            gVector.Add(g);
                        }
                    }
                }//ここまで

                //ここから揺動のループ
                var effectiveThickness = states[i].thickness / (shockDirection * new Vector3DBase(0, 0, 1));
                absorption *= Math.Exp(-numericBoxMassAbsorption.Value * FormDiffractionSimulator.formMain.Crystal.Density * effectiveThickness / 10000);
                foreach (var(rot, weight) in rotationList)
                {
                    var temp = GetDiffractionSpots(rot * initialRot * corrRot, gVector, states[i].thickness * absorption * absorption * weight);//入射と出射で二回absorptionをかける
                    spots.AddRange(temp);
                    if (n++ % 100 == 0 && !checkBoxSkipDrawing.Checked)
                    {
                        FormDiffractionSimulator.formMain.SetRotation(rot * initialRot * corrRot);
                    }
                }

                // if (spots.Count > 100 || i == states.Count - 1)
                {
                    var image = getImageData(spots);
                    for (int j = 0; j < compiledImage.Length; j++)
                    {
                        compiledImage[j] += image[j];
                    }
                    spots.Clear();
                }

                toolStripProgressBar.Value++;
                toolStripStatusLabel1.Text =
                    "Time elapsed: " + (sw.ElapsedMilliseconds / 1000.0).ToString("f1") + " sec., per slice: " + (sw.ElapsedMilliseconds - beforeSec).ToString() + " msec., wait for more " +
                    (sw.ElapsedMilliseconds / 1000.0 / toolStripProgressBar.Value * (toolStripProgressBar.Maximum - toolStripProgressBar.Value)).ToString("f1") + " sec.";
                beforeSec = sw.ElapsedMilliseconds;
                Application.DoEvents();
            }//メインループここまで

            compiledImage = compiledImage.Select(intensity => intensity * 1E6).ToArray();
            PseudoBitmap pseud = new PseudoBitmap(compiledImage, FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorWidth);

            Tiff.Writer("temp.tif", compiledImage, 2, FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorWidth);
            FormDiffractionSimulator.FormDiffractionSimulatorGeometry.ReadImage("temp.tif");

            if (filename != "")
            {
                File.Copy("temp.tif", filename, true);
            }

            FormDiffractionSimulator.SkipDrawing = FormDiffractionSimulator.formMain.SkipDrawing = false;
        }