public static void GetRingAndDetectorForXY(int aPosition, UInt16 XPlus, UInt16 XMinus, UInt16 YPlus, UInt16 YMinus,
                                                   out int Ring, out int Detector)
        {
            var blockNumber = (aPosition >> 4) & 0xFF;
            var ringGroup   = aPosition & 0xF;

            var i = blockNumber * 15 + EventConverter.iForX(XPlus, XMinus);
            var j = ringGroup * 15 + EventConverter.jForY(YPlus, YMinus);

            Detector = i;
            Ring     = j;
        }
        public bool Detect(Photon ph, out PETSingleEvent se)
        {
            se = new PETSingleEvent();

            if (ph.Status != stat.Finished)
            {
                return(false);
            }

            //to cylindrical
            double azimuthalAngle = Math.Atan2(ph.CurrentPosition.Y, ph.CurrentPosition.X);

            if (azimuthalAngle < 0)
            {
                azimuthalAngle += 2 * Math.PI;
            }
            //double rc = Math.Sqrt(ph.CurrentPosition.X * ph.CurrentPosition.X + ph.CurrentPosition.Y * ph.CurrentPosition.Y + ph.CurrentPosition.Z * ph.CurrentPosition.Z) * Math.Sin(ph.Theta);
            double rc = Math.Sqrt(ph.CurrentPosition.X * ph.CurrentPosition.X + ph.CurrentPosition.Y * ph.CurrentPosition.Y);
            double z0 = ph.CurrentPosition.Z;

            var tmpAngle = Math.Asin(rc / this.RingRadius * Math.Sin(azimuthalAngle - ph.Phi));
            //var tmpAngle = this.Phi - azimuthalAngle - Math.Asin(rc / ringRadius * Math.Sin(azimuthalAngle - this.Phi));

            var psi = tmpAngle + ph.Phi; //угол регистрации

            if (psi < 0)
            {
                psi += 2 * Math.PI;
            }
            if (psi >= 2 * Math.PI)
            {
                psi -= 2 * Math.PI;
            }

            var block = (int)(psi / (2 * Math.PI) * this.BlocksCount); // номер блока детекторов

            var r1 = Math.Sqrt(this.RingRadius * this.RingRadius + rc * rc - 2 * this.RingRadius * rc * Math.Cos(azimuthalAngle - psi));
            var dz = (r1 / Math.Tan(ph.Theta)) / this.BlockSize;

            z0 /= this.BlockSize;

            var blockRing = (int)Math.Floor(z0 + dz + this.RingsCount / 2.0); // номер кольца блоков

            //double s = Math.Sqrt((this.CurrentPosition.X - ringRadius * Math.Cos(psi)) * (this.CurrentPosition.X - ringRadius * Math.Cos(psi)) +
            //    (this.CurrentPosition.Y - ringRadius * Math.Sin(psi)) * (this.CurrentPosition.Y - ringRadius * Math.Sin(psi)) +
            //        (this.CurrentPosition.Z - dz * blockSide) * (this.CurrentPosition.Z - dz * blockSide)) + this.Path;
            //this.Time += s / (3e11);

            if (blockRing >= 0 && blockRing < this.RingsCount)
            {
                se.Position  = (UInt16)(((block & 0x3F) << 4) | (blockRing & 0xF));
                se.Timestamp = (UInt32)(ph.Time);

                var I = (byte)((psi - block * 2 * Math.PI / this.BlocksCount) / (2 * Math.PI / (this.BlocksCount * this.DetectorsPerBlock)));
                var J = (byte)((z0 + dz + this.RingsCount / 2.0) * this.DetectorsPerBlock) % this.DetectorsPerBlock;

                EventConverter.GetXYFromIJ(I, (byte)J, ph.Energy, out se.XPlus, out se.XMinus, out se.YPlus, out se.YMinus);
                return(true);
            }
            return(false);
        }
        public void Build(string path)
        {
            var sins = new double[numSins][, ];

            for (int i = 0; i < numSins; i++)
            {
                sins[i] = new double[indexer.NumDirs, indexer.NumLines];
            }

            Bitmap   bmp = new Bitmap(1024, 1024);
            Graphics gr  = Graphics.FromImage(bmp);

            gr.TranslateTransform(bmp.Width / 2f, bmp.Height / 2f);

            List <string> fileList = new List <string>();

            if (Directory.Exists(path))
            {
                DirectoryInfo    di    = new DirectoryInfo(path);
                FileSystemInfo[] files = di.GetFileSystemInfos();
                foreach (var file in files)
                {
                    fileList.Add(file.FullName);
                }
            }

            foreach (var file in fileList)
            {
                var clist = WorkWithFiles.ReadCoincList(file);
                foreach (var c in clist)
                {
                    PETDigitalCoincidenceTOF cIJ = new PETDigitalCoincidenceTOF();
                    EventConverter.CalculateDigitalCoincidenceTOF(c, ref cIJ);

                    int Ring1 = indexer.GetRing(c.Position1, cIJ.J1);
                    int Ring2 = indexer.GetRing(c.Position2, cIJ.J2);

                    var sinidx = Ring1 + Ring2;

                    if (sinidx >= numSins)
                    {
                        continue;
                    }

                    int Dir  = indexer.GetDir(c.Position1, c.Position2, cIJ.I1, cIJ.I2);
                    int Line = indexer.GetLine(c.Position1, c.Position2, cIJ.I1, cIJ.I2);

                    //if (isDebug && ++cnt % 1000 == 0)
                    //{
                    // gr.DrawLine(Pens.White, 410 * (float)Math.Cos(Math.PI * Detector1 / 360), 410 * (float)Math.Sin(Math.PI * Detector1 / 360),
                    // 410 * (float)Math.Cos(Math.PI * Detector2 / 360), 410 * (float)Math.Sin(Math.PI * Detector2 / 360));
                    //}
                    if (Line < 0)
                    {
                        continue;
                    }
                    sins[sinidx][Dir, Line]++;
                }
            }

            if (!Directory.Exists(outDir))
            {
                Directory.CreateDirectory(outDir);
            }

            for (int i = 0; i < numSins; i++)
            {
                Sinogram sino    = new Sinogram(sins[i], AnglesDistribution.Uniform(0, Math.PI, indexer.NumDirs));
                Stream   ostream = File.Create(string.Format("{0}\\{1}", outDir, string.Format("{0}.sg", i)));
                //using (StreamWriter w = new StreamWriter(ostream, Encoding.UTF8))
                using (ostream)
                {
                    Sinogram.SaveSinogramToStream(ostream, sino);
                }

                Sinogram.DumpSinogram(sins[i], string.Format("{0}\\{1}.png", outDir, i));
                //if (isDebug)
                // bmp.Save(string.Format("{0}\\lines.png", arg.OutDir));
            }
        }