//格式:##RESOLUTION=16 /// <summary> /// 填充数据格式 /// </summary> /// <param name="Para">数据格式</param> /// <param name="property">内容</param> private static bool FillParameter(FileFormat.DataInfo Para, string[] property) { switch (property[0]) { case "##FIRSTX": double.TryParse(property[1], out Para.firstX); break; case "##LASTX": double.TryParse(property[1], out Para.lastX); break; case "##MAXY": double.TryParse(property[1], out Para.maxYValue); break; case "##MINY": double.TryParse(property[1], out Para.minYValue); break; case "##YUNITS": //谱图类型(吸收谱,干涉谱...) { switch (property[1]) { case "TRANSMITTANCE": Para.dataType = FileFormat.YAXISTYPE.YTRANS; break; case "REFLECTANCE": Para.dataType = FileFormat.YAXISTYPE.YREFLEC; break; case "ABSORBANCE": Para.dataType = FileFormat.YAXISTYPE.YABSRB; break; case "KUBELKA-MONK": Para.dataType = FileFormat.YAXISTYPE.YKMONK; break; case "ARBITRARY UNITS": Para.dataType = FileFormat.YAXISTYPE.YARB; break; default: Para.dataType = FileFormat.YAXISTYPE.YARB; break; } } break; default: return(false); } return(true); }
/// <summary> /// 写入一个数据BLock /// </summary> /// <param name="writer">写入流</param> /// <param name="fileInfo">文件信息</param> /// <param name="dataInfo">数据块信息</param> /// <param name="xDatas">X数据</param> /// <param name="yDatas">Y数据</param> /// <returns></returns> private static bool WriteOneBlock(StreamWriter writer, FileFormat.FileInfo fileInfo, FileFormat.DataInfo dataInfo, double[] xDatas, double[] yDatas) { if (writer == null || fileInfo == null || dataInfo == null || xDatas == null || yDatas == null) { ErrorString = "Invalid parameters"; return(false); } //文件头,Title可以自定义名称 if (string.IsNullOrWhiteSpace(dataInfo.dataTitle)) { writer.WriteLine("##TITLE=" + dataInfo.dataType.ToString()); } else { writer.WriteLine("##TITLE=" + dataInfo.dataTitle); } writer.WriteLine("##JCAMP-DX=5.01"); //光谱类型 if (fileInfo.specType == FileFormat.SPECTYPE.SPCNIR) { writer.WriteLine("##DATA TYPE=" + "INFRARED SPECTRUM"); //INFRARED SPECTRUM } else if (fileInfo.specType == FileFormat.SPECTYPE.SPCRMN) { writer.WriteLine("##DATA TYPE=" + "RAMAN SPECTRUM"); //RAMAN SPECTRUM } else { writer.WriteLine("##DATA TYPE=" + "UNKNOWN"); //未知 } writer.WriteLine("##DATE=" + fileInfo.createTime.ToString("dd") + "/" + fileInfo.createTime.ToString("MM") + "/" + fileInfo.createTime.ToString("yyyy")); writer.WriteLine("##TIME=" + fileInfo.createTime.ToString("HH") + "/" + fileInfo.createTime.ToString("mm") + "/" + fileInfo.createTime.ToString("ss")); writer.WriteLine("##ORIGIN=VSPEC"); writer.WriteLine("##OWNER=VSPEC"); //X轴格式 if (fileInfo.xType == FileFormat.XAXISTYPE.XNMETR) { writer.WriteLine("##XUNITS=" + "NANOMETERS"); } else if (fileInfo.xType == FileFormat.XAXISTYPE.XWAVEN) { writer.WriteLine("##XUNITS=" + "1/CM"); } else if (fileInfo.xType == FileFormat.XAXISTYPE.XUMETR) { writer.WriteLine("##XUNITS=" + "MICROMETERS"); } else if (fileInfo.xType == FileFormat.XAXISTYPE.XSECS) { writer.WriteLine("##XUNITS=" + "SECONDS"); } else { writer.WriteLine("##XUNITS=" + "ARBITRARY UNITS"); } //Y轴格式 if (dataInfo.dataType == FileFormat.YAXISTYPE.YTRANS) { writer.WriteLine("##YUNITS=" + "TRANSMITTANCE"); } else if (dataInfo.dataType == FileFormat.YAXISTYPE.YREFLEC) { writer.WriteLine("##YUNITS=" + "REFLECTANCE"); } else if (dataInfo.dataType == FileFormat.YAXISTYPE.YABSRB) { writer.WriteLine("##YUNITS=" + "ABSORBANCE"); } else if (dataInfo.dataType == FileFormat.YAXISTYPE.YKMONK) { writer.WriteLine("##YUNITS=" + "KUBELKA-MONK"); } else { writer.WriteLine("##YUNITS=" + "ARBITRARY UNITS"); } writer.WriteLine("##RESOLUTION=" + fileInfo.resolution); writer.WriteLine("##FIRSTX=" + dataInfo.firstX); writer.WriteLine("##LASTX=" + dataInfo.lastX); writer.WriteLine("##MAXY=" + dataInfo.maxYValue); writer.WriteLine("##MINY=" + dataInfo.minYValue); //保留6位有效数字 double xfactor = (int)(Math.Truncate(Math.Log10(Math.Max(dataInfo.firstX, dataInfo.lastX)))) - 6; writer.WriteLine("##XFACTOR=1e" + xfactor); double yfactor = (int)(Math.Truncate(Math.Log10(dataInfo.maxYValue))) - 6; writer.WriteLine("##YFACTOR=1e" + yfactor.ToString()); writer.WriteLine("##NPOINTS=" + yDatas.Length); writer.WriteLine("##FIRSTY=" + yDatas[0]); writer.WriteLine("##XYDATA=(X++(Y..Y))"); yfactor = Math.Pow(10, yfactor); xfactor = Math.Pow(10, xfactor); //数据 int count = 10; double stepx = (dataInfo.lastX - dataInfo.firstX) / (yDatas.Length - 1); for (int line = 0; line < ((yDatas.Length - 1) / count) + 1; line++) //10个一行 { //xValue string writestr = ((int)(dataInfo.firstX / xfactor + line * count * stepx / xfactor)).ToString(); for (int col = 0; col < count; col++) { if (line * count + col >= yDatas.Length) { break; } writestr += " " + ((int)(yDatas[line * count + col] / yfactor)).ToString(); } writer.WriteLine(writestr); } writer.WriteLine("##END="); return(true); }
public static bool ReadFile(byte[] fileData, FileFormat fileFormat) { if (fileData == null || fileFormat == null) { ErrorString = "Invalid parameters"; return(false); } fileFormat.dataInfoList = null; fileFormat.acquisitionInfo = null; fileFormat.xDataList = null; fileFormat.fileInfo = null; fileFormat.yDataList = null; if (!IsJCAMPFile(fileData)) { ErrorString = "Invalid file format"; return(false); } System.IO.MemoryStream memStream = new System.IO.MemoryStream(fileData); System.IO.StreamReader dxFile = new System.IO.StreamReader(memStream); try { //查找数据位置 string curline = dxFile.ReadLine(); while (curline != null) { curline = curline.ToUpper(); if (curline.IndexOf("##TITLE") == 0) //一个Block开始 { //保留数据的标题 string oldtitle = curline; FileFormat.DataInfo dataInfo = null; double[] yDatas = null; curline = ReadOneBlock(dxFile, fileFormat, out dataInfo, out yDatas); //从ReadOneBlock返回最后读取的字符串 if (curline == null) { throw new Exception(ErrorString); } else { //文件头没有返回dataInfo和yDatas if (dataInfo != null && yDatas != null) { if (fileFormat.dataInfoList == null) { fileFormat.dataInfoList = new List <FileFormat.DataInfo>(); } fileFormat.dataInfoList.Add(dataInfo); if (fileFormat.yDataList == null) { fileFormat.yDataList = new List <double[]>(); } fileFormat.yDataList.Add(yDatas); //处理X轴,判断X轴是否与第一个相同 if (fileFormat.xDatas == null) { fileFormat.xDataList = new List <double[]>() { CreateStepXDatas(dataInfo.firstX, dataInfo.lastX, yDatas.Length) }; } else { double[] fXDatas = fileFormat.xDatas; //如果X轴数据不一样,需要创建新的X轴 if (!IsSameDouble(fXDatas[0], dataInfo.firstX) || !IsSameDouble(fXDatas[fXDatas.Length - 1], dataInfo.lastX) || fXDatas.Length != yDatas.Length) { fileFormat.xDataList.Add(CreateStepXDatas(dataInfo.firstX, dataInfo.lastX, yDatas.Length)); } } //添加数据的标题 string[] titleinfos = oldtitle.Split('='); dataInfo.dataTitle = titleinfos.Length > 1 ? titleinfos[1].Trim() : null; } //处理当前字符串 continue; } } curline = dxFile.ReadLine(); } return(true); } catch (System.Exception ex) { ErrorString = ex.Message; return(false); } finally { if (dxFile != null) { dxFile.Close(); } } }
/// <summary> /// 读取一个数据节 /// </summary> /// <param name="dxFile">文件流</param> /// <param name="fileData">光谱格式数据</param> /// <param name="dataInfo">out 数据信息</param> /// <param name="yDatas">out Y轴数据</param> /// <returns>返回最后一个字符串,错误返回null</returns> private static string ReadOneBlock(System.IO.StreamReader dxFile, FileFormat fileData, out FileFormat.DataInfo dataInfo, out double[] yDatas) { dataInfo = new FileFormat.DataInfo(); yDatas = null; if (fileData == null) { return(null); } if (fileData.fileInfo == null) { fileData.fileInfo = new FileFormat.FileInfo(); } if (fileData.acquisitionInfo == null) { fileData.acquisitionInfo = new FileFormat.AcquisitionInfo(); } var fileInfo = fileData.fileInfo; var acqInfo = fileData.acquisitionInfo; string curline = null; try { curline = dxFile.ReadLine(); if (curline == null) { throw new Exception("Invalid file format"); } //一个Block的第二行肯定是##JCAMP_DX curline = curline.ToUpper(); if (curline.IndexOf("##JCAMP_DX") != 0 && curline.IndexOf("##JCAMP-DX") != 0) { throw new Exception("Invalid file format"); } curline = dxFile.ReadLine(); if (curline == null) { throw new Exception("Invalid file format"); } curline = curline.ToUpper(); DateTime filetime; int dataCount = 0; double tempdouble; double yfactor = 1; double xfactor = 1; while (curline != null && curline.IndexOf("##END=") != 0 && curline.IndexOf("##TITLE=") != 0) { string[] property = curline.Split('='); if (property.Length == 2) //必须有值才处理 { property[0] = property[0].Trim(); property[1] = property[1].Trim(); switch (property[0]) { case "##FIRSTX": case "##LASTX": case "##MAXY": case "##MINY": case "##YUNITS": //谱图类型(吸收谱,干涉谱...) if (FillParameter(dataInfo, property) == false) { throw new Exception("Invalid file format"); } break; case "##DATE": //标准格式是YY/MM/DD, 但OPUS存的是DD/MM/YYYY if (DateTime.TryParse(property[1], out filetime)) { fileInfo.createTime = filetime; } break; case "##TIME": if (DateTime.TryParse(property[1], out filetime)) { fileInfo.createTime = fileInfo.createTime.AddHours(filetime.Hour); fileInfo.createTime = fileInfo.createTime.AddMinutes(filetime.Minute); fileInfo.createTime = fileInfo.createTime.AddSeconds(filetime.Second); } break; case "##DATA TYPE": //光谱的类型(红外,拉曼...) switch (property[1]) { case "INFRARED SPECTRUM": fileInfo.specType = FileFormat.SPECTYPE.SPCNIR; break; case "RAMAN SPECTRUM": fileInfo.specType = FileFormat.SPECTYPE.SPCRMN; break; } break; case "##NPOINTS": int.TryParse(property[1], out dataCount); break; case "##XFACTOR": //X数据放大系数 double.TryParse(property[1], out xfactor); break; case "##YFACTOR": //Y数据放大系数 double.TryParse(property[1], out yfactor); break; case "##RESOLUTION": if (double.TryParse(property[1], out tempdouble)) { fileInfo.resolution = tempdouble; } break; case "##ORIGIN": case "##OWNER": case "##CLASS": case "##SAMPLE DESCRIPTION": case "##SPECTROMETER/DATA SYSTEM": case "##INSTRUMENTAL PARAMETERS": case "##DATA PROCESSING": break; case "##XUNITS": switch (property[1]) { case "NANOMETERS": fileInfo.xType = FileFormat.XAXISTYPE.XNMETR; break; case "1/CM": fileInfo.xType = FileFormat.XAXISTYPE.XWAVEN; break; case "MICROMETERS": fileInfo.xType = FileFormat.XAXISTYPE.XUMETR; break; case "SECONDS": fileInfo.xType = FileFormat.XAXISTYPE.XSECS; break; case "ARBITRARY UNITS": fileInfo.xType = FileFormat.XAXISTYPE.XARB; break; } break; case "##XYDATA": curline = ReadXYData(dxFile, property[1], dataCount, yfactor, out yDatas); //获得最后读取的字符串 continue; } } //读下一个行 curline = dxFile.ReadLine(); if (curline != null) { curline = curline.ToUpper(); } } return(curline); } catch (Exception ex) { ErrorString = ex.Message; return(null); } }
/// <summary> /// 读取光谱文件 /// </summary> public static bool ReadFile(byte[] fileData, int fileSize, FileFormat fileFormat) { fileFormat.dataInfoList = null; fileFormat.acquisitionInfo = null; fileFormat.xDataList = null; fileFormat.fileInfo = null; fileFormat.yDataList = null; SPAHeader mainheader = GetXHeader(fileData, fileSize); if (mainheader.dataCount == int.MaxValue) //读取文件头错误 { return(false); } //填充光谱文件信息 fileFormat.fileInfo = new FileFormat.FileInfo(); //fileFormat.fileInfo.createTime = CommonMethod.DWordToDateTime(0xD9A36D78); fileFormat.fileInfo.dataCount = (int)mainheader.dataCount; fileFormat.fileInfo.fileMemo = GetFileTitle(fileData, fileSize); fileFormat.fileInfo.instDescription = GetInstSN(fileData, fileSize); fileFormat.fileInfo.modifyFlag = 0; fileFormat.fileInfo.resolution = mainheader.resolution == 0 ? 4.0 : 32768 / mainheader.resolution; fileFormat.fileInfo.specType = FileFormat.SPECTYPE.SPCNIR; //固定值 fileFormat.fileInfo.xType = FileFormat.XAXISTYPE.XWAVEN; //mainheader.xType = 1 fileFormat.fileInfo.zType = FileFormat.ZAXISTYPE.XMSEC; //固定值 fileFormat.fileInfo.fzinc = 0.5f; //固定值 fileFormat.fileInfo.fspare = new float[8]; //固定值 //读取X轴数据(肯定是均匀的X轴) fileFormat.xDataList = new List <double[]>(); double[] tempx = new double[mainheader.dataCount]; double stepx = (mainheader.lastx - mainheader.firstx) / (tempx.Length - 1); for (int i = 0; i < tempx.Length; i++) { tempx[i] = mainheader.firstx + i * stepx; } fileFormat.xDataList.Add(tempx); //获取Y数据以及格式信息 fileFormat.dataInfoList = new List <FileFormat.DataInfo>(); fileFormat.yDataList = new List <double[]>(); //读取Y轴数据 double[] ydata = GetYData(fileData, fileSize); if (ydata == null || ydata.Length == 0) { return(false); } //Y轴数据格式 FileFormat.DataInfo info = new FileFormat.DataInfo(); info.dataType = mainheader.yType == 0x0C ? FileFormat.YAXISTYPE.YABSRB : (mainheader.yType == 0x0F ? FileFormat.YAXISTYPE.YSCRF : FileFormat.YAXISTYPE.YSCSM); info.firstX = mainheader.firstx; info.lastX = mainheader.lastx; info.maxYValue = ydata.Max(); info.minYValue = ydata.Min(); fileFormat.dataInfoList.Add(info); fileFormat.yDataList.Add(ydata); InstrumentHeader instHeader = GetInstrumentHeader(fileData, fileSize); //读取光谱参数 fileFormat.acquisitionInfo = new FileFormat.AcquisitionInfo(); fileFormat.acquisitionInfo.GAIN = mainheader.bgGrain; fileFormat.acquisitionInfo.HIGHPASS = instHeader.highFilter; fileFormat.acquisitionInfo.LOWPASS = instHeader.lowFilter; fileFormat.acquisitionInfo.LWN = mainheader.lwn; fileFormat.acquisitionInfo.SPEED = instHeader.speed.ToString(); fileFormat.acquisitionInfo.SCANS = mainheader.sampleScans; fileFormat.acquisitionInfo.SCANSBG = mainheader.bgScans; fileFormat.acquisitionInfo.IRMODE = FileFormat.enumIRMODE.NearIR; return(true); }
/// <summary> /// 读取光谱文件 /// </summary> public static bool ReadFile(byte[] fileData, FileFormat fileFormat) { fileFormat.dataInfoList = null; fileFormat.acquisitionInfo = null; fileFormat.xDataList = null; fileFormat.fileInfo = null; fileFormat.yDataList = null; MainHeader mainheader = GetMainHeader(fileData); if (mainheader.fileMark == UInt16.MaxValue) //读取文件头错误 { return(false); } //填充光谱文件信息 fileFormat.fileInfo = new FileFormat.FileInfo(); fileFormat.fileInfo.createTime = CreateFileDateTime(mainheader.fileTime); fileFormat.fileInfo.dataCount = (int)mainheader.specCols; fileFormat.fileInfo.fileMemo = CommonMethod.CovertByteArrayToString(mainheader.tile, Encoding.Default); //仪器描述 仪器名称-序列号 fileFormat.fileInfo.instDescription = CommonMethod.CovertByteArrayToString(mainheader.instrument, Encoding.Default) + instSerialSeprator + CommonMethod.CovertByteArrayToString(mainheader.serialNo, Encoding.Default); fileFormat.fileInfo.modifyFlag = 0; fileFormat.fileInfo.resolution = 16; //固定值 fileFormat.fileInfo.specType = FileFormat.SPECTYPE.SPCNIR; //固定值 fileFormat.fileInfo.xType = FileFormat.XAXISTYPE.XNMETR; //mainheader.xType = 1 fileFormat.fileInfo.zType = FileFormat.ZAXISTYPE.XMSEC; //固定值 fileFormat.fileInfo.fzinc = 0.5f; //固定值 fileFormat.fileInfo.fspare = new float[8]; //固定值 //读取X轴数据(肯定是均匀的X轴) fileFormat.xDataList = new List <double[]>(); double[] tempx = new double[mainheader.specCols]; int index = 0; for (int i = 0; i < mainheader.rangeCount; i++) //每个光谱段读取 { for (int j = 0; j < mainheader.rangeCols[i]; j++) { tempx[index] = mainheader.rangeFirstX[i] + j * mainheader.rangeStepX[i]; index++; } } fileFormat.xDataList.Add(tempx); //获取Y数据以及格式信息 fileFormat.dataInfoList = new List <FileFormat.DataInfo>(); fileFormat.yDataList = new List <double[]>(); for (int i = 0; i < mainheader.fileCount; i++) { FileHeader fileHeader = GetFileHeader(fileData, i); if (fileHeader.position == UInt16.MaxValue) { return(false); } //读取Y轴数据 double[] ydata = GetSpectrumData(fileData, i); if (ydata == null || ydata.Length == 0) { return(false); } fileFormat.yDataList.Add(ydata); //Y轴数据格式 FileFormat.DataInfo info = new FileFormat.DataInfo(); info.dataTitle = CommonMethod.CovertByteArrayToString(fileHeader.sampleNo, Encoding.Default); info.dataType = FileFormat.YAXISTYPE.YABSRB; info.firstX = mainheader.rangeFirstX[0]; info.lastX = mainheader.rangeLastX[mainheader.rangeCount - 1]; info.maxYValue = ydata.Max(); info.minYValue = ydata.Min(); fileFormat.dataInfoList.Add(info); } //读取光谱参数 fileFormat.acquisitionInfo = new FileFormat.AcquisitionInfo(); fileFormat.acquisitionInfo.GAIN = 0; fileFormat.acquisitionInfo.HIGHPASS = 0; fileFormat.acquisitionInfo.LOWPASS = 0; fileFormat.acquisitionInfo.LWN = 0; fileFormat.acquisitionInfo.SPEED = null; fileFormat.acquisitionInfo.SCANS = 0; fileFormat.acquisitionInfo.SCANSBG = 0; fileFormat.acquisitionInfo.IRMODE = FileFormat.enumIRMODE.NearIR; return(true); }
public static bool ReadFile(byte[] fileData, int fileSize, FileFormat fileFormat) { fileFormat.dataInfoList = null; fileFormat.acquisitionInfo = null; fileFormat.xDataList = null; fileFormat.fileInfo = null; fileFormat.yDataList = null; SPCHeader mainheader = GetMainHeader(fileData, fileSize); if (mainheader.fnpts == int.MaxValue) //读取文件头错误 { return(false); } //填充光谱文件信息 fileFormat.fileInfo = new FileFormat.FileInfo(); fileFormat.fileInfo.createTime = CommonMethod.DWordToDateTime(mainheader.fdate); fileFormat.fileInfo.dataCount = (int)mainheader.fnpts; fileFormat.fileInfo.fileMemo = mainheader.fcmnt; //CommonMethod.ConvertFixedByteToString(mainheader.fcmnt, 130); fileFormat.fileInfo.instDescription = mainheader.fsource; //CommonMethod.ConvertFixedByteToString(mainheader.fsource, 9); fileFormat.fileInfo.modifyFlag = mainheader.fmods; double tempres = 0; //resolution string resstr = mainheader.fres; // CommonMethod.ConvertFixedByteToString(mainheader.fres, 9); fileFormat.fileInfo.resolution = double.TryParse(resstr, out tempres) == true ? tempres : 0; fileFormat.fileInfo.specType = mainheader.fexper == 0 ? FileFormat.SPECTYPE.SPCNIR : (FileFormat.SPECTYPE)mainheader.fexper; fileFormat.fileInfo.xType = (FileFormat.XAXISTYPE)mainheader.fxtype; fileFormat.fileInfo.zType = (FileFormat.ZAXISTYPE)mainheader.fztype; fileFormat.fileInfo.fzinc = mainheader.fzinc; fileFormat.fileInfo.fspare = mainheader.fspare; //CommonMethod.CopyDataArrayFromFixedPtr<float>(mainheader.fspare, 8); //读取X轴数据 if ((mainheader.ftflgs & (byte)Ftflgs.TXYXYS) == 0) //统一的X轴 { fileFormat.xDataList = new List <double[]>(); double[] tempx = GetXData(fileData, fileSize, 0); fileFormat.xDataList.Add(tempx); } else //多个X轴 { fileFormat.xDataList = new List <double[]>(); for (int i = 0; i < mainheader.fnsub; i++) { double[] tempx = GetXData(fileData, fileSize, i); fileFormat.xDataList.Add(tempx); } } //获取Y数据以及格式信息 fileFormat.dataInfoList = new List <FileFormat.DataInfo>(); fileFormat.yDataList = new List <double[]>(); for (int i = 0; i < mainheader.fnsub; i++) { SPCSubHeader subheader = GetSubHeader(fileData, fileSize, i); if (subheader.subnpts == int.MaxValue) //读取结构错误 { return(false); } //读取Y轴数据 double[] ydata = GetYData(fileData, fileSize, i); if (ydata == null || ydata.Length == 0) { return(false); } //Y轴数据格式 FileFormat.DataInfo info = new FileFormat.DataInfo(); if (subheader.subscan == 0) //用这个属性来记录子数据的类型(吸收谱,干涉谱等等) { info.dataType = mainheader.fytype == 0 ? FileFormat.YAXISTYPE.YABSRB : (FileFormat.YAXISTYPE)mainheader.fytype; } else { info.dataType = (FileFormat.YAXISTYPE)subheader.subscan; } info.firstX = mainheader.ffirst; info.lastX = mainheader.flast; info.maxYValue = ydata.Max(); info.minYValue = ydata.Min(); fileFormat.dataInfoList.Add(info); fileFormat.yDataList.Add(ydata); } //读取光谱参数 string parastr = GetLogText(fileData, fileSize); if (parastr != null) { fileFormat.acquisitionInfo = FromSPCLogData(parastr); } if (fileFormat.acquisitionInfo == null) { fileFormat.acquisitionInfo = new FileFormat.AcquisitionInfo(); } return(true); }