1 /**
2     This is the `showInsertions` command of `dentist`.
3 
4     Copyright: © 2018 Arne Ludwig <arne.ludwig@posteo.de>
5     License: Subject to the terms of the MIT license, as written in the
6              included LICENSE file.
7     Authors: Arne Ludwig <arne.ludwig@posteo.de>
8 */
9 module dentist.commands.showInsertions;
10 
11 import dentist.common.binio : InsertionDb;
12 import dentist.util.log;
13 import std.algorithm : map, max;
14 import std.array : array;
15 import std.file : getSize;
16 import std.math : log10, lrint, FloatingPointControl;
17 import std.stdio : stderr, writefln, writeln;
18 import std.typecons : tuple;
19 import vibe.data.json :
20     serializeToJsonString,
21     toJson = serializeToJson,
22     toJsonString = serializeToPrettyJson;
23 
24 /// Execute the `showInsertions` command with `options`.
25 void execute(Options)(in Options options)
26 {
27     size_t totalDbSize = options.insertionsFile.getSize();
28     auto insertionDb = InsertionDb.parse(options.insertionsFile);
29     if (!shouldLog(LogLevel.debug_))
30         insertionDb.releaseDb();
31 
32     auto stats = Stats(
33         totalDbSize,
34         insertionDb.insertions.length,
35         insertionDb.compressedBaseQuads.length,
36         insertionDb.spliceSites.length,
37     );
38 
39     if (options.useJson)
40         writeln(stats.toJsonString);
41     else
42         writeTabular(stats);
43 
44     if (shouldLog(LogLevel.debug_))
45     {
46         foreach (join; insertionDb[])
47         {
48             stderr.writeln(serializeToJsonString([
49                 "start": join.start.toJson,
50                 "end": join.end.toJson,
51                 "payload": [
52                     "sequence": join.payload.sequence.to!string.toJson,
53                     "contigLength": join.payload.contigLength.toJson,
54                     "spliceSites": join.payload.spliceSites.toJson,
55                 ].toJson,
56             ]));
57         }
58     }
59 }
60 
61 struct Stats
62 {
63     size_t totalDbSize;
64     size_t numInsertions;
65     size_t numCompressedBaseQuads;
66     size_t numSpliceSites;
67 
68     size_t columnWidth() const nothrow
69     {
70         FloatingPointControl fpCtrl;
71         fpCtrl.rounding = FloatingPointControl.roundUp;
72         auto numWidth = lrint(log10(max(
73             totalDbSize,
74             numInsertions,
75             numCompressedBaseQuads,
76             numSpliceSites,
77         )));
78 
79         return numWidth;
80     }
81 }
82 
83 void writeTabular(Stats stats)
84 {
85     auto columnWidth = stats.columnWidth();
86 
87     writefln!"totalDbSize:            %*d bytes"(columnWidth, stats.totalDbSize);
88     writefln!"numInsertions:          %*d"(columnWidth, stats.numInsertions);
89     writefln!"numCompressedBaseQuads: %*d"(columnWidth, stats.numCompressedBaseQuads);
90     writefln!"numSpliceSites:         %*d"(columnWidth, stats.numSpliceSites);
91 }