Skip to content

Commit

Permalink
Merge pull request #66 from paulsengroup/improve-zoomify
Browse files Browse the repository at this point in the history
Improve hictk zoomify
  • Loading branch information
robomics authored Sep 28, 2023
2 parents 4d6ef97 + 4776823 commit c969111
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/hictk/cli/cli_dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void Cli::make_dump_subcommand() {
void Cli::validate_dump_subcommand() const {
assert(_cli.get_subcommand("dump")->parsed());

[[maybe_unused]] std::vector<std::string> warnings;
std::vector<std::string> warnings;
std::vector<std::string> errors;
const auto& c = std::get<DumpConfig>(_config);

Expand Down
73 changes: 70 additions & 3 deletions src/hictk/cli/cli_zoomify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,23 @@ void Cli::make_zoomify_subcommand() {
sc.add_option(
"--resolutions",
c.resolutions,
"One or more resolution to be used for coarsening.")
->required(true);
"One or more resolution to be used for coarsening.");

sc.add_flag(
"--copy-base-resolution,!--no-copy-base-resolution",
c.copy_base_resolution,
"Copy the base resolution to the output file.");

sc.add_flag(
"--nice-steps,!--pow2-steps",
c.nice_resolution_steps,
"Use nice or power of two steps to automatically generate the list of resolutions.\n"
"Example:\n"
"Base resolution: 1000\n"
"Pow2: 1000, 2000, 4000, 8000...\n"
"Nice: 1000, 2000, 5000, 10000...\n")
->default_str("--nice-steps");

sc.add_option(
"-v,--verbosity",
c.verbosity,
Expand Down Expand Up @@ -102,6 +111,7 @@ static std::vector<std::uint32_t> detect_invalid_resolutions(
void Cli::validate_zoomify_subcommand() const {
assert(_cli.get_subcommand("zoomify")->parsed());

std::vector<std::string> warnings;
std::vector<std::string> errors;
const auto& c = std::get<ZoomifyConfig>(_config);

Expand All @@ -126,6 +136,19 @@ void Cli::validate_zoomify_subcommand() const {
fmt::join(invalid, "\n - "), clr.bin_size()));
}

const auto* sc = _cli.get_subcommand("zoomify");
const auto nice_or_pow2_steps_parsed =
!sc->get_option("--nice-steps")->empty() || !sc->get_option("--pow2-steps")->empty();
if (!c.resolutions.empty() && nice_or_pow2_steps_parsed) {
warnings.emplace_back(
"--nice-steps and --pow2-steps are ignored when resolutions are explicitly set with "
"--resolutions.");
}

for (const auto& w : warnings) {
SPDLOG_WARN(FMT_STRING("{}"), w);
}

if (!errors.empty()) {
throw std::runtime_error(
fmt::format(FMT_STRING("the following error(s) where encountered while validating CLI "
Expand All @@ -134,6 +157,45 @@ void Cli::validate_zoomify_subcommand() const {
}
}

static std::vector<std::uint32_t> generate_resolutions_pow2(
std::uint32_t base_resolution, std::uint32_t upper_bound = 10'000'000) {
assert(base_resolution != 0);
std::vector<std::uint32_t> resolutions{base_resolution};

for (auto res = resolutions.back(); res * 2 <= upper_bound; res = resolutions.back()) {
resolutions.push_back(res * 2);
}

return resolutions;
}

static std::vector<std::uint32_t> generate_resolutions_nice(
std::uint32_t base_resolution, std::uint32_t upper_bound = 10'000'000) {
assert(base_resolution != 0);
std::vector<std::uint32_t> resolutions{base_resolution};

while (resolutions.back() * 2 <= upper_bound) {
const auto res = resolutions.back();

if (res * 2 > upper_bound) {
break;
}
resolutions.push_back(res * 2);

if (res * 5 > upper_bound) {
break;
}
resolutions.push_back(res * 5);

if (res * 10 > upper_bound) {
break;
}
resolutions.push_back(res * 10);
}

return resolutions;
}

void Cli::transform_args_zoomify_subcommand() {
auto& c = std::get<ZoomifyConfig>(_config);

Expand All @@ -146,7 +208,12 @@ void Cli::transform_args_zoomify_subcommand() {
c.output_path = std::filesystem::path(clr.path()).replace_extension(".mcool").string();
}

std::sort(c.resolutions.begin(), c.resolutions.end());
if (c.resolutions.empty()) {
c.resolutions = c.nice_resolution_steps ? generate_resolutions_nice(clr.bin_size())
: generate_resolutions_pow2(clr.bin_size());
} else {
std::sort(c.resolutions.begin(), c.resolutions.end());
}

if (c.resolutions.front() != clr.bin_size()) {
c.resolutions.insert(c.resolutions.begin(), clr.bin_size());
Expand Down
1 change: 1 addition & 0 deletions src/hictk/include/hictk/tools/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ struct ZoomifyConfig {

std::vector<std::uint32_t> resolutions{};
bool copy_base_resolution{true};
bool nice_resolution_steps{true};

bool force{false};
std::uint8_t verbosity{4};
Expand Down
3 changes: 1 addition & 2 deletions test/scripts/hictk_zoomify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ trap 'rm -rf -- "$outdir"' EXIT

"$hictk_bin" zoomify \
"$ref_cooler::/resolutions/${resolutions[0]}" \
"$outdir/out.mcool" \
--resolutions "${resolutions[@]}"
"$outdir/out.mcool"

for res in "${resolutions[@]}"; do
if ! compare_coolers \
Expand Down

0 comments on commit c969111

Please sign in to comment.