licelfile
Version:
A Bun package for reading licel files (from lidar transient recorder)
77 lines (63 loc) • 2.99 kB
text/typescript
import { parseLicelProfile } from "./licelprofile";
import { type ILicelFile } from "./licelTypes";
import { latin1Decode, parseDateTime } from "./utils";
const HEADER_LINE_LENGTH = 80;
/**
* Загружает файл Licel из массива байтов.
* @param path - имя файла.
* @returns Объект ILicelFile, содержащий данные измерения.
*/
export async function loadLicelFile(path: string): Promise<ILicelFile> {
const rawBuffer = await Bun.file(path).arrayBuffer();
return loadLicelFileFromArrayBuffer(rawBuffer);
}
/**
* Загружает файл Licel из массива байтов.
* @param rawBuffer - Массив байтов.
* @returns Объект ILicelFile, содержащий данные измерения.
*/
export async function loadLicelFileFromArrayBuffer(rawBuffer: ArrayBuffer): Promise<ILicelFile> {
//const rawBuffer = await Bun.file(path).arrayBuffer();
const view = new DataView(rawBuffer);
const header0 = latin1Decode(rawBuffer.slice(0, 80)).trim().split(/\s+/);
const header1 = latin1Decode(rawBuffer.slice(80, 160)).trim().split(/\s+/);
const header2 = latin1Decode(rawBuffer.slice(160, 240)).trim().split(/\s+/);
const measurementStartTime = parseDateTime(`${header1[1]} ${header1[2]}`);
const measurementStopTime = parseDateTime(`${header1[3]} ${header1[4]}`);
const licelFile: ILicelFile = {
measurementSite: header1[0]!,
measurementStartTime,
measurementStopTime,
altitudeAboveSeaLevel: parseFloat(header1[5]!),
longitude: parseFloat(header1[6]!),
latitude: parseFloat(header1[7]!),
zenith: parseFloat(header1[8]!),
laserConfig: [{
numberOfShots: parseInt(header2[0]!, 10),
frequency: parseInt(header2[1]!, 10)
}, {
numberOfShots: parseInt(header2[2]!, 10),
frequency: parseInt(header2[3]!, 10)
}, {
numberOfShots: parseInt(header2[5]!, 10),
frequency: parseInt(header2[6]!, 10)
}],
nDatasets: parseInt(header2[4]!, 10),
profiles: [],
};
for (let i = 0; i < licelFile.nDatasets; i++) {
const profileLine = latin1Decode(rawBuffer.slice((3 + i) * HEADER_LINE_LENGTH, (3 + (i + 1)) * HEADER_LINE_LENGTH)).trim();
const profile = parseLicelProfile(profileLine);
licelFile.profiles.push(profile);
}
const bytesoffset = (3 + licelFile.nDatasets) * HEADER_LINE_LENGTH + 2;
let offset = bytesoffset;
for (let i = 0; i < licelFile.nDatasets; i++) {
const profileLen = licelFile.profiles![i]!.nDataPoints * 4;
const profileData = rawBuffer.slice(offset, offset + profileLen);
const profileDataUInt32 = new Uint32Array(profileData);
offset += (profileLen + 2);
licelFile.profiles![i]!.data = profileDataUInt32.map((value) => (value / licelFile.profiles![i]!.nShots));
}
return licelFile;
}