/// <summary>Add some data to the heap.</summary> internal virtual int PutData(Object data) { int size = ArrayFuncs.ComputeSize(data); ExpandHeap(size); MemoryStream bo = new MemoryStream(size); try { BufferedDataStream o = new BufferedDataStream(bo); o.WriteArray(data); o.Flush(); o.Close(); } catch (IOException) { throw new FitsException("Unable to write variable column length data"); } Array.Copy(bo.ToArray(), 0, heap, heapSize, size); int oldOffset = heapSize; heapSize += size; // change suggested in .99.1 version: heapOffset = heapSize; return(oldOffset); }
protected static int[] ComputeByteWidths(Array[] a) { int[] result = new int[a.Length]; for (int i = 0; i < a.Length; ++i) { result[i] = ArrayFuncs.ComputeSize(a[i]); } return(result); }
protected void SetupRenderers() { Array[] modelRow = ReplaceTroolean(_rs.ModelRow); Array[] modelRow2 = null; switch (_writeMode) { case StringWriteMode.HEAP: case StringWriteMode.PAD: modelRow2 = CopyModelRowReplaceStrings(modelRow, new int[2]); modelRow2 = CopyModelRowStripUnknowns(modelRow2, new byte[1]); // _rowSizeInBytes = ArrayFuncs.ComputeSize(CopyModelRowReplaceStrings(modelRow, new int[2])); _rowSizeInBytes = ArrayFuncs.ComputeSize(modelRow2); modelRow2 = CopyModelRowStripUnknowns(modelRow, new byte[1]); //myHeader = ManufactureHeader(modelRow, _rs.ColumnNames, _rs.TNULL, _rs.NRows); myHeader = ManufactureHeader(modelRow2, _rs.ColumnNames, _rs.TNULL, _rs.NRows); _stringArrayRenderer = ByteRenderer.STRING_ARRAY_RENDERER_HEAP; break; case StringWriteMode.TRUNCATE: modelRow2 = CopyModelRowReplaceStrings(modelRow, new String[] { new String(' ', _stringTruncationLength) }); modelRow2 = CopyModelRowStripUnknowns(modelRow2, new byte[1]); _rowSizeInBytes = ArrayFuncs.ComputeSize(modelRow2); myHeader = ManufactureHeader(modelRow2, _rs.ColumnNames, _rs.TNULL, _rs.NRows); _stringArrayRenderer = new ByteRenderer.StringArrayByteRendererTruncate(_stringTruncationLength, _padChar, _padLeft, false); break; } _hasStrings = false; for (int i = 0; i < _rs.ModelRow.Length; ++i) { _byteRenderers[i] = ByteRenderer.GetByteRenderer(_rs.ModelRow[i].GetType()); if (_rs.ModelRow[i] is String[]) { _byteRenderers[i] = _stringArrayRenderer; _hasStrings = true; } if (_byteRenderers[i].GetType() == typeof(ByteRenderer.NullByteRenderer)) { myHeader.AddComment("COLUMN " + (i + 1) + " NULL DUE TO UNKNOWN TYPE."); } } }
protected static int[] GetStringIndices(Array[] a) { int[] result = new int[a.Length]; for (int i = 0, offset = 0; i < a.Length; ++i) { result[i] = -1; if (a[i] is String[]) { result[i] = offset; offset += 8; // two ints, position & length } else if (a[i] is Troolean[]) { offset += 1; // one char, 'T', 'F', or null } else { offset += ArrayFuncs.ComputeSize(a[i]); } } return(result); }
/// <summary>Create an ImageData object using the specified object to /// initialize the data array. /// </summary> /// <param name="x">The initial data array. This should be a primitive /// array but this is not checked currently. /// </param> public ImageData(Object x) { dataArray = x; byteSize = ArrayFuncs.ComputeSize(x); }
/// <summary> /// Writes this binary table with data first going /// to a temp file (and heap file if necessary), /// then with header going to destination stream, /// then merging heap with table data if necessary /// and copying these to destination stream. /// </summary> /// <param name="s">The destination stream.</param> /// steps: /// 1) write the table to a tempfile /// byterenderers write data to the heap if necessary /// byterenderers return heap positions and lengths if necessary /// these are returned as a byte sequence like any other data /// and are written to the table like any other data /// 2) fix the header /// write the header to the main stream /// 3) write the table tempfile to the main stream, merging heap if necessary /// what a pain protected void WritePadOutput(ArrayDataIO s) { String tempFilename = CreateTempFilename() + "temp.tmp"; String heapFilename = CreateTempFilename() + "heap.tmp"; Stream tempS = new ActualBufferedStream(new FileStream(tempFilename, FileMode.Create)); Stream heapS = null; //Stream tempS = new BufferedStream(new FileStream(tempFilename, FileMode.Create), 4096); int[] maxColWidths = null; int[] stringIndices = GetStringIndices(_rs.ModelRow); int[] byteWidths = ComputeByteWidths(CopyModelRowStripUnknowns(ReplaceTroolean(_rs.ModelRow), new byte[1])); int nRows = 0; int maxColWidth = 0; if (_hasStrings) { maxColWidths = new int[_byteRenderers.Length]; heapS = new HeapStream(new FileStream(heapFilename, FileMode.Create)); //heapS = new BufferedStream(new FileStream(heapFilename, FileMode.Create)); for (int col = 0; col < _byteRenderers.Length; ++col) { _byteRenderers[col].Heap = heapS; maxColWidths[col] = -1; } } #region 1) write the table for (Array[] els = _rs.GetNextRow(ref _row); els != null;) { ++nRows; for (int col = 0; col < _byteRenderers.Length; ++col) { _byteRenderers[col].Write(els[col], tempS); if (els[col] is String[] && maxColWidths[col] < ((String[])els[col])[0].Length) { maxColWidths[col] = ((String[])els[col])[0].Length; if (maxColWidth < maxColWidths[col]) { maxColWidth = maxColWidths[col]; } } } els = _rs.GetNextRow(ref _row); } tempS.Flush(); heapS.Flush(); #endregion #region 2) fix the header and write it to the main stream if (_hasStrings) { // fix NAXIS1, NAXIS2 Array[] modelRow2 = CopyModelRowReplaceStrings(ReplaceTroolean(_rs.ModelRow), null); //modelRow2 = CopyModelRowStripUnknowns(modelRow2, new byte[1]); for (int i = 0; i < modelRow2.Length; ++i) { if (modelRow2[i] == null) { modelRow2[i] = new String[] { new String(' ', maxColWidths[i]) }; myHeader.RemoveCard("TFORM" + (i + 1)); myHeader.InsertValue("TFORM" + (i + 1), maxColWidths[i] + "A", null, "TDIM" + (i + 1)); } } modelRow2 = CopyModelRowStripUnknowns(modelRow2, new byte[1]); myHeader.RemoveCard("NAXIS1"); myHeader.InsertValue("NAXIS1", ArrayFuncs.ComputeSize(modelRow2), "row width in bytes", "NAXIS2"); myHeader.RemoveCard("NAXIS2"); myHeader.InsertValue("NAXIS2", nRows, "number of rows", "PCOUNT"); myHeader.RemoveCard("THEAP"); } myHeader.Write(s); #endregion #region 3) write the table tempfile to the main stream tempS.Seek(0, SeekOrigin.Begin); heapS.Seek(0, SeekOrigin.Begin); // man, if you can't even fit a row into memory, I give up byte[] row = new byte[_rowSizeInBytes]; // this is the old size byte[] padBuf = SupportClass.ToByteArray(new String(_padChar, maxColWidth)); int len = 0; int off = 0; for (int nRead = tempS.Read(row, 0, row.Length), rowOffset = 0; nRead > 0; rowOffset = 0) { for (int i = 0; i < byteWidths.Length; ++i) { if (stringIndices[i] != -1) { Array.Reverse(row, stringIndices[i], 4); // fix the length bytes Array.Reverse(row, stringIndices[i] + 4, 4); // fix the pos bytes len = BitConverter.ToInt32(row, stringIndices[i]); off = BitConverter.ToInt32(row, stringIndices[i] + 4); if (_padLeft) { s.Write(padBuf, 0, maxColWidths[i] - len); heapS.Seek(off, SeekOrigin.Begin); int bufread = heapS.Read(_buf, 0, len); s.Write(_buf, 0, len); } else { heapS.Seek(off, SeekOrigin.Begin); heapS.Read(_buf, 0, len); s.Write(_buf, 0, len); s.Write(padBuf, 0, maxColWidths[i] - len); } rowOffset += 8; // advance 2 ints into the row } else { // s better be buffered, or this is going to be slow. But since s is ArrayDataIO, // and the only current concrete ArrayDataIO implementations are buffered, // I think we're good. // **** MAKE SURE BUFFEREDSTREAM USED BY BUFFEREDDATASTREAM IS GOOD ***** s.Write(row, rowOffset, byteWidths[i]); rowOffset += byteWidths[i]; } } nRead = tempS.Read(row, 0, row.Length); } tempS.Close(); heapS.Close(); File.Delete(tempFilename); File.Delete(heapFilename); // pad the table int tableWidth = 0; for (int i = 0; i < byteWidths.Length; ++i) { if (stringIndices[i] != -1) { tableWidth += maxColWidths[i]; } else { tableWidth += byteWidths[i]; } } int pad = FitsUtil.Padding((long)nRows * (long)tableWidth); s.Write(new byte[pad], 0, pad); #endregion }
public void TestRandomGroup() { //float[,] fa = new float[20,20]; float[][] fa = new float[20][]; for (int i = 0; i < fa.Length; i++) { fa[i] = new float[20]; } float[] pa = new float[3]; BufferedFile bf = new BufferedFile( TestFileSetup.GetTargetFilename("rg1.fits"), FileAccess.ReadWrite, FileShare.ReadWrite); Object[][] data = new Object[1][]; data[0] = new Object[2]; data[0][0] = pa; data[0][1] = fa; Console.Out.WriteLine("***** Write header ******"); BasicHDU hdu = Fits.MakeHDU(data); Header hdr = hdu.Header; // Change the number of groups hdr.AddValue("GCOUNT", 20, "Number of groups"); hdr.Write(bf); Console.Out.WriteLine("***** Write data group by group ******"); for (int i = 0; i < 20; i += 1) { for (int j = 0; j < pa.Length; j += 1) { pa[j] = i + j; } for (int j = 0; j < fa.GetLength(0); j += 1) { try { // fa[j, j] = i * j; fa[j][j] = i * j; } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("i ,j value:" + i + " " + j); } } // Write a group bf.WriteArray(data); } byte[] padding = new byte[FitsUtil.Padding(20 * ArrayFuncs.ComputeSize(data))]; Console.Out.WriteLine("****** Write padding ******"); bf.Write(padding); bf.Flush(); bf.Close(); bf.Dispose(); Fits f = null; try { Console.Out.WriteLine("****** Read data back in ******"); f = new Fits(TestFileSetup.GetTargetFilename("rg1.fits")); BasicHDU[] hdus = f.Read(); data = (Object[][])hdus[0].Kernel; // data = hdus[0].Kernel; Console.Out.WriteLine("**** Check parameter and data info *****"); for (int i = 0; i < data.Length; i += 1) { pa = (float[])data[i][0]; // fa = (float[,]) data[i,1]; Array[] tfa = (Array[])data[i][1]; for (int j = 0; j < pa.Length; j += 1) { Assert.AreEqual((float)(i + j), pa[j]); } for (int j = 0; j < fa.Length; j += 1) { // Assert.AreEqual("dataTest:" + i + " " + j, (float)(i * j), fa[j,j]); Assert.AreEqual((float)(i * j), ((Array)tfa.GetValue(j)).GetValue(j)); } } f.Close(); Console.Out.WriteLine("**** Create HDU from kernel *****"); f = new Fits(); // Generate a FITS HDU from the kernel. f.AddHDU(Fits.MakeHDU(data)); bf = new BufferedFile( TestFileSetup.GetTargetFilename("rg2.fits"), FileAccess.ReadWrite, FileShare.ReadWrite); Console.Out.WriteLine("**** Write new file *****"); f.Write(bf); bf.Flush(); bf.Close(); bf.Dispose(); f.Close(); Console.Out.WriteLine("**** Read and check *****"); f = new Fits(TestFileSetup.GetTargetFilename("rg2.fits")); data = (Object[][])f.Read()[0].Kernel; for (int i = 0; i < data.Length; i += 1) { pa = (float[])data[i][0]; // fa = (float[,]) data[i,1]; Array[] tfa = (Array[])data[i][1]; for (int j = 0; j < pa.Length; j += 1) { Assert.AreEqual((float)(i + j), pa[j]); } for (int j = 0; j < fa.Length; j += 1) { //Assert.AreEqual("dataTest:" + i + " " + j, (float)(i * j), fa[j,j]); Assert.AreEqual((float)(i * j), ((Array)tfa.GetValue(j)).GetValue(j)); } } } finally { if (f != null) { f.Close(); } } }
/// <summary>Create an UndefinedData object using the specified object.</summary> public UndefinedData(Object x) { byteSize = ArrayFuncs.ComputeSize(x); data = new byte[(int)byteSize]; }