diff --git a/docs/program.rst b/docs/program.rst index 7a939d9a..77735613 100644 --- a/docs/program.rst +++ b/docs/program.rst @@ -925,6 +925,11 @@ that atom is assigned one of possible positions and its occupancy is zeroed. .. literalinclude:: h-help.txt :language: console +To test the addition of hydrogen to a single chemical component +from a monomer library, run:: + + gemmi h --format=chemcomp -L+ XYZ.cif output.pdb + mondiff ======= diff --git a/prog/h.cpp b/prog/h.cpp index 9263e6a9..1e78704e 100644 --- a/prog/h.cpp +++ b/prog/h.cpp @@ -92,22 +92,25 @@ int GEMMI_MAIN(int argc, char **argv) { else if (p.options[RemoveH]) h_change = gemmi::HydrogenChange::Remove; - MonArguments mon_args; - if (h_change != gemmi::HydrogenChange::Remove) - mon_args = get_monomer_args(p.options); - - if (p.options[Verbose]) - std::printf("Reading coordinates from %s\n", input.c_str()); gemmi::CoorFormat input_format = coor_format_as_enum(p.options[FormatIn]); if (input_format == gemmi::CoorFormat::Unknown) input_format = gemmi::coor_format_from_ext_gz(input); gemmi::CoorFormat output_format = gemmi::coor_format_from_ext_gz(output); bool preserve_doc = (input_format == gemmi::CoorFormat::Mmcif && output_format == gemmi::CoorFormat::Mmcif); + + MonArguments mon_args; + if (h_change != gemmi::HydrogenChange::Remove) { + bool needs_monlib = input_format != gemmi::CoorFormat::ChemComp; + mon_args = get_monomer_args(p.options, needs_monlib); + } + + if (p.options[Verbose]) + std::printf("Reading coordinates from %s\n", input.c_str()); try { gemmi::Structure st; std::unique_ptr doc; - if (preserve_doc) + if (preserve_doc || mon_args.has_plus()) doc.reset(new cif::Document); st = gemmi::read_structure_gz(input, input_format, doc.get()); if (st.models.empty() || st.models[0].chains.empty()) { @@ -139,7 +142,7 @@ int GEMMI_MAIN(int argc, char **argv) { if (p.options[Verbose]) std::printf("Writing coordinates to %s\n", output.c_str()); gemmi::Ofstream os(output, &std::cout); - if (gemmi::coor_format_from_ext_gz(output) == gemmi::CoorFormat::Pdb) { + if (output_format == gemmi::CoorFormat::Pdb) { shorten_ccd_codes(st); gemmi::write_pdb(st, os.ref()); } else { diff --git a/prog/monlib_opt.cpp b/prog/monlib_opt.cpp index fff52283..6f36b25c 100644 --- a/prog/monlib_opt.cpp +++ b/prog/monlib_opt.cpp @@ -22,13 +22,16 @@ const option::Descriptor MonLibUsage[] = { "\nExample 2: -L@ -L file.cif order: ML, file.cif" } }; -MonArguments get_monomer_args(const std::vector& options) { +MonArguments get_monomer_args(const std::vector& options, bool needs_monlib) { MonArguments args; const option::Option* mon = options[Monomers]; args.monomer_dir = mon ? mon->arg : std::getenv("CLIBD_MON"); if (args.monomer_dir == nullptr || args.monomer_dir[0] == '\0') { - fprintf(stderr, "Set $CLIBD_MON or use option --monomers.\n"); - std::exit(1); + if (needs_monlib) { + fprintf(stderr, "Set $CLIBD_MON or use option --monomers.\n"); + std::exit(1); + } + args.monomer_dir = nullptr; } args.libin = options[Libin]; args.verbose = options[Verbose].count(); @@ -68,9 +71,11 @@ void read_monomer_lib_and_user_files(gemmi::MonLib& monlib, putc('\n', stderr); } } - if (args.verbose) - fprintf(stderr, "Reading monomer library...\n"); - monlib.read_monomer_lib(args.monomer_dir, wanted, {&gemmi::Logger::to_stderr}); + if (args.monomer_dir) { + if (args.verbose) + fprintf(stderr, "Reading monomer library...\n"); + monlib.read_monomer_lib(args.monomer_dir, wanted, {&gemmi::Logger::to_stderr}); + } auto is_found = [&](const std::string& s) { return monlib.monomers.count(s); }; gemmi::vector_remove_if(wanted, is_found); if (libin) { diff --git a/prog/monlib_opt.h b/prog/monlib_opt.h index 1a246e12..f36ce4b2 100644 --- a/prog/monlib_opt.h +++ b/prog/monlib_opt.h @@ -13,10 +13,18 @@ struct MonArguments { const char* monomer_dir; const option::Option* libin; int verbose; + + bool has_plus() const { + for (auto it = libin; it; it = it->next()) + if (it->arg[0] == '+' && it->arg[1] == '\0') + return true; + return false; + } }; + // Exits w/ error if monomer dir is not specified (--monomers or $CLIBD_MON) -MonArguments get_monomer_args(const std::vector& options); +MonArguments get_monomer_args(const std::vector& options, bool needs_monlib=true); // Read monomer library and user-provided cif files according to args. // st_doc is used if we read monomer blocks from coordinate mmCIF.