Files
easySif/mainProgram/SpectralProcessor.cs
tangchao0503 7a449b7533 重构代码
1、将读取定标文件(rad、NonLinear)的功能,从文件ProjectManager.cs重构到文件SpectralProcessor.cs中的一个类(calAndNonLinearFileReader)中;
2、从文件ProjectManager.cs中重构出辐亮度转换方法,添加到文件SpectralProcessor.cs中SpectralProcessor类中的方法processDirectory_dn2rad → 这是为了兼容辐亮度转换命令行程序(用于整合到通量系统中);
2022-07-06 13:40:16 +08:00

847 lines
28 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.IO;
namespace mainProgram
{
public delegate void RadPercentCompleteDelegate(int ipos, string vinfo);//申明委托类型:用于通知福亮度校正的进度
class SpectralProcessor
{
public void NonLinearCorrection(double[] coefficient, double[] rawData, int bandnumber)
{
for (int i = 0; i < bandnumber; i++)
{
rawData[i] = rawData[i] / (coefficient[0]
+ coefficient[1] * rawData[i]
+ coefficient[2] * Math.Pow(rawData[i], 2)
+ coefficient[3] * Math.Pow(rawData[i], 3)
+ coefficient[4] * Math.Pow(rawData[i], 4)
+ coefficient[5] * Math.Pow(rawData[i], 5)
+ coefficient[6] * Math.Pow(rawData[i], 6)
+ coefficient[7] * Math.Pow(rawData[i], 7)
);
}
}
public void RadCorrection(double[] calData, uint integrationTime_cal, double[] targetData, int integrationTime_target, int bandnumber)
{
for (int i = 0; i < bandnumber; i++)
{
targetData[i] = calData[i] * targetData[i] * (integrationTime_cal * 1.0) / (integrationTime_target * 1.0);
if (targetData[i] < 0 || integrationTime_target == 0)//如果福亮度为负值则设置为0
{
targetData[i] = 0.0000000000000001;//丰建议不设置为0而设置为很小的数他的sif算法就不会出错
}
}
}
public void DelectDir(string srcPath)
{
DirectoryInfo dir = new DirectoryInfo(srcPath);
FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录
foreach (FileSystemInfo i in fileinfo)
{
if (i is DirectoryInfo) //判断是否文件夹
{
DirectoryInfo subdir = new DirectoryInfo(i.FullName);
subdir.Delete(true); //删除子目录和文件
}
else
{
File.Delete(i.FullName); //删除指定文件
}
}
}
public event RadPercentCompleteDelegate RadPercentCompleteEvent;//申明事件
public void processDirectory_dn2rad(string sourceDirectory, string destDirectory, CalData[] calDatas, NonLinearData[] nonLinearDatas, bool isdeleteDest = false, int CsvFileCounter = 0)//包含了工程目录结构
{
if(isdeleteDest)
DelectDir(destDirectory);
string[] sourceFilesPath = Directory.GetFileSystemEntries(sourceDirectory);
int counter = 0;
for (int i = 0; i < sourceFilesPath.Length; i++)//sourceDirectory下的每个日期文件夹
{
//构建rad中的输出文件夹
string[] forlders = sourceFilesPath[i].Split('\\');
string lastDirectory = forlders[forlders.Length - 1];
string dest = Path.Combine(destDirectory, lastDirectory);
if (!Directory.Exists(dest))
{
Directory.CreateDirectory(dest);
}
string[] rawFiles = Directory.GetFileSystemEntries(Path.Combine(sourceDirectory, lastDirectory));
foreach (string rawFileName in rawFiles)//日期文件夹下的每个DN值csv文件
{
string[] nameTmp = rawFileName.Split('\\');
string name = nameTmp[nameTmp.Length - 1];
SpectralDataReaderWriter spectralDataReaderWriter = new SpectralDataReaderWriter(rawFileName);
for (int j = 1; j <= spectralDataReaderWriter.TotalSpectralCount; j++)//处理 csv文件中的每条光谱
{
SpectralData spectralData = spectralDataReaderWriter.GetSpectral(j);
int nonLinearData_index = calAndNonLinearFileReader.GetnonLinearDataIndex(spectralData, nonLinearDatas);
int calData_index = calAndNonLinearFileReader.GetCalDataIndex(spectralData, calDatas);
if (nonLinearData_index >= 0)//非线性校正
{
NonLinearCorrection(nonLinearDatas[nonLinearData_index].nonLinearData, spectralData.spectral, spectralData.spectralDataLength);
}
if (calData_index >= 0)//福亮度转换
{
RadCorrection(calDatas[calData_index].gain, calDatas[calData_index].exposureTime, spectralData.spectral, spectralData.exposureTime, spectralData.spectralDataLength);
}
spectralDataReaderWriter.UpdateSpectral(j, spectralData);
}
string destFileName = Path.Combine(dest, name);
spectralDataReaderWriter.SaveCSV(destFileName);
counter++;
if (CsvFileCounter != 0)
{
float tmp1 = (float)counter / (float)CsvFileCounter;
float tmp2 = tmp1 * 100;
if (RadPercentCompleteEvent != null)
{
RadPercentCompleteEvent((int)tmp2, name + "\r\n");
}
}
}
}
}
}
class calAndNonLinearFileReader
{
static private int FindMaxRowCount(string filePath)
{
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
string strLine = "";
int maxColunmCount = 0;
while ((strLine = sr.ReadLine()) != null)
{
maxColunmCount++;
}
sr.Close();
fs.Close();
return maxColunmCount;
}
static public NonLinearData ReadNonLinearFile(string nonLinearFilePath)
{
NonLinearData nonLinearData;
string[] forlders = nonLinearFilePath.Split('\\');
nonLinearData.SN = forlders[forlders.Length - 1].Split('.')[0];
int lineCount = FindMaxRowCount(nonLinearFilePath);
nonLinearData.nonLinearData = new double[lineCount];
FileStream fs = new FileStream(nonLinearFilePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs);
string strLine = "";//记录每次读取的一行记录
int i = 0;
while ((strLine = sr.ReadLine()) != null)//逐行读取CSV中的数据
{
nonLinearData.nonLinearData[i] = double.Parse(strLine);
i++;
}
return nonLinearData;
}
static public CalData ReadCalFile(string calFilePath)
{
CalData calFile;
string[] forlders = calFilePath.Split('\\');
string filename = forlders[forlders.Length - 1].Split('.')[0];
string[] tmp = filename.Split('_');
calFile.SN = tmp[0];
calFile.SN = filename;
calFile.position = int.Parse(tmp[tmp.Length - 1]);
FileStream fs2 = new FileStream(calFilePath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs2);
calFile.exposureTime = br.ReadUInt32();
calFile.temperature = br.ReadSingle();
calFile.pixelCount = br.ReadInt32();
calFile.waveLengthInNM = new float[calFile.pixelCount];
calFile.gain = new double[calFile.pixelCount];
calFile.offset = new double[calFile.pixelCount];
for (int ii = 0; ii < calFile.pixelCount; ii++)
{
calFile.waveLengthInNM[ii] = br.ReadSingle();
}
for (int ii = 0; ii < calFile.pixelCount; ii++)
{
calFile.gain[ii] = br.ReadDouble();
}
for (int ii = 0; ii < calFile.pixelCount; ii++)
{
calFile.offset[ii] = br.ReadDouble();
}
return calFile;
}
static public int getNonLinearFileCount(string directory)
{
string[] metaFilesPath = Directory.GetFileSystemEntries(directory);
int txtFileCount = 0;
for (int i = 0; i < metaFilesPath.Length; i++)//
{
if (metaFilesPath[i].Contains("nonLinear"))
{
txtFileCount++;
}
}
return txtFileCount;
}
static public int getCalFileCount(string directory)//
{
string[] metaFilesPath = Directory.GetFileSystemEntries(directory);
int datFileCount = 0;
for (int i = 0; i < metaFilesPath.Length; i++)//
{
if (metaFilesPath[i].Contains("cal"))
{
datFileCount++;
}
}
return datFileCount;
}
static public bool readCalAndNonLinearFile(string directory, out CalData[] calDatas, out NonLinearData[] nonLinearDatas)
{
int datFileCount = getCalFileCount(directory);
int txtFileCount = getNonLinearFileCount(directory);
calDatas = new CalData[datFileCount];
nonLinearDatas = new NonLinearData[txtFileCount];
int d1 = 0, d2 = 0;
string[] metaFilesPath = Directory.GetFileSystemEntries(directory);
for (int i = 0; i < metaFilesPath.Length; i++)
{
if (metaFilesPath[i].Contains("nonLinear"))
{
nonLinearDatas[d1] = ReadNonLinearFile(metaFilesPath[i]);
d1++;
}
else if (metaFilesPath[i].Contains("cal"))
{
calDatas[d2] = ReadCalFile(metaFilesPath[i]);
d2++;
}
}
return true;
}
//返回值:-1代表没有匹配项
static public int GetnonLinearDataIndex(SpectralData spectralData, NonLinearData[] nonLinearData)
{
for (int i = 0; i < nonLinearData.GetLength(0); i++)
{
if (nonLinearData[i].SN.Contains(spectralData.SN))
{
return i;
}
}
return -1;
}
//返回值:-1代表没有匹配项
static public int GetCalDataIndex(SpectralData spectralData, CalData[] calData)
{
for (int i = 0; i < calData.GetLength(0); i++)
{
if (calData[i].SN.Contains(spectralData.SN) && calData[i].position == spectralData.position)
{
return i;
}
}
return -1;
}
}
public enum DataStatus { NoData, Raw, NonLinearCorrection, Rad, Sif };
public struct SpectralData
{
public DataStatus dataStatus;
public string SN;
public int position;
public int exposureTime;
public int spectralDataLength;
public double[] spectral;//long or double ?????????????????????????
}
public struct SifData
{
public string deviceType;
public string[] position;
public string[] time;
public double[,] sif;//二维数组
}
public struct CalData
{
public uint exposureTime;
public int pixelCount;
public float temperature;
public float[] waveLengthInNM;
public double[] gain;
public double[] offset;
public string SN;
public int position;
}
public struct NonLinearData
{
public double[] nonLinearData;
public string SN;
}
public class FileEncoding
{
// 给定文件的路径,读取文件的二进制数据,判断文件的编码类型
public static Encoding GetType(string FILE_NAME)
{
FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
Encoding r = GetType(fs);
fs.Close();
return r;
}
// 通过给定的文件流,判断文件的编码类型
public static Encoding GetType(FileStream fs)
{
byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };
byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };
byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //带BOM
Encoding reVal = Encoding.Default;
BinaryReader r = new BinaryReader(fs, Encoding.Default);
int i;
int.TryParse(fs.Length.ToString(), out i);
byte[] ss = r.ReadBytes(i);
if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF))
{
reVal = Encoding.UTF8;
}
else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00)
{
reVal = Encoding.BigEndianUnicode;
}
else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41)
{
reVal = Encoding.Unicode;
}
r.Close();
return reVal;
}
// 判断是否是不带 BOM 的 UTF8 格式
private static bool IsUTF8Bytes(byte[] data)
{
int charByteCounter = 1; //计算当前正分析的字符应还有的字节数
byte curByte; //当前分析的字节.
for (int i = 0; i < data.Length; i++)
{
curByte = data[i];
if (charByteCounter == 1)
{
if (curByte >= 0x80)
{
//判断当前
while (((curByte <<= 1) & 0x80) != 0)
{
charByteCounter++;
}
//标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 
if (charByteCounter == 1 || charByteCounter > 6)
{
return false;
}
}
}
else
{
//若是UTF-8 此时第一位必须为1
if ((curByte & 0xC0) != 0x80)
{
return false;
}
charByteCounter--;
}
}
if (charByteCounter > 1)
{
throw new Exception("非预期的byte格式");
}
return true;
}
}
public class SpectralDataReaderWriter
{
public SpectralDataReaderWriter(string csvPath)
{
mCsvPath = csvPath;
OpenCSV();
GetMetaData();
}
private string mCsvPath;
public DataTable mDataTable = null;
private int mTotalSpectrometer;
private int mTotalSpectralCount;
private int mSpectralCountOfOneSpectrometer;
private int[] mWavelengthCountOfSpectrometers;//mWavelengthCountOfSpectrometers
private string[] mSN;
public int TotalSpectralCount
{
get
{
return mTotalSpectralCount;
}
set
{
mTotalSpectralCount = value;
}
}
public int findMaxColunmCount(string filePath)
{
Encoding encoding = FileEncoding.GetType(filePath); //Encoding.ASCII;//
DataTable dt = new DataTable();
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, encoding);
string strLine = "";
string[] aryLine = null;
int maxColunmCount = 0;
int tmp;
while ((strLine = sr.ReadLine()) != null)
{
aryLine = strLine.Split(',');
tmp = aryLine.Length;
if (maxColunmCount < tmp)
{
maxColunmCount = tmp;
}
}
sr.Close();
fs.Close();
return maxColunmCount;
}
//https://www.jb51.net/article/193012.htm
public void OpenCSV()//从csv读取数据返回table
{
mDataTable = new DataTable();
int columnCount1 = findMaxColunmCount(mCsvPath);
for (int i = 0; i < columnCount1; i++)
{
DataColumn dc1 = new DataColumn();
mDataTable.Columns.Add(dc1);
}
Encoding encoding = FileEncoding.GetType(mCsvPath); //Encoding.ASCII;//
FileStream fs = new FileStream(mCsvPath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, encoding);
string strLine = "";//记录每次读取的一行记录
string[] aryLine = null;//记录每行记录中的各字段内容
while ((strLine = sr.ReadLine()) != null)//逐行读取CSV中的数据
{
aryLine = strLine.Split(',');
DataRow dr = mDataTable.NewRow();
for (int j = 0; j < aryLine.Length; j++)
{
dr[j] = aryLine[j];
}
mDataTable.Rows.Add(dr);
}
sr.Close();
fs.Close();
}
public void GetMetaData()
{
mTotalSpectrometer = int.Parse(mDataTable.Rows[1][1].ToString());
mWavelengthCountOfSpectrometers = new int[mTotalSpectrometer];
mSN = new string[mTotalSpectrometer];
for (int i = 0; i < mTotalSpectrometer; i++)
{
mWavelengthCountOfSpectrometers[i] = int.Parse(mDataTable.Rows[i * 2 + 2][6].ToString());
mSN[i] = mDataTable.Rows[i * 2 + 2][4].ToString();
}
mTotalSpectralCount = mDataTable.Rows.Count - 3 - mTotalSpectrometer * 2;
mSpectralCountOfOneSpectrometer = mTotalSpectralCount / mTotalSpectrometer;
}
public SpectralData GetSpectral(int index)
{
SpectralData spectralData;
if (index > mTotalSpectralCount)
{
//return spectralData;
}
int rowOffset = 3 + mTotalSpectrometer * 2;
int wavelengthCountIndex = GetIndex(index);
spectralData.SN = mSN[wavelengthCountIndex];
spectralData.position = GetPosition(index);
spectralData.spectralDataLength = mWavelengthCountOfSpectrometers[wavelengthCountIndex];
spectralData.exposureTime = int.Parse(mDataTable.Rows[index - 1 + rowOffset][2].ToString());
spectralData.spectral = new double[mWavelengthCountOfSpectrometers[wavelengthCountIndex]];
for (int i = 0; i < mWavelengthCountOfSpectrometers[wavelengthCountIndex]; i++)
{
string tmp = mDataTable.Rows[index - 1 + rowOffset][i + 3].ToString();
spectralData.spectral[i] = long.Parse(tmp);
}
spectralData.dataStatus = DataStatus.Raw;
return spectralData;
}
public void UpdateSpectral(int index, SpectralData spectralData)
{
int rowOffset = 3 + mTotalSpectrometer * 2;
int wavelengthCountIndex = GetIndex(index);
for (int i = 0; i < spectralData.spectralDataLength; i++)
{
mDataTable.Rows[index - 1 + rowOffset][i + 3] = spectralData.spectral[i];
}
}
public int GetIndex(int index)
{
index -= 1;//因为0基索引所以减1
double wavelengthCountIndexTmp = index / mSpectralCountOfOneSpectrometer;
int wavelengthCountIndex = (int)Math.Floor(wavelengthCountIndexTmp);//因为0基索引所以向下取整否则向上取整
return wavelengthCountIndex;
}
public int GetPosition(int index)
{
//index -= 1;//因为0基索引所以减1
//int position;
//int chushu = index / mSpectralCountOfOneSpectrometer;
//int yushu = index % mSpectralCountOfOneSpectrometer;
//if (yushu == 0)
//{
// position = mSpectralCountOfOneSpectrometer;
//}
//else
//{
// position = yushu;
//}
//return position;
int position;
int chushu = index / mSpectralCountOfOneSpectrometer;
int yushu = index % mSpectralCountOfOneSpectrometer;
if (yushu == 0)
{
position = mSpectralCountOfOneSpectrometer;
}
else
{
position = yushu;
}
return position;
}
public void SaveCSV(string fullPath)//table数据写入csv
{
FileInfo fi = new FileInfo(fullPath);
if (!fi.Directory.Exists)
{
fi.Directory.Create();
}
FileStream fs = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
string data = "";
//for (int i = 0; i < mDataTable.Columns.Count; i++)//写入列名
//{
// data += mDataTable.Columns[i].ColumnName.ToString();
// if (i < mDataTable.Columns.Count - 1)
// {
// data += ",";
// }
//}
//sw.WriteLine(data);
for (int i = 0; i < mDataTable.Rows.Count; i++) //写入各行数据
{
data = "";
for (int j = 0; j < mDataTable.Columns.Count; j++)
{
string str = mDataTable.Rows[i][j].ToString();
str = str.Replace("\"", "\"\"");//替换英文冒号 英文冒号需要换成两个冒号
if (str.Contains(',') || str.Contains('"')
|| str.Contains('\r') || str.Contains('\n')) //含逗号 冒号 换行符的需要放到引号中
{
str = string.Format("\"{0}\"", str);
}
data += str;
if (j < mDataTable.Columns.Count - 1)
{
data += ",";
}
}
sw.WriteLine(data);
}
sw.Close();
fs.Close();
}
public bool ChangeFileName(string OldPath, string NewPath)
{
bool re = false;
try
{
if (File.Exists(OldPath))
{
File.Move(OldPath, NewPath);
re = true;
}
}
catch
{
re = false;
}
return re;
}
public bool SaveCSV(string fullPath, string Data)
{
bool re = true;
try
{
FileStream FileStream = new FileStream(fullPath, FileMode.Append);
StreamWriter sw = new StreamWriter(FileStream, Encoding.UTF8);
sw.WriteLine(Data);
//清空缓冲区
sw.Flush();
//关闭流
sw.Close();
FileStream.Close();
}
catch
{
re = false;
}
return re;
}
};
public class SifDataReaderWriter
{
public SifDataReaderWriter(string csvPath)
{
mCsvPath = csvPath;
OpenCSV();
GetMetaData();
}
private string mCsvPath;
public DataTable mDataTable = null;
private int mTotalPositionCount;
private int mTotalSifCount;
//https://www.jb51.net/article/193012.htm
public void OpenCSV()//从csv读取数据返回table
{
mDataTable = new DataTable();
int columnCount1 = findMaxColunmCount(mCsvPath);
for (int i = 0; i < columnCount1; i++)
{
DataColumn dc1 = new DataColumn();
mDataTable.Columns.Add(dc1);
}
Encoding encoding = FileEncoding.GetType(mCsvPath); //Encoding.ASCII;//
FileStream fs = new FileStream(mCsvPath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, encoding);
string strLine = "";//记录每次读取的一行记录
string[] aryLine = null;//记录每行记录中的各字段内容
while ((strLine = sr.ReadLine()) != null)//逐行读取CSV中的数据
{
aryLine = strLine.Split(',');
DataRow dr = mDataTable.NewRow();
for (int j = 0; j < aryLine.Length; j++)
{
dr[j] = aryLine[j];
}
mDataTable.Rows.Add(dr);
}
sr.Close();
fs.Close();
}
public int findMaxColunmCount(string filePath)
{
Encoding encoding = FileEncoding.GetType(filePath); //Encoding.ASCII;//
DataTable dt = new DataTable();
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, encoding);
string strLine = "";
string[] aryLine = null;
int maxColunmCount = 0;
int tmp;
while ((strLine = sr.ReadLine()) != null)
{
aryLine = strLine.Split(',');
tmp = aryLine.Length;
if (maxColunmCount < tmp)
{
maxColunmCount = tmp;
}
}
sr.Close();
fs.Close();
return maxColunmCount;
}
public void GetMetaData()
{
mTotalPositionCount = mDataTable.Columns.Count - 2;
mTotalSifCount = mDataTable.Rows.Count - 1;
}
public SifData GetSifData()
{
SifData sifData;
//if (index > mTotalSifCount)//错误本文件没有第index条sif时间序列光谱
//{
// //return sifData;
//}
sifData.deviceType = mDataTable.Rows[1][mDataTable.Columns.Count - 1].ToString();
sifData.position = new string[mTotalPositionCount];
sifData.sif = new double[mTotalSifCount, mTotalPositionCount];
sifData.time = new string[mTotalSifCount];
for (int i = 1; i < mTotalPositionCount + 1; i++)//第一列是时间
{
sifData.position[i - 1] = mDataTable.Rows[0][i].ToString();
for (int j = 1; j < mTotalSifCount + 1; j++)//第一行是描述标题
{
string timeTmp = mDataTable.Rows[j][0].ToString();
sifData.time[j - 1] = timeTmp;
string sifTmp = mDataTable.Rows[j][i].ToString();
if (sifTmp.Length == 0)
{
sifData.sif[j - 1, i - 1] = 0;
}
else
{
sifData.sif[j - 1, i - 1] = double.Parse(sifTmp);
}
}
}
return sifData;
}
}
}