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
|
channel: Id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Name = std.BoundedArray(u8, 128);
|
||||||
|
|
||||||
// Persistent
|
// Persistent
|
||||||
reference: Reference,
|
reference: Reference,
|
||||||
height: f32 = 300,
|
height: f32 = 300,
|
||||||
// TODO: Implement different styles of following: Look ahead, sliding, sliding window
|
// TODO: Implement different styles of following: Look ahead, sliding, sliding window
|
||||||
follow: bool = false,
|
follow: bool = false,
|
||||||
graph_opts: Graph.ViewOptions = .{},
|
graph_opts: Graph.ViewOptions = .{},
|
||||||
name: std.BoundedArray(u8, 128) = .{},
|
name: Name = .{},
|
||||||
|
|
||||||
// Runtime
|
// Runtime
|
||||||
graph_cache: Graph.RenderCache = .{},
|
graph_cache: Graph.RenderCache = .{},
|
||||||
@ -1137,6 +1139,9 @@ pub const Project = struct {
|
|||||||
|
|
||||||
try self.views.insertUndefinedAt(id);
|
try self.views.insertUndefinedAt(id);
|
||||||
|
|
||||||
|
const name = try readString(reader, allocator);
|
||||||
|
defer allocator.free(name);
|
||||||
|
|
||||||
const reference_tag = try readInt(reader, u8);
|
const reference_tag = try readInt(reader, u8);
|
||||||
var reference: View.Reference = undefined;
|
var reference: View.Reference = undefined;
|
||||||
if (reference_tag == @intFromEnum(View.Reference.file)) {
|
if (reference_tag == @intFromEnum(View.Reference.file)) {
|
||||||
@ -1157,7 +1162,8 @@ pub const Project = struct {
|
|||||||
const view = self.views.get(id).?;
|
const view = self.views.get(id).?;
|
||||||
view.* = View{
|
view.* = View{
|
||||||
.reference = reference,
|
.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).?;
|
const view = self.views.get(view_id).?;
|
||||||
|
|
||||||
try writeId(writer, view_id);
|
try writeId(writer, view_id);
|
||||||
|
try writeString(writer, view.name.constSlice());
|
||||||
try writeInt(writer, u8, @intFromEnum(view.reference));
|
try writeInt(writer, u8, @intFromEnum(view.reference));
|
||||||
switch (view.reference) {
|
switch (view.reference) {
|
||||||
.channel => |channel_id| {
|
.channel => |channel_id| {
|
||||||
@ -1622,7 +1629,7 @@ pub fn showUI(self: *App) !void {
|
|||||||
fn exportProject(self: *App) !void {
|
fn exportProject(self: *App) !void {
|
||||||
log.debug("Export", .{});
|
log.debug("Export", .{});
|
||||||
|
|
||||||
const project = self.project;
|
const project = &self.project;
|
||||||
const export_location = project.export_location orelse return error.NoExportLocation;
|
const export_location = project.export_location orelse return error.NoExportLocation;
|
||||||
const experiment_name = project.experiment_name.items;
|
const experiment_name = project.experiment_name.items;
|
||||||
if (experiment_name.len == 0) {
|
if (experiment_name.len == 0) {
|
||||||
@ -1654,16 +1661,19 @@ fn exportProject(self: *App) !void {
|
|||||||
|
|
||||||
const sample_rate = self.project.sample_rate orelse 1;
|
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();
|
defer file.close();
|
||||||
const writer = file.writer();
|
const writer = file.writer();
|
||||||
|
|
||||||
{
|
{ //Filename
|
||||||
try writer.writeAll(export_filename);
|
try writer.writeAll(export_filename);
|
||||||
try writer.writeAll("\n\n");
|
try writer.writeAll("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{ // Solutions
|
||||||
try writer.writeAll("Time Solution\n");
|
try writer.writeAll("Time Solution\n");
|
||||||
for (self.project.solutions.items) |solution| {
|
for (self.project.solutions.items) |solution| {
|
||||||
const total_seconds = @as(f64, @floatFromInt(solution.sample)) / sample_rate;
|
const total_seconds = @as(f64, @floatFromInt(solution.sample)) / sample_rate;
|
||||||
@ -1676,13 +1686,20 @@ fn exportProject(self: *App) !void {
|
|||||||
try writer.writeAll("\n");
|
try writer.writeAll("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{ // Gain
|
||||||
try writer.writeAll("Time 100/Gain\n");
|
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");
|
try writer.writeAll("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{ // Statistics points
|
||||||
try writer.writeAll("Time of Statistic points\n");
|
try writer.writeAll("Time of Statistic points\n");
|
||||||
for (project.statistic_points.items) |sample_timestamp| {
|
for (project.statistic_points.items) |sample_timestamp| {
|
||||||
const total_seconds = @as(f64, @floatFromInt(sample_timestamp)) / sample_rate;
|
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});
|
const text = try std.fmt.allocPrint(self.allocator, "{d:.2}\n", .{total_seconds});
|
||||||
defer self.allocator.free(text);
|
defer self.allocator.free(text);
|
||||||
|
|
||||||
_ = try writer.writeAll(text);
|
try writer.writeAll(text);
|
||||||
|
|
||||||
}
|
}
|
||||||
try writer.writeAll("\n");
|
try writer.writeAll("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{ // Pipete solutions
|
||||||
try writer.writeAll("Pipete Solution:\n");
|
try writer.writeAll("Pipete Solution:\n");
|
||||||
try writer.writeAll(self.project.pipete_solution.items);
|
try writer.writeAll(self.project.pipete_solution.items);
|
||||||
try writer.writeAll("\n");
|
try writer.writeAll("\n");
|
||||||
|
try writer.writeAll("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{ // Note
|
||||||
try writer.writeAll("Note:\n");
|
try writer.writeAll("Note:\n");
|
||||||
try writer.writeAll(self.project.notes.items);
|
try writer.writeAll(self.project.notes.items);
|
||||||
try writer.writeAll("\n");
|
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 {
|
pub fn tick(self: *App) !void {
|
||||||
@ -1940,6 +1987,9 @@ fn startCollection(self: *App) !void {
|
|||||||
const channel_name = utils.getBoundedStringZ(&channel.name);
|
const channel_name = utils.getBoundedStringZ(&channel.name);
|
||||||
const channel_type = NIDaq.getChannelType(channel_name) orelse continue;
|
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) {
|
if (channel_type == .analog_input) {
|
||||||
const allowed_sample_values = channel.allowed_sample_values orelse continue;
|
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.setContinousSampleRate(.{ .sample_rate = sample_rate });
|
||||||
|
|
||||||
try task.start();
|
try task.start();
|
||||||
|
Loading…
Reference in New Issue
Block a user