Skip to content

Commit

Permalink
v1.1.1 Added .pdf and .svg to snapshot command. Simplified pdf/png sa…
Browse files Browse the repository at this point in the history
…ving from CLI
  • Loading branch information
kcleal committed Oct 3, 2024
1 parent 8551006 commit 71cd769
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
pull_request:

env:
version: 1.1.0
version: 1.1.1

jobs:
mingw:
Expand Down
1 change: 0 additions & 1 deletion deps/build_skia.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ if [ "$OS" = "Darwin" ]; then
echo "SDK_PATH ${SDK_PATH}"
EXTRA_CFLAGS=$(echo "$EXTRA_CFLAGS" | sed 's/\]$//')
EXTRA_CFLAGS+=", \"-mmacosx-version-min=10.15\", \"-isysroot\", \"${SDK_PATH}\"]"

EXTRA_LDFLAGS=$(echo "$EXTRA_LDFLAGS" | sed 's/\]$//')
EXTRA_LDFLAGS+=", \"-mmacosx-version-min=10.15\", \"-isysroot\", \"${SDK_PATH}\"]"

Expand Down
2 changes: 1 addition & 1 deletion deps/gw.desktop
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[Desktop Entry]
Encoding=UTF-8
Version=1.1.0
Version=1.1.1
Type=Application
Terminal=true
Exec=bash -c "/usr/bin/gw"
Expand Down
42 changes: 23 additions & 19 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void print_banner() {
}

// note to developer - update version in workflows/main.yml, menu.cpp, term_out.cpp, and deps/gw.desktop, and installers .md in docs
const char GW_VERSION [7] = "1.1.0";
const char GW_VERSION [7] = "1.1.1";


bool str_is_number(const std::string &s) {
Expand Down Expand Up @@ -736,28 +736,32 @@ int main(int argc, char *argv[]) {

plotter.opts.theme.setAlphas();

if (program.is_used("--fmt") && (program.get<std::string>("--fmt") == "pdf" || program.get<std::string>("--fmt") == "svg" )) {
std::string format_str = program.get<std::string>("--fmt");
std::filesystem::path fname;
std::filesystem::path out_path;
std::string format_str = ".png";
if (program.is_used("--file")) {
fname = program.get<std::string>("--file");
format_str = fname.extension().generic_string();
} else if (program.is_used("--fmt") && program.get<std::string>("--fmt") != "png") {
format_str = "." + program.get<std::string>("--fmt");
}

if (format_str != ".png") {
if (regions.empty()) {
std::cerr << "Error: --fmt is only supported by providing a --region\n";
std::exit(-1);
}

std::filesystem::path fname;
std::filesystem::path out_path;

if (program.is_used("--file")) {
fname = program.get<std::string>("--file");
out_path = fname;
} else {
if (outdir.empty()) {
if (fname.empty()) {
if (fname.empty()) {
std::cerr << "Error: please provide an output directory using --outdir, or direct to --file\n";
std::exit(-1);
}
fname = regions[0].chrom + "_" + std::to_string(regions[0].start) + "_" +
std::to_string(regions[0].end) + "." + format_str;
out_path = outdir / fname;
std::to_string(regions[0].end) + format_str;

}
out_path = outdir / fname;

#if defined(_WIN32) || defined(_WIN64)
const wchar_t* outp = out_path.c_str();
Expand All @@ -769,12 +773,12 @@ int main(int argc, char *argv[]) {
#endif
SkDynamicMemoryWStream buffer;

if (format_str == "pdf") {
if (format_str == ".pdf") {
auto pdfDocument = SkPDF::MakeDocument(&buffer);
SkCanvas *pageCanvas = pdfDocument->beginPage(iopts.dimensions.x, iopts.dimensions.y);
plotter.fb_width = iopts.dimensions.x;
plotter.fb_height = iopts.dimensions.y;
plotter.setRasterSize(plotter.fb_width, plotter.fb_height);
plotter.setImageSize(plotter.fb_width, plotter.fb_height);
if (!extra_commands.empty()) {
for (const auto& command: extra_commands) {
plotter.inputText = command;
Expand All @@ -787,7 +791,7 @@ int main(int argc, char *argv[]) {
} else {
plotter.fb_width = iopts.dimensions.x;
plotter.fb_height = iopts.dimensions.y;
plotter.setRasterSize(plotter.fb_width, plotter.fb_height);
plotter.setImageSize(plotter.fb_width, plotter.fb_height);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(iopts.dimensions.x, iopts.dimensions.y));
if (!extra_commands.empty()) {
Expand All @@ -810,7 +814,7 @@ int main(int argc, char *argv[]) {
// Plot a png image, either of target region or whole chromosome
sk_sp<SkImage> img;
if (!regions.empty()) { // plot target regions
plotter.setRasterSize(iopts.dimensions.x, iopts.dimensions.y);
plotter.setImageSize(iopts.dimensions.x, iopts.dimensions.y);
sk_sp<SkSurface> rasterSurface = SkSurface::MakeRasterN32Premul(iopts.dimensions.x,
iopts.dimensions.y);
SkCanvas *canvas = rasterSurface->getCanvas();
Expand Down Expand Up @@ -864,7 +868,7 @@ int main(int argc, char *argv[]) {
for (int i = 0; i < iopts.threads; ++i) {
auto *m = new Manager::GwPlot(genome, bam_paths, iopts, regions, tracks);
m->opts.theme.setAlphas();
m->setRasterSize(iopts.dimensions.x, iopts.dimensions.y);
m->setImageSize(iopts.dimensions.x, iopts.dimensions.y);
m->opts.threads = 1;
m->gap = 0;
m->drawLocation = false;
Expand Down Expand Up @@ -984,7 +988,7 @@ int main(int argc, char *argv[]) {
for (int i = 0; i < iopts.threads; ++i) {
auto *m = new Manager::GwPlot(genome, bam_paths, iopts, regions, tracks);
m->opts.theme.setAlphas();
m->setRasterSize(iopts.dimensions.x, iopts.dimensions.y);
m->setImageSize(iopts.dimensions.x, iopts.dimensions.y);
m->opts.threads = 1;
for (auto &s: filters) {
m->addFilter(s);
Expand Down
2 changes: 1 addition & 1 deletion src/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ namespace Menu {

if (opts.control_level.empty()) {
if (opts.menu_table == Themes::MenuTable::MAIN) {
tip = opts.ini_path + " v1.1.0";
tip = opts.ini_path + " v1.1.1";
}
else if (opts.menu_table == Themes::MenuTable::GENOMES) { tip = "Use ENTER key to select genome, or RIGHT_ARROW key to edit path"; }
else if (opts.menu_table == Themes::MenuTable::SHIFT_KEYMAP) { tip = "Change characters selected when using shift+key"; }
Expand Down
13 changes: 13 additions & 0 deletions src/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ namespace Parse {
Parser(std::ostream& errOutput);
~Parser() = default;

// Copy assignment operator
Parser& operator=(const Parser& other) {
if (this != &other) {
orBlock = other.orBlock;
filter_str = other.filter_str;
opMap = other.opMap;
permit = other.permit;
evaluations_block = other.evaluations_block;
targetIndexes = other.targetIndexes;
}
return *this;
}

bool orBlock;
std::string filter_str;
ankerl::unordered_dense::map< std::string, Property> opMap;
Expand Down
69 changes: 58 additions & 11 deletions src/plot_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@
#include "themes.h"


#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/core/SkDocument.h"
#include "include/docs/SkPDFDocument.h"
#include "include/core/SkStream.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkPicture.h"
#include "include/svg/SkSVGCanvas.h"


/* Notes for adding new commands:
* 1. Make a new function, accepting a pointer to a GwPlot instance and any other args
* 2. Add function to run_command_map below
Expand Down Expand Up @@ -785,7 +795,7 @@ namespace Commands {
}
std::string fname;
p->currentVarTrack = &p->variantTracks[p->variantFileSelection];
if (parts.size() == 1) {
if (parts.size() == 1) { // Choose filename automatically based on region
if (p->mode == Manager::Show::SINGLE) {
std::filesystem::path fname_path = Utils::makeFilenameFromRegions(p->regions);
#if defined(_WIN32) || defined(_WIN64)
Expand All @@ -802,6 +812,7 @@ namespace Commands {
}
} else {
std::string nameFormat = parts[1];
// try and parse information from vcf record e.g. {pos}.png
if (p->currentVarTrack != nullptr && p->currentVarTrack->type == HGW::TrackType::VCF && p->mode == Manager::Show::SINGLE) {
if (p->mouseOverTileIndex == -1 || p->currentVarTrack->blockStart + p->mouseOverTileIndex > (int) p->currentVarTrack->multiLabels.size()) {
return Err::SILENT;
Expand Down Expand Up @@ -831,10 +842,50 @@ namespace Commands {
out << termcolor::red << "Error:" << termcolor::reset << " path not found " << out_path.parent_path() << std::endl;
return Err::INVALID_PATH;
} else {
if (!p->imageCacheQueue.empty()) {
Manager::imagePngToFile(p->imageCacheQueue.back().second, out_path.string());
Term::clearLine(out);
if (out_path.extension() == ".png") {
if (!p->imageCacheQueue.empty()) {
Manager::imagePngToFile(p->imageCacheQueue.back().second, out_path.string());
Term::clearLine(out);
out << "\rSaved to " << out_path << std::endl;
}
} else if (out_path.extension() == ".pdf" || out_path.extension() == ".svg") {
std::string format_str = (out_path.extension() == ".pdf") ? "pdf" : "svg";

#if defined(_WIN32) || defined(_WIN64)
const wchar_t* outp = out_path.c_str();
std::wstring pw(outp);
std::string outp_str(pw.begin(), pw.end());
SkFILEWStream out(outp_str.c_str());
#else
SkFILEWStream out_stream(out_path.c_str());
#endif
SkDynamicMemoryWStream buffer;

for (auto &cl: p->collections) {
cl.skipDrawingCoverage = false;
cl.skipDrawingReads = false;
}
if (format_str == "pdf") {
auto pdfDocument = SkPDF::MakeDocument(&buffer);
SkCanvas *pageCanvas = pdfDocument->beginPage(p->fb_width, p->fb_height);
p->runDrawOnCanvas(pageCanvas);
pdfDocument->close();
buffer.writeToStream(&out_stream);
} else {
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(SkRect::MakeWH(p->fb_width, p->fb_height));
p->runDrawOnCanvas(canvas);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(SkRect::MakeWH(p->fb_width, p->fb_height), &out_stream);
if (svgCanvas) {
picture->playback(svgCanvas.get());
svgCanvas->flush();
};
}
out << "\rSaved to " << out_path << std::endl;
} else {
out << termcolor::red << "Error:" << termcolor::reset << " extension not supported " << out_path.extension() << std::endl;
return Err::OPTION_NOT_SUPPORTED;
}
}
return Err::NONE;
Expand Down Expand Up @@ -1049,16 +1100,12 @@ namespace Commands {
} else {
return Err::OPTION_NOT_UNDERSTOOD;
}
}
// Err snapshot(Plot* p, std::vector<std::string> parts, std::ostream& out) {
else if (Utils::endsWith(command, ".png")) {
} else if (Utils::endsWith(command, ".png") || Utils::endsWith(command, ".pdf") || Utils::endsWith(command, ".svg")) {
return snapshot(p, parts, out);
}
else if (Utils::endsWith(parts.back(), ".ini")) {
} else if (Utils::endsWith(parts.back(), ".ini")) {
out << "Saved session: " << parts.back() << std::endl;
p->saveSession(parts.back());
}
else if (Utils::endsWith(parts.back(), ".tsv") || (Utils::endsWith(parts.back(), ".txt"))) {
} else if (Utils::endsWith(parts.back(), ".tsv") || (Utils::endsWith(parts.back(), ".txt"))) {
out << "Output label file set as: " << parts.back() << std::endl;
p->setOutLabelFile(parts.back());
p->saveLabels();
Expand Down
49 changes: 29 additions & 20 deletions src/plot_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,14 @@ namespace Manager {
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
std::cerr << "Error: failed to initialize GLAD GL\n";
}
if (GLAD_GL_VERSION_4_1) {
std::cerr << "OpenGL 4.1 is supported\n";
} else {
std::cerr << "OpenGL 4.1 is not supported\n";
std::cerr << "OpenGL 3.3 is " << ((GLAD_GL_VERSION_3_3) ? "" : "not ") << "supported\n";
std::cerr << "OpenGL 2.1 is " << ((GLAD_GL_VERSION_2_1) ? "" : "not ") << "supported\n";
if (debug) {
if (GLAD_GL_VERSION_4_1) {
std::cerr << "OpenGL 4.1 is supported\n";
} else {
std::cerr << "OpenGL 4.1 is not supported\n";
std::cerr << "OpenGL 3.3 is " << ((GLAD_GL_VERSION_3_3) ? "" : "not ") << "supported\n";
std::cerr << "OpenGL 2.1 is " << ((GLAD_GL_VERSION_2_1) ? "" : "not ") << "supported\n";
}
}
}
if (debug) {
Expand Down Expand Up @@ -986,7 +988,7 @@ namespace Manager {

}

void GwPlot::setRasterSize(int width, int height) {
void GwPlot::setImageSize(int width, int height) {
// monitorScale = 1;
fb_width = width;
fb_height = height;
Expand Down Expand Up @@ -1669,21 +1671,30 @@ namespace Manager {
}
canvas->drawPaint(opts.theme.bgPaint);
SkRect clip;
for (auto &cl: collections) {

canvas->save();

if (cl.bamIdx == 0) { // cover the ref too
clip.setXYWH(cl.xOffset, 0, cl.regionPixels, cl.yOffset + trackY + covY + refSpace);
} else {
clip.setXYWH(cl.xOffset, cl.yOffset - covY, cl.regionPixels, cl.yOffset + trackY + covY);
for (auto &cl: collections) {
if (cl.skipDrawingCoverage && cl.skipDrawingReads) { // keep read and coverage area
continue;
}
canvas->clipRect(clip, false);
canvas->save();
// for now cl.skipDrawingCoverage and cl.skipDrawingReads are almost always the same
if ((!cl.skipDrawingCoverage && !cl.skipDrawingReads) || imageCacheQueue.empty()) {
clip.setXYWH(cl.xOffset, cl.yOffset - covY, cl.regionPixels, trackY + covY - gap);
canvas->clipRect(clip, false);
} else if (cl.skipDrawingCoverage) {
clip.setXYWH(cl.xOffset, cl.yOffset, cl.regionPixels, cl.yPixels);
canvas->clipRect(clip, false);
} else if (cl.skipDrawingReads){
clip.setXYWH(cl.xOffset, cl.yOffset - covY, cl.regionPixels, covY);
canvas->clipRect(clip, false);
} // else no clip
canvas->drawPaint(opts.theme.bgPaint);

if (!cl.skipDrawingReads) {
if (!cl.skipDrawingReads && !bams.empty()) {

if (cl.regionLen >= opts.low_memory && !bams.empty() && opts.link_op == 0) { // low memory mode will be used
if (cl.regionLen >= opts.low_memory) {
assert (opts.link_op == 0 && regions[cl.regionIdx].getSortOption() == SortType::NONE);
// low memory mode will be used
cl.clear();
if (opts.threads == 1) {
HGW::iterDraw(cl, bams[cl.bamIdx], headers[cl.bamIdx], indexes[cl.bamIdx],
Expand All @@ -1702,9 +1713,8 @@ namespace Manager {
}
}
canvas->restore();

// Drawing::drawCollection(opts, cl, canvas, trackY, yScaling, fonts, opts.link_op, refSpace, pointSlop, textDrop, pH, monitorScale);
}

if (opts.max_coverage) {
Drawing::drawCoverage(opts, collections, canvas, fonts, covY, refSpace, gap);
}
Expand All @@ -1720,7 +1730,6 @@ namespace Manager {

void GwPlot::runDrawNoBufferOnCanvas(SkCanvas* canvas) {
// std::chrono::high_resolution_clock::time_point initial = std::chrono::high_resolution_clock::now();

if (bams.empty()) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/plot_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ namespace Manager {

void setGlfwFrameBufferSize();

void setRasterSize(int width, int height);
void setImageSize(int width, int height);

int makeRasterSurface();

Expand Down
Loading

0 comments on commit 71cd769

Please sign in to comment.