export channel samples to a file
This commit is contained in:
parent
6adf0b9423
commit
0c237eb053
87
src/app.zig
87
src/app.zig
@ -739,13 +739,15 @@ pub const View = struct {
|
||||
channel: Id
|
||||
};
|
||||
|
||||
const Name = std.BoundedArray(u8, 128);
|
||||
|
||||
// Persistent
|
||||
reference: Reference,
|
||||
height: f32 = 300,
|
||||
// TODO: Implement different styles of following: Look ahead, sliding, sliding window
|
||||
follow: bool = false,
|
||||
graph_opts: Graph.ViewOptions = .{},
|
||||
name: std.BoundedArray(u8, 128) = .{},
|
||||
name: Name = .{},
|
||||
|
||||
// Runtime
|
||||
graph_cache: Graph.RenderCache = .{},
|
||||
@ -1137,6 +1139,9 @@ pub const Project = struct {
|
||||
|
||||
try self.views.insertUndefinedAt(id);
|
||||
|
||||
const name = try readString(reader, allocator);
|
||||
defer allocator.free(name);
|
||||
|
||||
const reference_tag = try readInt(reader, u8);
|
||||
var reference: View.Reference = undefined;
|
||||
if (reference_tag == @intFromEnum(View.Reference.file)) {
|
||||
@ -1157,7 +1162,8 @@ pub const Project = struct {
|
||||
const view = self.views.get(id).?;
|
||||
view.* = View{
|
||||
.reference = reference,
|
||||
.transformed_samples = sample_list_id
|
||||
.transformed_samples = sample_list_id,
|
||||
.name = try View.Name.fromSlice(name)
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1202,6 +1208,7 @@ pub const Project = struct {
|
||||
const view = self.views.get(view_id).?;
|
||||
|
||||
try writeId(writer, view_id);
|
||||
try writeString(writer, view.name.constSlice());
|
||||
try writeInt(writer, u8, @intFromEnum(view.reference));
|
||||
switch (view.reference) {
|
||||
.channel => |channel_id| {
|
||||
@ -1622,7 +1629,7 @@ pub fn showUI(self: *App) !void {
|
||||
fn exportProject(self: *App) !void {
|
||||
log.debug("Export", .{});
|
||||
|
||||
const project = self.project;
|
||||
const project = &self.project;
|
||||
const export_location = project.export_location orelse return error.NoExportLocation;
|
||||
const experiment_name = project.experiment_name.items;
|
||||
if (experiment_name.len == 0) {
|
||||
@ -1654,16 +1661,19 @@ fn exportProject(self: *App) !void {
|
||||
|
||||
const sample_rate = self.project.sample_rate orelse 1;
|
||||
|
||||
var file = try export_dir.createFile(export_filename, .{});
|
||||
const txt_filename = try std.mem.concat(self.allocator, u8, &.{ export_filename, ".txt" });
|
||||
defer self.allocator.free(txt_filename);
|
||||
|
||||
var file = try export_dir.createFile(txt_filename, .{});
|
||||
defer file.close();
|
||||
const writer = file.writer();
|
||||
|
||||
{
|
||||
{ //Filename
|
||||
try writer.writeAll(export_filename);
|
||||
try writer.writeAll("\n\n");
|
||||
}
|
||||
|
||||
{
|
||||
{ // Solutions
|
||||
try writer.writeAll("Time Solution\n");
|
||||
for (self.project.solutions.items) |solution| {
|
||||
const total_seconds = @as(f64, @floatFromInt(solution.sample)) / sample_rate;
|
||||
@ -1676,13 +1686,20 @@ fn exportProject(self: *App) !void {
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
{
|
||||
{ // Gain
|
||||
try writer.writeAll("Time 100/Gain\n");
|
||||
// TODO:
|
||||
for (project.gain_changes.constSlice()) |gain_change| {
|
||||
const total_seconds = gain_change.gain / sample_rate;
|
||||
|
||||
const line = try std.fmt.allocPrint(self.allocator, "{d:.2} {d:.2}\n", .{ total_seconds, gain_change.gain });
|
||||
defer self.allocator.free(line);
|
||||
|
||||
try writer.writeAll(line);
|
||||
}
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
{
|
||||
{ // Statistics points
|
||||
try writer.writeAll("Time of Statistic points\n");
|
||||
for (project.statistic_points.items) |sample_timestamp| {
|
||||
const total_seconds = @as(f64, @floatFromInt(sample_timestamp)) / sample_rate;
|
||||
@ -1690,25 +1707,55 @@ fn exportProject(self: *App) !void {
|
||||
const text = try std.fmt.allocPrint(self.allocator, "{d:.2}\n", .{total_seconds});
|
||||
defer self.allocator.free(text);
|
||||
|
||||
_ = try writer.writeAll(text);
|
||||
try writer.writeAll(text);
|
||||
|
||||
}
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
{
|
||||
{ // Pipete solutions
|
||||
try writer.writeAll("Pipete Solution:\n");
|
||||
try writer.writeAll(self.project.pipete_solution.items);
|
||||
try writer.writeAll("\n");
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
{
|
||||
{ // Note
|
||||
try writer.writeAll("Note:\n");
|
||||
try writer.writeAll(self.project.notes.items);
|
||||
try writer.writeAll("\n");
|
||||
}
|
||||
|
||||
// TODO: export channels
|
||||
{
|
||||
var view_iter = project.views.iterator();
|
||||
while (view_iter.next()) |view| {
|
||||
if (view.reference != .channel) {
|
||||
continue;
|
||||
}
|
||||
const referenced_channel = project.channels.get(view.reference.channel) orelse continue;
|
||||
|
||||
var channel_name: []u8 = undefined;
|
||||
if (view.name.len > 0) {
|
||||
channel_name = try self.allocator.dupe(u8, view.name.constSlice());
|
||||
} else {
|
||||
channel_name = try self.allocator.dupe(u8, referenced_channel.name.constSlice());
|
||||
}
|
||||
defer self.allocator.free(channel_name);
|
||||
|
||||
std.mem.replaceScalar(u8, channel_name, '/', '_');
|
||||
const channel_filename = try std.fmt.allocPrint(self.allocator, "{s}_{s}.bin", .{export_filename, channel_name});
|
||||
defer self.allocator.free(channel_filename);
|
||||
|
||||
var channel_file = try export_dir.createFile(channel_filename, .{});
|
||||
defer channel_file.close();
|
||||
|
||||
const sample_list = project.sample_lists.get(referenced_channel.collected_samples_id) orelse continue;
|
||||
var sample_iter = sample_list.iterator(0, sample_list.getLength());
|
||||
while (sample_iter.next()) |samples| {
|
||||
try channel_file.writeAll(std.mem.sliceAsBytes(samples));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(self: *App) !void {
|
||||
@ -1940,6 +1987,9 @@ fn startCollection(self: *App) !void {
|
||||
const channel_name = utils.getBoundedStringZ(&channel.name);
|
||||
const channel_type = NIDaq.getChannelType(channel_name) orelse continue;
|
||||
|
||||
const sample_list = self.project.sample_lists.get(channel.collected_samples_id) orelse continue;
|
||||
sample_list.clear(self.allocator);
|
||||
|
||||
if (channel_type == .analog_input) {
|
||||
const allowed_sample_values = channel.allowed_sample_values orelse continue;
|
||||
|
||||
@ -1953,6 +2003,17 @@ fn startCollection(self: *App) !void {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var view_iter = self.project.views.iterator();
|
||||
while (view_iter.next()) |view| {
|
||||
if (view.reference == .channel) {
|
||||
const sample_list = self.project.sample_lists.get(view.transformed_samples) orelse continue;
|
||||
sample_list.clear(self.allocator);
|
||||
view.graph_cache.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try task.setContinousSampleRate(.{ .sample_rate = sample_rate });
|
||||
|
||||
try task.start();
|
||||
|
Loading…
Reference in New Issue
Block a user