void PeaksWorkspace::saveNexus(::NeXus::File * file) const { //Number of Peaks const size_t np(peaks.size()); // Column vectors for peaks table std::vector<int> detectorID(np); std::vector<double> H(np); std::vector<double> K(np); std::vector<double> L(np); std::vector<double> intensity(np); std::vector<double> sigmaIntensity(np); std::vector<double> binCount(np); std::vector<double> initialEnergy(np); std::vector<double> finalEnergy(np); std::vector<double> waveLength(np); std::vector<double> scattering(np); std::vector<double> dSpacing(np); std::vector<double> TOF(np); std::vector<int> runNumber(np); std::vector<double> goniometerMatrix(9 * np); // Populate column vectors from Peak Workspace for (size_t i = 0; i < np; i++) { Peak p = peaks[i]; detectorID[i] = p.getDetectorID(); H[i] = p.getH(); K[i] = p.getK(); L[i] = p.getL(); intensity[i] = p.getIntensity(); sigmaIntensity[i] = p.getSigmaIntensity(); binCount[i] = p.getBinCount(); initialEnergy[i] = p.getInitialEnergy(); finalEnergy[i] = p.getFinalEnergy(); waveLength[i] = p.getWavelength(); scattering[i] = p.getScattering(); dSpacing[i] = p.getDSpacing(); TOF[i] = p.getTOF(); runNumber[i] = p.getRunNumber(); { Matrix<double> gm = p.getGoniometerMatrix(); goniometerMatrix[9 * i] = gm[0][0]; goniometerMatrix[9 * i + 1] = gm[1][0]; goniometerMatrix[9 * i + 2] = gm[2][0]; goniometerMatrix[9 * i + 3] = gm[0][1]; goniometerMatrix[9 * i + 4] = gm[1][1]; goniometerMatrix[9 * i + 5] = gm[2][1]; goniometerMatrix[9 * i + 6] = gm[0][2]; goniometerMatrix[9 * i + 7] = gm[1][2]; goniometerMatrix[9 * i + 8] = gm[1][2]; } // etc. } // Start Peaks Workspace in Nexus File std::string specifyInteger = "An integer"; std::string specifyDouble = "A double"; file->makeGroup("peaks_workspace", "NXentry", true); // For when peaksWorkspace can be loaded // Detectors column file->writeData("column_1", detectorID); file->openData("column_1"); file->putAttr("name", "Dectector ID"); file->putAttr("interpret_as", specifyInteger); file->putAttr("units", "Not known"); file->closeData(); // H column file->writeData("column_2", H); file->openData("column_2"); file->putAttr("name", "H"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // K column file->writeData("column_3", K); file->openData("column_3"); file->putAttr("name", "K"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // L column file->writeData("column_4", L); file->openData("column_4"); file->putAttr("name", "L"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Intensity column file->writeData("column_5", intensity); file->openData("column_5"); file->putAttr("name", "Intensity"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Sigma Intensity column file->writeData("column_6", sigmaIntensity); file->openData("column_6"); file->putAttr("name", "Sigma Intensity"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Bin Count column file->writeData("column_7", binCount); file->openData("column_7"); file->putAttr("name", "Bin Count"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Initial Energy column file->writeData("column_8", initialEnergy); file->openData("column_8"); file->putAttr("name", "Initial Energy"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Final Energy column file->writeData("column_9", finalEnergy); file->openData("column_9"); file->putAttr("name", "Final Energy"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Wave Length Column file->writeData("column_10", waveLength); file->openData("column_10"); file->putAttr("name", "Wave Length"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Scattering Column file->writeData("column_11", scattering); file->openData("column_11"); file->putAttr("name", "Scattering"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // D Spacing Column file->writeData("column_12", dSpacing); file->openData("column_12"); file->putAttr("name", "D Spacing"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // TOF Column file->writeData("column_13", TOF); file->openData("column_13"); file->putAttr("name", "TOF"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); //Run Number column file->writeData("column_14", runNumber); file->openData("column_14"); file->putAttr("name", "Run Number"); file->putAttr("interpret_as", specifyInteger); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Goniometer Matrix Column std::vector<int> array_dims; array_dims.push_back(static_cast<int>(peaks.size())); array_dims.push_back(9); file->writeData("column_15", goniometerMatrix, array_dims); file->openData("column_15"); file->putAttr("name", "Goniometer Matrix"); file->putAttr("interpret_as", "A matrix of 3x3 doubles"); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // QLab & QSample are calculated and do not need to be saved file->closeGroup(); // end of peaks workpace }
void PeakHKLErrors::functionDeriv1D(Jacobian *out, const double *xValues, const size_t nData) { PeaksWorkspace_sptr Peaks = AnalysisDataService::Instance().retrieveWS<PeaksWorkspace>( PeakWorkspaceName); boost::shared_ptr<Geometry::Instrument> instNew = getNewInstrument(Peaks); const DblMatrix &UB = Peaks->sample().getOrientedLattice().getUB(); DblMatrix UBinv(UB); UBinv.Invert(); UBinv /= 2 * M_PI; double GonRotx = getParameter("GonRotx"); double GonRoty = getParameter("GonRoty"); double GonRotz = getParameter("GonRotz"); Matrix<double> InvGonRotxMat = RotationMatrixAboutRegAxis(GonRotx, 'x'); Matrix<double> InvGonRotyMat = RotationMatrixAboutRegAxis(GonRoty, 'y'); Matrix<double> InvGonRotzMat = RotationMatrixAboutRegAxis(GonRotz, 'z'); Matrix<double> GonRot = InvGonRotxMat * InvGonRotyMat * InvGonRotzMat; InvGonRotxMat.Invert(); InvGonRotyMat.Invert(); InvGonRotzMat.Invert(); std::map<int, Kernel::Matrix<double>> RunNums2GonMatrix; getRun2MatMap(Peaks, OptRuns, RunNums2GonMatrix); g_log.debug() << "----------------------------Derivative------------------------\n"; V3D samplePosition = instNew->getSample()->getPos(); IPeak &ppeak = Peaks->getPeak(0); double L0 = ppeak.getL1(); double velocity = (L0 + ppeak.getL2()) / ppeak.getTOF(); double K = 2 * M_PI / ppeak.getWavelength() / velocity; // 2pi/lambda = K* velocity V3D beamDir = instNew->getBeamDirection(); size_t paramNums[] = {parameterIndex(std::string("SampleXOffset")), parameterIndex(std::string("SampleYOffset")), parameterIndex(std::string("SampleZOffset"))}; for (size_t i = 0; i < nData; i += 3) { int peakNum = boost::math::iround(xValues[i]); IPeak &peak_old = Peaks->getPeak(peakNum); Peak peak = createNewPeak(peak_old, instNew, 0, peak_old.getL1()); int runNum = peak_old.getRunNumber(); std::string runNumStr = std::to_string(runNum); for (int kk = 0; kk < static_cast<int>(nParams()); kk++) { out->set(i, kk, 0.0); out->set(i + 1, kk, 0.0); out->set(i + 2, kk, 0.0); } double chi, phi, omega; size_t chiParamNum, phiParamNum, omegaParamNum; size_t N = OptRuns.find("/" + runNumStr); if (N < OptRuns.size()) { chi = getParameter("chi" + (runNumStr)); phi = getParameter("phi" + (runNumStr)); omega = getParameter("omega" + (runNumStr)); peak.setGoniometerMatrix(GonRot * RunNums2GonMatrix[runNum]); chiParamNum = parameterIndex("chi" + (runNumStr)); phiParamNum = parameterIndex("phi" + (runNumStr)); omegaParamNum = parameterIndex("omega" + (runNumStr)); } else { Geometry::Goniometer Gon(peak.getGoniometerMatrix()); std::vector<double> phichiOmega = Gon.getEulerAngles("YZY"); chi = phichiOmega[1]; phi = phichiOmega[2]; omega = phichiOmega[0]; // peak.setGoniometerMatrix( GonRot*Gon.getR()); chiParamNum = phiParamNum = omegaParamNum = nParams() + 10; peak.setGoniometerMatrix(GonRot * peak.getGoniometerMatrix()); } V3D sampOffsets(getParameter("SampleXOffset"), getParameter("SampleYOffset"), getParameter("SampleZOffset")); peak.setSamplePos(peak.getSamplePos() + sampOffsets); // NOTE:Use getQLabFrame except for below. // For parameters the getGoniometerMatrix should remove GonRot, for derivs // wrt GonRot*, wrt chi*,phi*,etc. // Deriv wrt chi phi and omega if (phiParamNum < nParams()) { Matrix<double> chiMatrix = RotationMatrixAboutRegAxis(chi, 'z'); Matrix<double> phiMatrix = RotationMatrixAboutRegAxis(phi, 'y'); Matrix<double> omegaMatrix = RotationMatrixAboutRegAxis(omega, 'y'); Matrix<double> dchiMatrix = DerivRotationMatrixAboutRegAxis(chi, 'z'); Matrix<double> dphiMatrix = DerivRotationMatrixAboutRegAxis(phi, 'y'); Matrix<double> domegaMatrix = DerivRotationMatrixAboutRegAxis(omega, 'y'); Matrix<double> InvG = omegaMatrix * chiMatrix * phiMatrix; InvG.Invert(); // Calculate Derivatives wrt chi(phi,omega) in degrees Matrix<double> R = omegaMatrix * chiMatrix * dphiMatrix; Matrix<double> InvR = InvG * R * InvG * -1; V3D lab = peak.getQLabFrame(); V3D Dhkl0 = UBinv * InvR * lab; R = omegaMatrix * dchiMatrix * phiMatrix; InvR = InvG * R * InvG * -1; V3D Dhkl1 = UBinv * InvR * peak.getQLabFrame(); R = domegaMatrix * chiMatrix * phiMatrix; InvR = InvG * R * InvG * -1; V3D Dhkl2 = UBinv * InvR * peak.getQLabFrame(); // R.transpose should be R inverse out->set(i, chiParamNum, Dhkl1[0]); out->set(i + 1, chiParamNum, Dhkl1[1]); out->set(i + 2, chiParamNum, Dhkl1[2]); out->set(i, phiParamNum, Dhkl0[0]); out->set(i + 1, phiParamNum, Dhkl0[1]); out->set(i + 2, phiParamNum, Dhkl0[2]); out->set(i, omegaParamNum, Dhkl2[0]); out->set(i + 1, omegaParamNum, Dhkl2[1]); out->set(i + 2, omegaParamNum, Dhkl2[2]); } // if optimize for chi phi and omega on this peak //------------------------Goniometer Rotation Derivatives //----------------------- Matrix<double> InvGonRot(GonRot); InvGonRot.Invert(); Matrix<double> InvGon = InvGonRot * peak.getGoniometerMatrix(); InvGon.Invert(); V3D DGonx = (UBinv * InvGon * InvGonRotzMat * InvGonRotyMat * DerivRotationMatrixAboutRegAxis( -GonRotx, 'x') * // - gives inverse of GonRot peak.getQLabFrame()) * -1; V3D DGony = (UBinv * InvGon * InvGonRotzMat * DerivRotationMatrixAboutRegAxis(-GonRoty, 'y') * InvGonRotxMat * peak.getQLabFrame()) * -1; V3D DGonz = (UBinv * InvGon * DerivRotationMatrixAboutRegAxis(-GonRotz, 'z') * InvGonRotyMat * InvGonRotxMat * peak.getQLabFrame()) * -1; size_t paramnum = parameterIndex("GonRotx"); out->set(i, paramnum, DGonx[0]); out->set(i + 1, paramnum, DGonx[1]); out->set(i + 2, paramnum, DGonx[2]); out->set(i, parameterIndex("GonRoty"), DGony[0]); out->set(i + 1, parameterIndex("GonRoty"), DGony[1]); out->set(i + 2, parameterIndex("GonRoty"), DGony[2]); out->set(i, parameterIndex("GonRotz"), DGonz[0]); out->set(i + 1, parameterIndex("GonRotz"), DGonz[1]); out->set(i + 2, parameterIndex("GonRotz"), DGonz[2]); //-------------------- Sample Orientation derivatives //---------------------------------- // Qlab = -KV + k|V|*beamdir // D = pos-sampPos //|V|= vmag=(L0 + D )/tof // t1= tof - L0/|V| {time from sample to pixel} // V = D/t1 V3D D = peak.getDetPos() - samplePosition; double vmag = (L0 + D.norm()) / peak.getTOF(); double t1 = peak.getTOF() - L0 / vmag; // Derivs wrt sample x, y, z // Ddsx =( - 1, 0, 0), d|D|^2/dsx -> 2|D|d|D|/dsx =d(tranp(D)* D)/dsx =2 // Ddsx* tranp(D) //|D| also called Dmag V3D Dmagdsxsysz(D); Dmagdsxsysz *= (-1 / D.norm()); V3D vmagdsxsysz = Dmagdsxsysz / peak.getTOF(); V3D t1dsxsysz = vmagdsxsysz * (L0 / vmag / vmag); Matrix<double> Gon = peak.getGoniometerMatrix(); Gon.Invert(); // x=0 is deriv wrt SampleXoffset, x=1 is deriv wrt SampleYoffset, etc. for (int x = 0; x < 3; x++) { V3D pp; pp[x] = 1; V3D dQlab1 = pp / -t1 - D * (t1dsxsysz[x] / t1 / t1); V3D dQlab2 = beamDir * vmagdsxsysz[x]; V3D dQlab = dQlab2 - dQlab1; dQlab *= K; V3D dQSamp = Gon * dQlab; V3D dhkl = UBinv * dQSamp; out->set(i, paramNums[x], dhkl[0]); out->set(i + 1, paramNums[x], dhkl[1]); out->set(i + 2, paramNums[x], dhkl[2]); } } }
/** Append the peaks from a .peaks file into the workspace * @param outWS :: the workspace in which to place the information * @param filename :: path to the .peaks file */ void LoadIsawPeaks::appendFile( PeaksWorkspace_sptr outWS, std::string filename ) { // Open the file std::ifstream in( filename.c_str() ); // Read the header, load the instrument double T0; std::string s = readHeader( outWS, in , T0); // set T0 in the run parameters API::Run & m_run = outWS->mutableRun(); m_run.addProperty<double>("T0", T0, true); if( !in.good() || s.length() < 1 ) throw std::runtime_error( "End of Peaks file before peaks" ); if( s.compare( std::string( "0" ) ) != 0 ) throw std::logic_error( "No header for Peak segments" ); readToEndOfLine( in , true ); s = getWord( in , false ); int run, bankNum; double chi , phi , omega , monCount; // Build the universal goniometer that will build the rotation matrix. Mantid::Geometry::Goniometer uniGonio; uniGonio.makeUniversalGoniometer(); // TODO: Can we find the number of peaks to get better progress reporting? Progress prog(this, 0.0, 1.0, 100); while( in.good() ) { // Read the header if necessary s = readPeakBlockHeader( s , in , run , bankNum , chi , phi , omega , monCount ); // Build the Rotation matrix using phi,chi,omega uniGonio.setRotationAngle("phi", phi); uniGonio.setRotationAngle("chi", chi); uniGonio.setRotationAngle("omega", omega); //Put goniometer into peaks workspace outWS->mutableRun().setGoniometer(uniGonio, false); std::ostringstream oss; std::string bankString = "bank"; if (outWS->getInstrument()->getName() == "WISH") bankString = "WISHpanel0"; oss << bankString << bankNum; std::string bankName = oss.str(); int seqNum = -1; try { // Read the peak Peak peak = readPeak(outWS, s, in, seqNum, bankName); // Get the calculated goniometer matrix Matrix<double> gonMat = uniGonio.getR(); peak.setGoniometerMatrix(gonMat); peak.setRunNumber(run); peak.setMonitorCount( monCount ); double tof = peak.getTOF(); Kernel::Units::Wavelength wl; wl.initialize(peak.getL1(), peak.getL2(), peak.getScattering(), 0, peak.getInitialEnergy(), 0.0); peak.setWavelength(wl.singleFromTOF( tof)); // Add the peak to workspace outWS->addPeak(peak); } catch (std::runtime_error & e) { g_log.warning() << "Error reading peak SEQN " << seqNum << " : " << e.what() << std::endl; } prog.report(); } }
void PeaksWorkspace::saveNexus(::NeXus::File *file) const { // Number of Peaks const size_t np(peaks.size()); // Column vectors for peaks table std::vector<int> detectorID(np); std::vector<double> H(np); std::vector<double> K(np); std::vector<double> L(np); std::vector<double> intensity(np); std::vector<double> sigmaIntensity(np); std::vector<double> binCount(np); std::vector<double> initialEnergy(np); std::vector<double> finalEnergy(np); std::vector<double> waveLength(np); std::vector<double> scattering(np); std::vector<double> dSpacing(np); std::vector<double> TOF(np); std::vector<int> runNumber(np); std::vector<double> goniometerMatrix(9 * np); std::vector<std::string> shapes(np); // Populate column vectors from Peak Workspace size_t maxShapeJSONLength = 0; for (size_t i = 0; i < np; i++) { Peak p = peaks[i]; detectorID[i] = p.getDetectorID(); H[i] = p.getH(); K[i] = p.getK(); L[i] = p.getL(); intensity[i] = p.getIntensity(); sigmaIntensity[i] = p.getSigmaIntensity(); binCount[i] = p.getBinCount(); initialEnergy[i] = p.getInitialEnergy(); finalEnergy[i] = p.getFinalEnergy(); waveLength[i] = p.getWavelength(); scattering[i] = p.getScattering(); dSpacing[i] = p.getDSpacing(); TOF[i] = p.getTOF(); runNumber[i] = p.getRunNumber(); { Matrix<double> gm = p.getGoniometerMatrix(); goniometerMatrix[9 * i] = gm[0][0]; goniometerMatrix[9 * i + 1] = gm[1][0]; goniometerMatrix[9 * i + 2] = gm[2][0]; goniometerMatrix[9 * i + 3] = gm[0][1]; goniometerMatrix[9 * i + 4] = gm[1][1]; goniometerMatrix[9 * i + 5] = gm[2][1]; goniometerMatrix[9 * i + 6] = gm[0][2]; goniometerMatrix[9 * i + 7] = gm[1][2]; goniometerMatrix[9 * i + 8] = gm[2][2]; } const std::string shapeJSON = p.getPeakShape().toJSON(); shapes[i] = shapeJSON; if (shapeJSON.size() > maxShapeJSONLength) { maxShapeJSONLength = shapeJSON.size(); } } // Start Peaks Workspace in Nexus File const std::string specifyInteger = "An integer"; const std::string specifyDouble = "A double"; const std::string specifyString = "A string"; file->makeGroup("peaks_workspace", "NXentry", true); // For when peaksWorkspace can be loaded // Coordinate system file->writeData("coordinate_system", static_cast<uint32_t>(m_coordSystem)); // Write out the Qconvention // ki-kf for Inelastic convention; kf-ki for Crystallography convention std::string m_QConvention = this->getConvention(); file->putAttr("QConvention", m_QConvention); // Detectors column file->writeData("column_1", detectorID); file->openData("column_1"); file->putAttr("name", "Detector ID"); file->putAttr("interpret_as", specifyInteger); file->putAttr("units", "Not known"); file->closeData(); // H column file->writeData("column_2", H); file->openData("column_2"); file->putAttr("name", "H"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // K column file->writeData("column_3", K); file->openData("column_3"); file->putAttr("name", "K"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // L column file->writeData("column_4", L); file->openData("column_4"); file->putAttr("name", "L"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Intensity column file->writeData("column_5", intensity); file->openData("column_5"); file->putAttr("name", "Intensity"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Sigma Intensity column file->writeData("column_6", sigmaIntensity); file->openData("column_6"); file->putAttr("name", "Sigma Intensity"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Bin Count column file->writeData("column_7", binCount); file->openData("column_7"); file->putAttr("name", "Bin Count"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Initial Energy column file->writeData("column_8", initialEnergy); file->openData("column_8"); file->putAttr("name", "Initial Energy"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Final Energy column file->writeData("column_9", finalEnergy); file->openData("column_9"); file->putAttr("name", "Final Energy"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Wave Length Column file->writeData("column_10", waveLength); file->openData("column_10"); file->putAttr("name", "Wave Length"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Scattering Column file->writeData("column_11", scattering); file->openData("column_11"); file->putAttr("name", "Scattering"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // D Spacing Column file->writeData("column_12", dSpacing); file->openData("column_12"); file->putAttr("name", "D Spacing"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // TOF Column file->writeData("column_13", TOF); file->openData("column_13"); file->putAttr("name", "TOF"); file->putAttr("interpret_as", specifyDouble); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Run Number column file->writeData("column_14", runNumber); file->openData("column_14"); file->putAttr("name", "Run Number"); file->putAttr("interpret_as", specifyInteger); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Goniometer Matrix Column std::vector<int> array_dims; array_dims.push_back(static_cast<int>(peaks.size())); array_dims.push_back(9); file->writeData("column_15", goniometerMatrix, array_dims); file->openData("column_15"); file->putAttr("name", "Goniometer Matrix"); file->putAttr("interpret_as", "A matrix of 3x3 doubles"); file->putAttr("units", "Not known"); // Units may need changing when known file->closeData(); // Shape std::vector<int64_t> dims; dims.push_back(np); dims.push_back(static_cast<int>(maxShapeJSONLength)); const std::string name = "column_16"; file->makeData(name, NeXus::CHAR, dims, false); file->openData(name); auto toNexus = new char[maxShapeJSONLength * np]; for (size_t ii = 0; ii < np; ii++) { std::string rowStr = shapes[ii]; for (size_t ic = 0; ic < rowStr.size(); ic++) toNexus[ii * maxShapeJSONLength + ic] = rowStr[ic]; for (size_t ic = rowStr.size(); ic < static_cast<size_t>(maxShapeJSONLength); ic++) toNexus[ii * maxShapeJSONLength + ic] = ' '; } file->putData((void *)(toNexus)); delete[] toNexus; file->putAttr("units", "Not known"); // Units may need changing when known file->putAttr("name", "Shape"); file->putAttr("interpret_as", specifyString); file->closeData(); // QLab & QSample are calculated and do not need to be saved file->closeGroup(); // end of peaks workpace }