// DataIO_Std::WriteDataNormal() int DataIO_Std::WriteDataNormal(CpptrajFile& file, DataSetList const& Sets) { // Assume all 1D data sets. if (Sets.empty() || CheckAllDims(Sets, 1)) return 1; // For this output to work the X-dimension of all sets needs to match. // The most important things for output are min and step so just check that. // Use X dimension of set 0 for all set dimensions. CheckXDimension( Sets ); // TODO: Check for empty dim. DataSet* Xdata = Sets[0]; Dimension const& Xdim = static_cast<Dimension const&>( Xdata->Dim(0) ); int xcol_width = Xdim.Label().size() + 1; // Only used if hasXcolumn_ if (xcol_width < 8) xcol_width = 8; int xcol_precision = 3; // Determine size of largest DataSet. size_t maxFrames = DetermineMax( Sets ); // Set up X column. TextFormat x_col_format(XcolFmt()); if (hasXcolumn_) { if (XcolPrecSet()) { xcol_width = XcolWidth(); x_col_format = TextFormat(XcolFmt(), XcolWidth(), XcolPrec()); } else { // Create format string for X column based on dimension in first data set. // Adjust X col precision as follows: if the step is set and has a // fractional component set the X col width/precision to either the data // width/precision or the current width/precision, whichever is larger. If // the set is XYMESH but step has not been set (so we do not know spacing // between X values) use default precision. Otherwise the step has no // fractional component so make the precision zero. double step_i; double step_f = modf( Xdim.Step(), &step_i ); double min_f = modf( Xdim.Min(), &step_i ); if (Xdim.Step() > 0.0 && (step_f > 0.0 || min_f > 0.0)) { xcol_precision = std::max(xcol_precision, Xdata->Format().Precision()); xcol_width = std::max(xcol_width, Xdata->Format().Width()); } else if (Xdata->Type() != DataSet::XYMESH) xcol_precision = 0; x_col_format.SetCoordFormat( maxFrames, Xdim.Min(), Xdim.Step(), xcol_width, xcol_precision ); } } else { // If not writing an X-column, no leading space for the first dataset. Xdata->SetupFormat().SetFormatAlign( TextFormat::RIGHT ); } // Write header to buffer std::vector<int> Original_Column_Widths; if (writeHeader_) { // If x-column present, write x-label if (hasXcolumn_) WriteNameToBuffer( file, Xdim.Label(), xcol_width, true ); // To prevent truncation of DataSet legends, adjust the width of each // DataSet if necessary. for (DataSetList::const_iterator ds = Sets.begin(); ds != Sets.end(); ++ds) { // Record original column widths in case they are changed. Original_Column_Widths.push_back( (*ds)->Format().Width() ); int colLabelSize; if (ds == Sets.begin() && !hasXcolumn_) colLabelSize = (int)(*ds)->Meta().Legend().size() + 1; else colLabelSize = (int)(*ds)->Meta().Legend().size(); //mprintf("DEBUG: Set '%s', fmt width= %i, colWidth= %i, colLabelSize= %i\n", // (*ds)->legend(), (*ds)->Format().Width(), (*ds)->Format().ColumnWidth(), // colLabelSize); if (colLabelSize >= (*ds)->Format().ColumnWidth()) (*ds)->SetupFormat().SetFormatWidth( colLabelSize ); } // Write dataset names to header, left-aligning first set if no X-column DataSetList::const_iterator set = Sets.begin(); if (!hasXcolumn_) WriteNameToBuffer( file, (*set)->Meta().Legend(), (*set)->Format().ColumnWidth(), true ); else WriteNameToBuffer( file, (*set)->Meta().Legend(), (*set)->Format().ColumnWidth(), false ); ++set; for (; set != Sets.end(); ++set) WriteNameToBuffer( file, (*set)->Meta().Legend(), (*set)->Format().ColumnWidth(), false ); file.Printf("\n"); } // Write Data DataSet::SizeArray positions(1); for (positions[0] = 0; positions[0] < maxFrames; positions[0]++) { // Output Frame for each set if (hasXcolumn_) file.Printf( x_col_format.fmt(), Xdata->Coord(0, positions[0]) ); for (DataSetList::const_iterator set = Sets.begin(); set != Sets.end(); ++set) (*set)->WriteBuffer(file, positions); file.Printf("\n"); } // Restore original column widths if necessary if (!Original_Column_Widths.empty()) for (unsigned int i = 0; i != Original_Column_Widths.size(); i++) Sets[i]->SetupFormat().SetFormatWidth( Original_Column_Widths[i] ); return 0; }