feat:ReadSCP

This commit is contained in:
nieziyan 2023-10-17 20:45:59 +08:00
parent 9820d285e7
commit 2628be8cb0
5 changed files with 470 additions and 1 deletions

View File

@ -6,6 +6,8 @@ public interface DateConstant {
String TIME = "HH:mm:ss";
String TIME_MS = "HH:mm:ss.S";
String DATE_TIME = "yyyy-MM-dd HH:mm:ss";
String DATE_TIME_S = "yyyy/MM/dd-HH:mm:ss";
@ -14,6 +16,8 @@ public interface DateConstant {
String DATE_BIAS_TIME = "yyyy/MM/dd HH:mm:ss";
String DATE_BIAS_TIME_MS = "yyyy/MM/dd HH:mm:ss.S";
String TIME_START = " 00:00:00";
String TIME_END = " 23:59:59";

View File

@ -0,0 +1,91 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
@Data
public class SpcHead1 {
public SpcHead1() {
// 需根据谱改变
EngPrNum = 3;
EffNum = 0;
SpcRecNum = 0;
SpcChnNum = 0;
// 重要指针
AcqInfRP = 2;
CalRP1 = 5;
CalRP2 = 7;
EffRP = 14;
EngPrRP = 11;
SpcFirstRP = 68;
Inftyp = 1;
Filtyp = 1;
Reserved1 = 1;
Reserved2 = 0;
SamDesRP = 3;
DetDesRP = 4;
EbrDesRP = 0;
AnaRP1 = 31;
AnaRP2 = 37;
AnaRP3 = 46;
AnaRP4 = 56;
SrpDesRP = 0;
IeqDesRP = 0;
GeoDesRP = 0;
MpcDesRP = 0;
CalDesRP = 10;
ROI1 = 65;
Reserved3 = 0;
DDP = 0;
ActUnit = 0;
LabPerRP = 55;
MaxNumE = 323;
MaxNumU = 323;
Abstch = 0;
AcqTime = 12631.7f;
AcqTime8 = 12631.7;
}
public short Inftyp; //1:整形SPC文件的标志 必须为1
public short Filtyp; //2:整形SPC文件的标志 必须为1
public short Reserved1; //3:Reserved
public short Reserved2; //4:Reserved
public short AcqInfRP; //5:Acquisition Information Record pointer
public short SamDesRP; //6:Sample Description Record pointer
public short DetDesRP; //7:Detector Description Record pointer
public short EbrDesRP; //8:EBAR Description Record
public short AnaRP1; //9:First Analysis Parameters Record pointer
public short AnaRP2; //10:Second Analysis Parameters Record pointer
public short AnaRP3; //11:Third Analysis Parameters Record pointer
public short AnaRP4; //12:Fourth Analysis Parameters Record pointer
public short SrpDesRP; //13:Absorption Correction Description Record pointer
public short IeqDesRP; //14:IEQ Description Record pointer
public short GeoDesRP; //15:Geometry Correction Description Record pointer
public short MpcDesRP; //16:MPC Description Record pointer
public short CalDesRP; //17:Calibration Description Record pointer
public short CalRP1; //18:First Calibration Data Record pointer
public short CalRP2; //19:Second Calibration Data Record pointer
public short EffRP; //20:Efficiency Pairs Record pointer(first record)
public short ROI1; //21:Record Number of the first of the two ROI records
public short EngPrRP; //22:Energe pairs record pointer
public short EngPrNum; //23:Number of energy pair records
public short Reserved3; //24:Reserved
public short DDP; //25:Disable deconvolution of unknown peaks
public short ActUnit; //26:True=microCuries,false=becquerels
public short LabPerRP; //27:Laboratory and operator name record pointer
public short MaxNumE; //28:Maximum Record Number Ever Used
public short MaxNumU; //29:Maximum Record Number In Use
public short EffNum; //30:Number of Efficiency Pairs Records(See public short 20)
public short SpcFirstRP; //31:Spectrum Record pointer (pointer to first record)
public short SpcRecNum; //32:Number of records in the spectrum
public short SpcChnNum; //33:Number of channels in spectrum
public short Abstch; //34:Physical start channel for data
public float AcqTime; //35,36:Date and Time of acquisition start in DECDAY format
public double AcqTime8; //37,40:Date and Time as double precision DECDAY
}

View File

@ -0,0 +1,30 @@
package org.jeecg.modules.base.entity;
import lombok.Data;
@Data
public class SpcHead2 {
public SpcHead2() {
// 需根据谱改变
Chnsrt = 0;
RealTime = 0.0f;
LiveTime = 0.0f;
Seqnum = 0;
Mcanu = 1;
Segnum = 1;
Mcadvt = 0;
}
public short AddRAM; //40:用于补足内存
public short Seqnum; //41:Sequence number
public short Mcanu; //42:MCA number as two ASCII characters(old) or Detector
// number as integer for systems with Connections
public short Segnum; //43:Segment number as two ASCII characters(old)
// or as integer value 1 for systems with Connections
public short Mcadvt; //44:MCA device type
public short Chnsrt; //45:Start channel number
public float RealTime; //46,47:Real Time in seconds
public float LiveTime; //48,49:Live time in seconds
}

View File

@ -1,11 +1,12 @@
package org.jeecg.modules.entity.vo;
import com.google.common.collect.Lists;
import lombok.Data;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
@Data
public class FileData implements Serializable {

View File

@ -0,0 +1,343 @@
package org.jeecg.modules.controller;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.CharsetUtil;
import org.jeecg.common.constant.DateConstant;
import org.jeecg.modules.base.entity.SpcHead1;
import org.jeecg.modules.base.entity.SpcHead2;
import org.jeecg.modules.entity.vo.FileData;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static java.lang.Math.pow;
public class Demo {
public static void main(String[] args) throws IOException {
FileData fileData = new FileData();
String filePath = "C:\\\\Users\\\\a\\\\Desktop\\\\shift\\\\standard.SPC";
// r:只读 rw:读写
RandomAccessFile SpcFile = new RandomAccessFile(filePath, "r");
short Inftyp;
short Filtyp;
byte[] buffer = new byte[2];
SpcFile.read(buffer);
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
Inftyp = byteBuffer.getShort();
SpcFile.read(buffer);
byteBuffer = ByteBuffer.wrap(buffer);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
Filtyp = byteBuffer.getShort();
if (Inftyp != 1 || Filtyp != 1) return;
// 读入整形spc文件的头记录(第一个记录)128字节
SpcHead1 head1 = new SpcHead1();
SpcHead2 head2 = new SpcHead2();
SpcFile.seek(0);
// Acquisition
// 从intspc能谱中读取能谱开测时间
int AcqY, AcqM, AcqD, AcqH, AcqMin;
float AcqS, AcqRT, AcqLT;
byte[] temByte = new byte[200 * 2];
int lOffset;
lOffset = (head1.AcqInfRP - 1) * 128;
SpcFile.seek((lOffset + 16) * 2);
SpcFile.read(temByte, 0, 12 * 2);
char[] temchar = byteToChar(temByte);
char char1, char2;
char1 = temchar[7];
char2 = temchar[8];
if (temchar[9] == '0') {
temchar[7] = '1';
temchar[8] = '9';
} else {
temchar[7] = '2';
temchar[8] = '0';
}
temchar[9] = char1;
temchar[10] = char2;
temchar[11] = '\0';
AcqY = 0;
for (int i = 7; i < 11; i++) {
temchar[i] = (char) (temchar[i] - 48);
AcqY = (int) (AcqY + temchar[i] * pow(10, 10 - i));
}
if (temchar[3] == 'J' && temchar[4] == 'a' && temchar[5] == 'n') AcqM = 1;
if (temchar[3] == 'F' && temchar[4] == 'e' && temchar[5] == 'b') AcqM = 2;
if (temchar[3] == 'M' && temchar[4] == 'a' && temchar[5] == 'r') AcqM = 3;
if (temchar[3] == 'A' && temchar[4] == 'p' && temchar[5] == 'r') AcqM = 4;
if (temchar[3] == 'M' && temchar[4] == 'a' && temchar[5] == 'y') AcqM = 5;
if (temchar[3] == 'J' && temchar[4] == 'u' && temchar[5] == 'n') AcqM = 6;
if (temchar[3] == 'J' && temchar[4] == 'u' && temchar[5] == 'l') AcqM = 7;
if (temchar[3] == 'A' && temchar[4] == 'u' && temchar[5] == 'g') AcqM = 8;
if (temchar[3] == 'S' && temchar[4] == 'e' && temchar[5] == 'p') AcqM = 9;
if (temchar[3] == 'O' && temchar[4] == 'c' && temchar[5] == 't') AcqM = 10;
if (temchar[3] == 'N' && temchar[4] == 'o' && temchar[5] == 'v') AcqM = 11;
if (temchar[3] == 'D' && temchar[4] == 'e' && temchar[5] == 'c') AcqM = 12;
AcqD = 0;
for (int i = 0; i < 2; i++) {
temchar[i] = (char) (temchar[i] - 48);
AcqD = (int) (AcqD + temchar[i] * pow(10, 1 - i));
}
SpcFile.read(temByte, 0 ,10 * 2);
temchar = byteToChar(temByte);
temchar[9] = '\0';
AcqH = 0;
for (int i = 0; i < 2; i++) {
temchar[i] = (char) (temchar[i] - 48);
AcqH = (int) (AcqH + temchar[i] * pow(10, 1 - i));
}
AcqMin = 0;
for (int i = 3; i < 5; i++) {
temchar[i] = (char) (temchar[i] - 48);
AcqMin = (int) (AcqMin + temchar[i] * pow(10, 4 - i));
}
AcqS = 0;
for (int i = 6; i < 8; i++) {
temchar[i] = (char) (temchar[i] - 48);
AcqS = (float) (AcqS + temchar[i] * pow(10, 7 - i));
}
AcqLT = 0;
SpcFile.read(temByte, 0, 10 * 2);
temchar = byteToChar(temByte);
for (int i = 0; i < 10; i++) {
if (temchar[i] == 32) {
temchar[i] = 0;
} else {
temchar[i] = (char) (temchar[i] - 48);
}
AcqLT = (float) (AcqLT + temchar[i] * pow(10, 9 - i));
}
AcqRT = 0;
SpcFile.read(temByte, 0, 10 * 2);
temchar = byteToChar(temByte);
for (int i = 0; i < 10; i++) {
if (temchar[i] == 32)
temchar[i] = 0;
else
temchar[i] = (char) (temchar[i] - 48);
AcqRT = (float) (AcqRT + temchar[i] * pow(10, 9 - i));
}
int seconds = (int) AcqS;
int ms = (int) ((AcqS - seconds) * 10);
String acq_date = LocalDate.of(AcqY, AcqM, AcqD).
format(DateTimeFormatter.ofPattern(DateConstant.DATE_BIAS));
fileData.setAcq_date(acq_date);
String acq_time = LocalTime.of(AcqH, AcqMin, seconds, ms)
.format(DateTimeFormatter.ofPattern(DateConstant.TIME_MS));
fileData.setAcq_time(acq_time);
fileData.setAcq_real((double) head2.RealTime);
fileData.setAcq_live((double) head2.LiveTime);
// Calibration
// 从intspc能谱中读取能谱刻度时间
int CalY, CalM, CalD, CalH, CalMin;
float CalS;
lOffset = (head1.CalRP2 - 1) * 128;
SpcFile.seek((lOffset + 32) * 2);
SpcFile.read(temByte, 0, 10 * 2);
temchar = byteToChar(temByte);
char1 = temchar[7];
char2 = temchar[8];
if (temchar[9] == '0') {
temchar[7] = '1';
temchar[8] = '9';
} else {
temchar[7] = '2';
temchar[8] = '0';
}
temchar[9] = char1;
temchar[10] = char2;
temchar[11] = '\0';
CalY = 0;
for (int i = 7; i < 11; i++) {
temchar[i] = (char) (temchar[i] - 48);
CalY = (int) (CalY + temchar[i] * pow(10, 10 - i));
}
if (temchar[3] == 'J' && temchar[4] == 'a' && temchar[5] == 'n') CalM = 1;
if (temchar[3] == 'F' && temchar[4] == 'e' && temchar[5] == 'b') CalM = 2;
if (temchar[3] == 'M' && temchar[4] == 'a' && temchar[5] == 'r') CalM = 3;
if (temchar[3] == 'A' && temchar[4] == 'p' && temchar[5] == 'r') CalM = 4;
if (temchar[3] == 'M' && temchar[4] == 'a' && temchar[5] == 'y') CalM = 5;
if (temchar[3] == 'J' && temchar[4] == 'u' && temchar[5] == 'n') CalM = 6;
if (temchar[3] == 'J' && temchar[4] == 'u' && temchar[5] == 'l') CalM = 7;
if (temchar[3] == 'A' && temchar[4] == 'u' && temchar[5] == 'g') CalM = 8;
if (temchar[3] == 'S' && temchar[4] == 'e' && temchar[5] == 'p') CalM = 9;
if (temchar[3] == 'O' && temchar[4] == 'c' && temchar[5] == 't') CalM = 10;
if (temchar[3] == 'N' && temchar[4] == 'o' && temchar[5] == 'v') CalM = 11;
if (temchar[3] == 'D' && temchar[4] == 'e' && temchar[5] == 'c') CalM = 12;
CalD = 0;
for (int i = 0; i < 2; i++) {
temchar[i] = (char) (temchar[i] - 48);
CalD = (int) (CalD + temchar[i] * pow(10, 1 - i));
}
SpcFile.read(temByte, 0, 10 * 2);
temchar = byteToChar(temByte);
temchar[9] = '\0';
CalH = 0;
for (int i = 0; i < 2; i++) {
temchar[i] = (char) (temchar[i] - 48);
CalH = (int) (CalH + temchar[i] * pow(10, 1 - i));
}
CalMin = 0;
for (int i = 3; i < 5; i++) {
temchar[i] = (char) (temchar[i] - 48);
CalMin = (int) (CalMin + temchar[i] * pow(10, 4 - i));
}
CalS = 0;
for (int i = 6; i < 8; i++) {
temchar[i] = (char) (temchar[i] - 48);
CalS = (float) (CalS + temchar[i] * pow(10, 7 - i));
}
int cal_s = (int) CalS;
int cal_ms = (int) ((CalS - cal_s) * 10);
String calibra_time = LocalDateTime.of(CalY, CalM, CalD, CalH, CalMin, cal_s, cal_ms)
.format(DateTimeFormatter.ofPattern(DateConstant.DATE_BIAS_TIME_MS));
fileData.setCalibra_time(calibra_time);
// g_Energy g_Resolution
if (head1.EngPrRP > 0) // 存在能量刻度
{
// 从intspc能谱中读取能谱刻度信息
byte[] cerByte = new byte[32 * 4];
byte[] engByte = new byte[32 * 4];
byte[] fWHMByte = new byte[32 * 4];
lOffset = (head1.EngPrRP - 1) * 128;
SpcFile.seek(lOffset * 2);
SpcFile.read(cerByte, 0, 128 * 2);
float Cer[] = byteToFloat(cerByte);
SpcFile.read(engByte, 0, 128 * 2);
float Eng[] = byteToFloat(engByte);
SpcFile.read(fWHMByte, 0, 128 * 2);
float FWHM[] = byteToFloat(fWHMByte);
short EngNum;
byte[] engNumByte = new byte[4];
lOffset = (head1.CalRP1 - 1) * 128;
SpcFile.seek((lOffset + 74) * 2);
SpcFile.read(engNumByte, 0, 2 * 2);
EngNum = byteToShort(engNumByte);
float CerUnc = 0.5F;
for (int i = 0; i < EngNum; i++) {
fileData.getVvEner().get(0).add((double) Eng[i]);
fileData.getVvEner().get(1).add((double) Cer[i]);
fileData.getVvEner().get(2).add((double) CerUnc);
}
if (EngNum > 1) {
int i1 = 1, i2 = EngNum - 2;
if (EngNum < 4) {
i1 = 0;
i2 = EngNum - 1;
}
fileData.setEner_slope((double) ((Eng[i2] - Eng[i1]) / (Cer[i2] - Cer[i1])));
double v1 = fileData.getVvEner().get(0).get(i1) * fileData.getVvEner().get(1).get(i2);
double v2 = fileData.getVvEner().get(0).get(i2) * fileData.getVvEner().get(1).get(i1);
double v3 = fileData.getVvEner().get(1).get(i2) - fileData.getVvEner().get(1).get(i1);
fileData.setEner_intercept((v1 - v2) / v3);
}
for (int i = 0; i < EngNum; i++) {
fileData.getVvReso().get(0).add((double) Eng[i]);
fileData.getVvReso().get(1).add(FWHM[i] * fileData.getEner_slope());
fileData.getVvReso().get(2).add((double) CerUnc);
}
}
// g_Efficiency
if (head1.EffRP > 0) { // 存在效率刻度
byte[] effNumByte = new byte[4];
lOffset = (head1.CalRP1 - 1) * 128;
SpcFile.seek((lOffset + 4) * 2);
SpcFile.read(effNumByte,0,2);
short EffNum = byteToShort(effNumByte);
// 0,2,4等偶数存放能量1,3,5等奇数存放效率
byte[] effByte = new byte[32 * 4];
float EffUnc = 0.5F;
lOffset = (head1.EffRP - 1) * 128;
SpcFile.seek(lOffset * 2);
SpcFile.read(effByte, 0, 128 * 2);
float Eff[] = byteToFloat(effByte);
for (int i = 0; i < EffNum; i++) {
fileData.getVvEffi().get(0).add((double) Eff[i * 2]);
fileData.getVvEffi().get(1).add((double) Eff[i * 2 + 1]);
fileData.getVvEffi().get(2).add((double) EffUnc);
}
}
// Spectrum
int[] SpcData = new int[100000];
fileData.setNum_count(head1.SpcChnNum);
fileData.setStart_chan(head2.Chnsrt);
float EngA, EngB, EngC;
lOffset = (head1.CalRP1 - 1) * 128;
SpcFile.seek(lOffset + 20);
SpcFile.read(( char*)&EngA, 4);
SpcFile.read(( char*)&EngB, 4);
SpcFile.read(( char*)&EngC, 4);
fileData.max_energy = EngA + EngB * fileData.num_count + EngC * pow(fileData.num_count, 2);
lOffset = (head1.SpcFirstRP - 1) * 128;
SpcFile.seek(lOffset);
SpcFile.read(( char*)SpcData, fileData.num_count * 4);
for (int i = 0; i < fileData.num_count; i++) {
fileData.vCounts.push_back(SpcData[i]);
}
SpcFile.close();
}
public static char[] byteToChar(byte[] data) {
return new String(data, StandardCharsets.UTF_8).toCharArray();
}
public static float[] byteToFloat(byte[] data) {
// 每个浮点数占用4个字节
int floatCount = data.length / 4;
float[] floatArray = new float[floatCount];
ByteBuffer buffer = ByteBuffer.wrap(data);
for (int i = 0; i < floatCount; i++) {
floatArray[i] = buffer.getFloat();
}
return floatArray;
}
public static short byteToShort(byte[] byteData) {
ByteBuffer buffer = ByteBuffer.wrap(byteData);
buffer.order(ByteOrder.LITTLE_ENDIAN);
return buffer.getShort();
}
}