/// <summary> /// Processes a single input file. /// </summary> private void ProcessFile(string inFile, string outFile, WaveFunction.ColorDelegate colorFunc) { unsafe { int sx = -1; int sy = -1; int sz = -1; string inFormat = ""; float latticeSpacing = 0.0f; long inDataStartPos = 0; string nl = Environment.NewLine; float fa = 0.0f, fb = 0.0f; byte *fa0 = (byte *)(&fa); byte *fa1 = fa0 + 1; byte *fa2 = fa0 + 2; byte *fa3 = fa0 + 3; byte *fb0 = (byte *)(&fb); byte *fb1 = fb0 + 1; byte *fb2 = fb0 + 2; byte *fb3 = fb0 + 3; using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open))) { // Parse the header of the input file while (br.BaseStream.Position < br.BaseStream.Length) { string textLine = WaveFunction.ReadTextLine(br); if (textLine.StartsWith("Wavefunction3D")) { string[] comps = textLine.Split(null); inFormat = comps[1]; latticeSpacing = Single.Parse(comps[3]); } else if (textLine.StartsWith("DIMENSIONS")) { string[] comps = textLine.Split(null); sx = Int32.Parse(comps[1]); sy = Int32.Parse(comps[2]); sz = Int32.Parse(comps[3]); } else if (textLine.StartsWith("LOOKUP_TABLE default")) { break; } } // Bail out if the header was not what we expected if (string.IsNullOrEmpty(inFormat) || (sx < 0) || (sy < 0) || (sz < 0)) { throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile."); } if (inFormat != "REAL_AND_IMAG") { throw new ArgumentException("Unsupported Wavefunction format, in Colorer.ProcessFile. " + "(" + inFormat + ")"); } inDataStartPos = br.BaseStream.Position; // Create output file using (FileStream fileStream = File.Create(outFile)) { using (BinaryWriter bw = new BinaryWriter(fileStream)) { // Write the output header string outFormat = (colorFunc == null) ? "AMPLITUDE_ONLY" : "AMPLITUDE_AND_COLOR"; bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl)); bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + outFormat.ToString() + " " + "spacing: " + latticeSpacing.ToString() + nl)); bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl)); bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl)); bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sx + " " + sy + " " + sz + nl)); bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl)); bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl)); bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sx * sy * sz + nl)); bw.Write(Encoding.ASCII.GetBytes("SCALARS amplitude float" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); // Read {re,im} pairs from the input file, and write the corresponding ampl values to the output file // (Avoid reading-in the whole input file up-front, as it may be extremely large.) byte[] outPlane = new byte[sx * sy * 4]; float maxAmpl = 0.0f; for (int z = 0; z < sz; z++) { byte[] inPlane = br.ReadBytes(sx * sy * 8); int ni = 0, no = 0;; for (int y = 0; y < sy; y++) { for (int x = 0; x < sx; x++) { *fa3 = inPlane[ni]; // Reverse the byte order *fa2 = inPlane[ni + 1]; *fa1 = inPlane[ni + 2]; *fa0 = inPlane[ni + 3]; *fb3 = inPlane[ni + 4]; *fb2 = inPlane[ni + 5]; *fb1 = inPlane[ni + 6]; *fb0 = inPlane[ni + 7]; ni += 8; fa = (float)Math.Sqrt(fa * fa + fb * fb); if (fa > maxAmpl) { maxAmpl = fa; } outPlane[no] = *fa3; outPlane[no + 1] = *fa2; outPlane[no + 2] = *fa1; outPlane[no + 3] = *fa0; no += 4; } } bw.Write(outPlane); } // Now write the colors if (colorFunc != null) { bw.Write(Encoding.ASCII.GetBytes("SCALARS colors unsigned_char 3" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); br.BaseStream.Seek(inDataStartPos, SeekOrigin.Begin); byte[] colorPlane = new byte[sx * sy * 3]; for (int z = 0; z < sz; z++) { byte[] inPlane = br.ReadBytes(sx * sy * 8); int ni = 0, no = 0;; for (int y = 0; y < sy; y++) { for (int x = 0; x < sx; x++) { *fa3 = inPlane[ni]; // Real part *fa2 = inPlane[ni + 1]; *fa1 = inPlane[ni + 2]; *fa0 = inPlane[ni + 3]; *fb3 = inPlane[ni + 4]; // Imaginary part *fb2 = inPlane[ni + 5]; *fb1 = inPlane[ni + 6]; *fb0 = inPlane[ni + 7]; ni += 8; Color color = (colorFunc == null) ? Color.Blue : colorFunc(fb, fa, maxAmpl); colorPlane[no] = color.R; colorPlane[no + 1] = color.G; colorPlane[no + 2] = color.B; no += 3; } } bw.Write(colorPlane); } } } } } } }
/// <summary> /// Processes a single input file. /// </summary> private void ProcessFile(string inFile, string outFile) { unsafe { int sx = -1, sy = -1, sz = -1; string format = ""; float latticeSpacing = 0.0f; string nl = Environment.NewLine; float[] kernel = CreateGaussianKernel(m_smoothingFactor); int sk = kernel.Length; int hsk = (sk - 1) / 2; using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open))) { // Parse the header of the input file while (br.BaseStream.Position < br.BaseStream.Length) { string textLine = WaveFunction.ReadTextLine(br); if (textLine.StartsWith("Wavefunction3D")) { string[] comps = textLine.Split(null); format = comps[1]; latticeSpacing = Single.Parse(comps[3]); } else if (textLine.StartsWith("DIMENSIONS")) { string[] comps = textLine.Split(null); sx = Int32.Parse(comps[1]); sy = Int32.Parse(comps[2]); sz = Int32.Parse(comps[3]); } else if (textLine.StartsWith("LOOKUP_TABLE default")) { break; } } // Bail out if the header was not what we expected if (string.IsNullOrEmpty(format) || (sx < 0) || (sy < 0) || (sz < 0)) { throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile."); } if (format != "REAL_AND_IMAG") { throw new ArgumentException("Unsupported Wavefunction format, in Smoother.ProcessFile. " + "(" + format + ")"); } // Allocate some storage float[][][] slab = TdseUtils.Misc.Allocate3DArray(sk, sy, 2 * sx); float[][] outPlane = TdseUtils.Misc.Allocate2DArray(sy, 2 * sx); float[][] workSpace = TdseUtils.Misc.Allocate2DArray(sy, 2 * sx); // Create and open the output file using (FileStream fileStream = File.Create(outFile)) { using (BinaryWriter bw = new BinaryWriter(fileStream)) { // Write the output header bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl)); bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + "REAL_AND_IMAG" + " " + "spacing: " + latticeSpacing.ToString() + nl)); bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl)); bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl)); bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sx + " " + sy + " " + sz + nl)); bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl)); bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl)); bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sx * sy * sz + nl)); bw.Write(Encoding.ASCII.GetBytes("SCALARS wf float 2" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); // Read the initial few planes for (int i = hsk; i < sk; i++) { GetNextXYPlane(br, kernel, workSpace, slab[i]); } for (int i = 0; i < hsk; i++) { TdseUtils.Misc.Copy2DArray(slab[sk - 1 - i], slab[i]); // Mirror boundary conditions on z } // Smooth along z, and write-out the result SmoothAlongZ(slab, kernel, outPlane); WriteXYPlane(bw, outPlane); // Loop over remaining planes for (int z = 1; z < sz; z++) { // Cycle the z-planes, and read-in a new one float[][] temp = slab[0]; for (int i = 0; i < sk - 1; i++) { slab[i] = slab[i + 1]; } slab[sk - 1] = temp; if (z < sz - hsk) { GetNextXYPlane(br, kernel, workSpace, slab[sk - 1]); } else { TdseUtils.Misc.Copy2DArray(slab[2 * (sz - 1 - z)], slab[sk - 1]); // Mirror boundary conditions on z } // Smooth along z, and write-out the result SmoothAlongZ(slab, kernel, outPlane); WriteXYPlane(bw, outPlane); } } } } } }
/// <summary> /// Processes a single input file. /// </summary> private void ProcessFile(string inFile, string outFile) { unsafe { int sx = -1, sy = -1, sz = -1; string format = ""; float latticeSpacing = 0.0f; string nl = Environment.NewLine; using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open))) { // Parse the header of the input file while (br.BaseStream.Position < br.BaseStream.Length) { string textLine = WaveFunction.ReadTextLine(br); if (textLine.StartsWith("Wavefunction3D")) { string[] comps = textLine.Split(null); format = comps[1]; latticeSpacing = (float)(Single.Parse(comps[3]) / m_upsampFactor); } else if (textLine.StartsWith("DIMENSIONS")) { string[] comps = textLine.Split(null); sx = Int32.Parse(comps[1]); sy = Int32.Parse(comps[2]); sz = Int32.Parse(comps[3]); } else if (textLine.StartsWith("LOOKUP_TABLE default")) { break; } } // Bail out if the header was not what we expected if (string.IsNullOrEmpty(format) || (sx < 0) || (sy < 0) || (sz < 0)) { throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile."); } if (format != "REAL_AND_IMAG") { throw new ArgumentException("Unsupported Wavefunction format, in Smoother.ProcessFile. " + "(" + format + ")"); } // Allocate some storage int sxu = (int)Math.Max(1, sx * m_upsampFactor); int syu = (int)Math.Max(1, sy * m_upsampFactor); int szu = (int)Math.Max(1, sz * m_upsampFactor); int sxu2 = 2 * sxu; float[][] workSpace = TdseUtils.Misc.Allocate2DArray(sy, 2 * sx); float[][] outPlane = TdseUtils.Misc.Allocate2DArray(syu, sxu2); // Read the initial few xy planes float[][][] iXYPlanes = new float[sz][][]; for (int zIn = 0; zIn < 4; zIn++) { iXYPlanes[zIn] = TdseUtils.Misc.Allocate2DArray(syu, sxu2); GetNextXYPlane(br, iXYPlanes[zIn], workSpace, m_upsampFactor); } // Precalculate the z-weights and indices int[] zInm2, zInm1, zInp1, zInp2; float[] wzm2, wzm1, wzp1, wzp2; GetUpsampleArrays(sz, m_upsampFactor, out zInm2, out zInm1, out zInp1, out zInp2, out wzm2, out wzm1, out wzp1, out wzp2); // Create and open the output file using (FileStream fileStream = File.Create(outFile)) { using (BinaryWriter bw = new BinaryWriter(fileStream)) { // Write the output header bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl)); bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + "REAL_AND_IMAG" + " " + "spacing: " + latticeSpacing.ToString() + nl)); bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl)); bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl)); bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sxu + " " + syu + " " + szu + nl)); bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl)); bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl)); bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sxu * syu * szu + nl)); bw.Write(Encoding.ASCII.GetBytes("SCALARS wf float 2" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); // Loop over the output z-planes for (int zOut = 0; zOut < szu; zOut++) { // Cache z-weights and offsets float Wzm2 = wzm2[zOut]; float Wzm1 = wzm1[zOut]; float Wzp1 = wzp1[zOut]; float Wzp2 = wzp2[zOut]; float[][] pixValsZInm2 = iXYPlanes[zInm2[zOut]]; float[][] pixValsZInm1 = iXYPlanes[zInm1[zOut]]; float[][] pixValsZInp1 = iXYPlanes[zInp1[zOut]]; float[][] pixValsZInp2 = iXYPlanes[zInp2[zOut]]; if (pixValsZInp2 == null) { // Load (and upsample) the next xy plane float[][] temp = iXYPlanes[zInp2[zOut] - 4]; iXYPlanes[zInp2[zOut] - 4] = null; GetNextXYPlane(br, temp, workSpace, m_upsampFactor); pixValsZInp2 = iXYPlanes[zInp2[zOut]] = temp; } for (int yOut = 0; yOut < syu; yOut++) { float[] pixValsZInm2Y = pixValsZInm2[yOut]; float[] pixValsZInm1Y = pixValsZInm1[yOut]; float[] pixValsZInp1Y = pixValsZInp1[yOut]; float[] pixValsZInp2Y = pixValsZInp2[yOut]; float[] outPlaneY = outPlane[yOut]; for (int xOut = 0; xOut < sxu2; xOut++) { outPlaneY[xOut] = Wzm2 * pixValsZInm2Y[xOut] + Wzm1 * pixValsZInm1Y[xOut] + Wzp1 * pixValsZInp1Y[xOut] + Wzp2 * pixValsZInp2Y[xOut]; } } WriteXYPlane(bw, outPlane); } } } } } }
/// <summary> /// Processes a single input file. /// </summary> private void ProcessFile(string inFile, string outFile) { unsafe { int sxIn = -1, syIn = -1, szIn = -1; int sxOut = -1, syOut = -1, szOut = -1; string format = ""; float latticeSpacing = 0.0f; string nl = Environment.NewLine; using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open))) { // Parse the header of the input file while (br.BaseStream.Position < br.BaseStream.Length) { string textLine = WaveFunction.ReadTextLine(br); if (textLine.StartsWith("Wavefunction3D")) { string[] comps = textLine.Split(null); format = comps[1]; latticeSpacing = Single.Parse(comps[3]); } else if (textLine.StartsWith("DIMENSIONS")) { string[] comps = textLine.Split(null); sxIn = Int32.Parse(comps[1]); syIn = Int32.Parse(comps[2]); szIn = Int32.Parse(comps[3]); } else if (textLine.StartsWith("LOOKUP_TABLE default")) { break; } } // Bail out if the header was not what we expected if (string.IsNullOrEmpty(format) || (sxIn < 0) || (syIn < 0) || (szIn < 0)) { throw new ArgumentException("Invalid Wavefunction file, in Cropper.ProcessFile."); } // Create output file sxOut = sxIn - m_xCrop1 - m_xCrop2; syOut = syIn - m_yCrop1 - m_yCrop2; szOut = szIn - m_zCrop1 - m_zCrop2; using (FileStream fileStream = File.Create(outFile)) { using (BinaryWriter bw = new BinaryWriter(fileStream)) { // Write the output header bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl)); bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + format.ToString() + " " + "spacing: " + latticeSpacing.ToString() + nl)); bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl)); bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl)); bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sxOut + " " + syOut + " " + szOut + nl)); bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl)); bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl)); bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sxOut * syOut * szOut + nl)); // Read values from the input file, and write (some of) them to the output file. // (Avoid reading-in the whole input file up-front, as it may be extremely large.) if (format == "REAL_AND_IMAG") { bw.Write(Encoding.ASCII.GetBytes("SCALARS wf float 2" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); byte[] outPlane = new byte[sxOut * syOut * 8]; for (int z = 0; z < szIn - m_zCrop2; z++) { byte[] inPlane = br.ReadBytes(sxIn * syIn * 8); if (z < m_zCrop1) { continue; } for (int y = m_yCrop1; y < syIn - m_yCrop2; y++) { Buffer.BlockCopy(inPlane, (y * sxIn + m_xCrop1) * 8, outPlane, (y - m_yCrop1) * sxOut * 8, sxOut * 8); } bw.Write(outPlane); } } else if ((format == "AMPLITUDE_ONLY") || (format == "AMPLITUDE_AND_COLOR")) { bw.Write(Encoding.ASCII.GetBytes("SCALARS amplitude float" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); byte[] outPlane = new byte[sxOut * syOut * 4]; for (int z = 0; z < szIn; z++) { byte[] inPlane = br.ReadBytes(sxIn * syIn * 4); if ((z < m_zCrop1) || (z > szIn - m_zCrop2 - 1)) { continue; } for (int y = m_yCrop1; y < syIn - m_yCrop2; y++) { Buffer.BlockCopy(inPlane, (y * sxIn + m_xCrop1) * 4, outPlane, (y - m_yCrop1) * sxOut * 4, sxOut * 4); } bw.Write(outPlane); } if (format == "AMPLITUDE_AND_COLOR") { bw.Write(Encoding.ASCII.GetBytes("SCALARS colors unsigned_char 3" + nl)); bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl)); outPlane = new byte[sxOut * syOut * 3]; for (int z = 0; z < szIn - m_zCrop2; z++) { byte[] inPlane = br.ReadBytes(sxIn * syIn * 3); if (z < m_zCrop1) { continue; } for (int y = m_yCrop1; y < syIn - m_yCrop2; y++) { Buffer.BlockCopy(inPlane, (y * sxIn + m_xCrop1) * 3, outPlane, (y - m_yCrop1) * sxOut * 3, sxOut * 3); } bw.Write(outPlane); } } } else { throw new ArgumentException("Unsupported Wavefunction format, in Cropper.ProcessFile. " + "(" + format + ")"); } } } } } }