diff --git a/docs/Writerside/images/example-snfg.png b/docs/Writerside/images/example-snfg.png new file mode 100644 index 0000000..46cd98e Binary files /dev/null and b/docs/Writerside/images/example-snfg.png differ diff --git a/docs/Writerside/topics/Automated-Glycan-Building.topic b/docs/Writerside/topics/Automated-Glycan-Building.topic index 2ff953d..a362029 100644 --- a/docs/Writerside/topics/Automated-Glycan-Building.topic +++ b/docs/Writerside/topics/Automated-Glycan-Building.topic @@ -30,9 +30,9 @@

Advanced Example:

- Attempt to build N-glycans into ABCD.cif with structure factors. + Attempt to build O-mannoses into ABCD.cif with structure factors. - sails -pdbin ABCD.cif -mtzin ABCD-sf.cif.gz -cycles 4 -colin-fo F,SIGF -nglycan + sails -pdbin ABCD.cif -mtzin ABCD-sf.cif.gz -type o-mannosylate -cycles 1 -colin-fo F,SIGF @@ -51,30 +51,33 @@ Path to output CIF file. -

Default: sails-model-out.cif

+

Default: sails-model-out.cif

Path to output MTZ file. -

Default: sails-refln-out.mtz

+

Default: sails-refln-out.mtz

Path to output MTZ file. -

Default: sails-log.json

+

Default: sails-log.json

Number of internal cycles to run. -

Default: 2

+

Default: 2

- - Build N-glycans into the given structure -

Default Option

+ + Type of glycosylation +

Options:

+ +
  • n-glycosylate
  • +
  • c-glycosylate
  • +
  • o-mannosylate
  • +
    +

    Default: n-glycosylate

    - - Build C-glycans (tryptophan mannosylation) into the given structure - Comma separated SF observations and associated uncertainty. -

    Default: FP,SIGFP

    +

    Default: FP,SIGFP

    Comma separated SF weight and associated phase. diff --git a/docs/Writerside/topics/Generate-SNFG-Diagrams.topic b/docs/Writerside/topics/Generate-SNFG-Diagrams.topic index 92029c2..6c056ce 100644 --- a/docs/Writerside/topics/Generate-SNFG-Diagrams.topic +++ b/docs/Writerside/topics/Generate-SNFG-Diagrams.topic @@ -6,10 +6,15 @@ title="Generate SNFG Diagrams" id="Generate-SNFG-Diagrams" help-id="Generate-SNFG-Diagrams">

    - Sails provides a fast utility tool to generate SNFG diagrams using Sails' internal diagram engine. A specific + Sails provides a fast utility tool to generate Symbol Nomeclature for Glycans Diagram (SNFG) diagrams using Sails' internal diagram engine. A specific site can be specified with -chain and -seqid parameters, or, all the detectable SNFGs will be generated.

    +

    + Example SNFG Diagram for a high mannose glycan + Symbol Nomeclature for Glycans Diagram for a high mannose structure +

    +

    Syntax:

    @@ -27,6 +32,7 @@ sails-snfg -model built.cif --all -snfgout snfgs
    +

    Describe what each option is used for:

    diff --git a/package/src/bindings/python_sails.cpp b/package/src/bindings/python_sails.cpp index 0ce3660..5741c94 100644 --- a/package/src/bindings/python_sails.cpp +++ b/package/src/bindings/python_sails.cpp @@ -147,6 +147,8 @@ NB_MODULE(sails_module, m) { m.def("n_glycosylate_from_objects", &n_glycosylate, "structure"_a, "mtz"_a, "cycles"_a, "resource_dir"_a, "verbose"_a); m.def("c_glycosylate_from_objects", &c_glycosylate, "structure"_a, "mtz"_a, "cycles"_a, "resource_dir"_a, "verbose"_a); + m.def("o_mannosylate_from_objects", &o_mannosylate, "structure"_a, "mtz"_a, "cycles"_a, "resource_dir"_a, "verbose"_a); + m.def("test_snfg", &test); m.def("get_snfg", &get_snfg, "chain"_a, "seqid"_a , "structure"_a, "resource_dir"_a); diff --git a/package/src/cpp/sails-density.cpp b/package/src/cpp/sails-density.cpp index 9d23d86..6e14e6d 100644 --- a/package/src/cpp/sails-density.cpp +++ b/package/src/cpp/sails-density.cpp @@ -170,7 +170,7 @@ void Sails::Density::recalculate_map(gemmi::Structure &structure) { new_mtz.add_column("FWT", 'F', -1, -1, true); new_mtz.add_column("PHWT", 'P', -1, -1, true); new_mtz.add_column("DELFWT", 'F', -1, -1, true); - new_mtz.add_column("PHDELWT", 'P', -1, -1, true);; + new_mtz.add_column("PHDELWT", 'P', -1, -1, true); new_mtz.set_data(recalculated_data.data(), recalculated_data.size()); new_mtz.ensure_asu(); @@ -217,7 +217,7 @@ void Sails::Density::calculate_po_pc_map(gemmi::Structure &structure) { new_mtz.add_dataset("SAILS"); new_mtz.add_base(); new_mtz.add_column("FDIFFCALC", 'F', -1, -1, true); - new_mtz.add_column("PDIFFCALC", 'P', -1, -1, true);; + new_mtz.add_column("PDIFFCALC", 'P', -1, -1, true); new_mtz.set_data(recalculated_data.data(), recalculated_data.size()); new_mtz.ensure_asu(); diff --git a/package/src/cpp/sails-linkage.cpp b/package/src/cpp/sails-linkage.cpp index 6942222..2d283e0 100644 --- a/package/src/cpp/sails-linkage.cpp +++ b/package/src/cpp/sails-linkage.cpp @@ -134,7 +134,6 @@ void Sails::Model::remove_leaving_atom(Sails::LinkageData &data, gemmi::Residue void Sails::Model::add_sugar_to_structure(const Sugar *terminal_sugar, SuperpositionResult &favoured_addition, ChainType &chain_type) { int chain_idx = terminal_sugar->site.chain_idx; - int residue_idx = terminal_sugar->site.residue_idx; if (chain_type == protein) { const size_t last_chain_idx = structure->models[terminal_sugar->site.model_idx].chains.size(); @@ -142,7 +141,6 @@ void Sails::Model::add_sugar_to_structure(const Sugar *terminal_sugar, Superposi gemmi::Chain chain; chain.name = Utils::get_next_string( structure->models[terminal_sugar->site.model_idx].chains[last_chain_idx - 1].name); - residue_idx = -1; structure->models[terminal_sugar->site.model_idx].chains.emplace_back(chain); } @@ -220,8 +218,8 @@ std::optional Sails::Model::add_residue( auto library_monomer = get_monomer(data.acceptor, true); if (!library_monomer.has_value()) { throw std::runtime_error("Could not get required monomer, " - "ensure that CCP4 monomer library is sourced." - "If you have a local monomer library, ensure that you" + "ensure that CCP4 monomer library is sourced. " + "If you have a local monomer library, ensure that you " "have CLIBD set"); } auto reference_library_monomer = gemmi::Residue(library_monomer.value()); @@ -338,7 +336,7 @@ void Sails::Model::extend_if_possible(Density &density, bool debug, ChainType &c if (!opt_result.has_value()) { if (debug) print_rejection_log(); continue; - }; + } possible_additions[data.donor_number].emplace_back(opt_result.value()); diff --git a/package/src/cpp/sails-sequence.cpp b/package/src/cpp/sails-sequence.cpp index de41802..bd8ce35 100644 --- a/package/src/cpp/sails-sequence.cpp +++ b/package/src/cpp/sails-sequence.cpp @@ -4,14 +4,11 @@ #include "../include/sails-sequence.h" Sails::Glycosites Sails::find_n_glycosylation_sites(const gemmi::Structure &structure) { - std::vector glycosites; auto models = structure.children(); for (int model_idx = 0; model_idx < models.size(); model_idx++) { - auto chains = models[model_idx].children(); for (int chain_idx = 0; chain_idx < chains.size(); chain_idx++) { - auto residues = chains[chain_idx].children(); // if there are less than three residues, skip @@ -19,13 +16,13 @@ Sails::Glycosites Sails::find_n_glycosylation_sites(const gemmi::Structure &stru for (int residue_idx = 0; residue_idx < residues.size() - 2; residue_idx++) { char first = gemmi::find_tabulated_residue(residues[residue_idx].name).one_letter_code; - if (first != 'N') {continue;} + if (first != 'N') { continue; } char third = gemmi::find_tabulated_residue(residues[residue_idx + 2].name).one_letter_code; - if (third != 'S' && third != 'T') {continue;} + if (third != 'S' && third != 'T') { continue; } char second = gemmi::find_tabulated_residue(residues[residue_idx + 1].name).one_letter_code; - if (second == 'P') {continue;} + if (second == 'P') { continue; } glycosites.emplace_back(model_idx, chain_idx, residue_idx); } @@ -39,24 +36,46 @@ Sails::Glycosites Sails::find_c_glycosylation_sites(const gemmi::Structure &stru std::vector glycosites; auto models = structure.children(); for (int model_idx = 0; model_idx < models.size(); model_idx++) { - auto chains = models[model_idx].children(); for (int chain_idx = 0; chain_idx < chains.size(); chain_idx++) { - auto residues = chains[chain_idx].children(); // if there are less than three residues, skip if (residues.size() < 4) continue; for (int residue_idx = 0; residue_idx < residues.size() - 3; residue_idx++) { - char first = gemmi::find_tabulated_residue(residues[residue_idx].name).one_letter_code; - if (first != 'W') {continue;} + if (first != 'W') { continue; } char fourth = gemmi::find_tabulated_residue(residues[residue_idx + 3].name).one_letter_code; - if (fourth != 'W') {continue;} + if (fourth != 'W') { continue; } glycosites.emplace_back(model_idx, chain_idx, residue_idx); - glycosites.emplace_back(model_idx, chain_idx, residue_idx+3); + glycosites.emplace_back(model_idx, chain_idx, residue_idx + 3); + } + } + } + + return glycosites; +} + +Sails::Glycosites Sails::find_o_mannosylation_sites(const gemmi::Structure &structure, + std::map &solvent_accessibility_map) { + std::vector glycosites; + auto models = structure.children(); + for (int model_idx = 0; model_idx < models.size(); model_idx++) { + auto chains = models[model_idx].children(); + for (int chain_idx = 0; chain_idx < chains.size(); chain_idx++) { + auto residues = chains[chain_idx].children(); + // if there are less than three residues, skip + if (residues.size() < 4) continue; + for (int residue_idx = 0; residue_idx < residues.size() - 3; residue_idx++) { + std::string name = residues[residue_idx].name; + if (name != "SER" && name != "THR") continue; + Glycosite g = {model_idx, chain_idx, residue_idx}; + double solvent_accessibility = solvent_accessibility_map[g]; + if (solvent_accessibility > 10) { + glycosites.emplace_back(g); + } } } } diff --git a/package/src/cpp/sails-telemetry.cpp b/package/src/cpp/sails-telemetry.cpp index 4d93fe8..a8c70d5 100644 --- a/package/src/cpp/sails-telemetry.cpp +++ b/package/src/cpp/sails-telemetry.cpp @@ -65,13 +65,4 @@ std::optional Sails::Telemetry::format_log(gemmi::Structure *struct return stream.str(); } return std::nullopt; - - // for (const auto &[cycle, entries]: log) { - // std::cout << "Cycle " << cycle << "\n"; - // for (const auto &entry: entries) { - // std::cout << "Added " << entry.residue_id << "\t" << entry.rscc_score << "\t" << entry.rsr_score << "\t" - // << entry.dds_score << "\n"; - // } - // std::cout << std::endl; - // } } diff --git a/package/src/cpp/sails-topology.cpp b/package/src/cpp/sails-topology.cpp index af4932a..7a38fc9 100644 --- a/package/src/cpp/sails-topology.cpp +++ b/package/src/cpp/sails-topology.cpp @@ -105,7 +105,7 @@ void Sails::Topology::find_residue_near_donor(Glycosite &glycosite, Glycan &glyc // } // std::cout << std::endl; continue; - }; + } // Add the sugar, and then linkage // This is required to ensure the sugar objects live until the Glycan goes out of scope. diff --git a/package/src/cpp/sails.cpp b/package/src/cpp/sails.cpp index 7f6c12c..0e36327 100644 --- a/package/src/cpp/sails.cpp +++ b/package/src/cpp/sails.cpp @@ -19,6 +19,7 @@ #include #include #include +#include void print_rejection_dds(const Sails::Glycosite& s1, const Sails::Glycosite& s2, gemmi::Structure* structure, float score) { @@ -30,9 +31,10 @@ void print_removal_rscc(const gemmi::Residue& residue, float rscc) { std::cout << "Removing " << Sails::Utils::format_residue_key(&residue) << " because of low RSCC =" << rscc << std::endl; } -void remove_erroneous_sugars(gemmi::Structure *structure, Sails::Density *density, Sails::Glycan *glycan, bool debug) { - constexpr float rscc_threshold = 0.5; - constexpr float dds_threshold = 1.1; +void remove_erroneous_sugars(gemmi::Structure *structure, Sails::Density *density, Sails::Glycan *glycan, bool strict, + bool debug) { + const float rscc_threshold = strict ? 0.65: 0.5; + const float dds_threshold = strict ? 1.0: 1.1; std::vector to_remove; for (const auto &[fst, snd]: *glycan) { @@ -96,8 +98,8 @@ void check_spacegroup(gemmi::Mtz* mtz, gemmi::Structure* structure) { if (mtz->spacegroup_name.empty()) mtz->spacegroup_name = structure->spacegroup_hm; } -Sails::Output run_cycle(Sails::Glycosites& glycosites, gemmi::Structure &structure, Sails::MTZ &sails_mtz, int cycles, std::string & - resource_dir, bool verbose) { +Sails::Output run_cycle(Sails::Glycosites &glycosites, gemmi::Structure &structure, Sails::MTZ &sails_mtz, int cycles, + std::string &resource_dir, bool strict, bool verbose) { std::string data_file = resource_dir + "/data.json"; Sails::JSONLoader loader = {data_file}; @@ -153,7 +155,7 @@ Sails::Output run_cycle(Sails::Glycosites& glycosites, gemmi::Structure &structu // std::cout << "Attempting removal at " << Sails::Utils::format_residue_from_site(glycosite, &structure) << std::endl; Sails::Glycan old_glycan = glycan; - remove_erroneous_sugars(&structure, &density, &glycan, verbose); + remove_erroneous_sugars(&structure, &density, &glycan, strict, verbose); topology.set_structure(&structure); // need to update neighbor search after removing n residues Sails::Glycan new_glycan = topology.find_glycan_topology(glycosite); @@ -189,13 +191,21 @@ Sails::Output run_cycle(Sails::Glycosites& glycosites, gemmi::Structure &structu Sails::Output n_glycosylate(gemmi::Structure &structure, Sails::MTZ &sails_mtz, int cycles, std::string &resource_dir, bool verbose) { auto glycosites = Sails::find_n_glycosylation_sites(structure); - return run_cycle(glycosites, structure, sails_mtz, cycles, resource_dir, verbose); + return run_cycle(glycosites, structure, sails_mtz, cycles, resource_dir, false, verbose); } Sails::Output c_glycosylate(gemmi::Structure &structure, Sails::MTZ &sails_mtz, int cycles, std::string &resource_dir, bool verbose) { auto glycosites = Sails::find_c_glycosylation_sites(structure); - return run_cycle(glycosites, structure, sails_mtz, cycles, resource_dir, verbose); + return run_cycle(glycosites, structure, sails_mtz, cycles, resource_dir, false, verbose); +} + +Sails::Output o_mannosylate(gemmi::Structure &structure, Sails::MTZ &sails_mtz, int cycles, std::string &resource_dir, + bool verbose) { + Sails::SolventAccessibility sa = Sails::SolventAccessibility(&structure); + Sails::SolventAccessibility::SolventAccessibilityMap sa_map = sa.calculate_solvent_accessibility(); + auto glycosites = Sails::find_o_mannosylation_sites(structure, sa_map); + return run_cycle(glycosites, structure, sails_mtz, cycles, resource_dir, false, verbose); } std::string get_snfg(std::string chain, int seqid, gemmi::Structure& structure, std::string& resource_dir) { @@ -244,28 +254,26 @@ std::map get_all_snfgs(gemmi::Structure& structure, st } void test() { - const std::string path = "testing/test_data/5fji/5FJI.cif"; - const std::string mtz_path = "testing/test_data/5fji/5fji.mtz"; - + const std::string path = "testing/test_data/4ax7/4AX7_deglycosylated.cif"; + const std::string mtz_path = "testing/test_data/4ax7/4AX7.mtz"; + gemmi::Mtz mtz = gemmi::read_mtz_file(mtz_path); + auto smtz = Sails::form_sails_mtz(mtz, "FP", "SIGFP"); gemmi::Structure structure = gemmi::read_structure_file(path); std::string data_file = "package/src/sails/data/data.json"; Sails::JSONLoader loader = {data_file}; Sails::ResidueDatabase residue_database = loader.load_residue_database(); - auto snfg = Sails::SNFG(&structure, &residue_database); - Sails::Topology topology = {&structure, residue_database}; - auto glycosites = Sails::find_n_glycosylation_sites(structure); + Sails::Density density = Sails::Density(mtz); + density.load_hkl("FP", "SIGFP"); + density.recalculate_map(structure); - for (auto& site: glycosites) { - // auto site = glycosites[4]; - auto glycan = topology.find_glycan_topology(site); - if (glycan.empty()) continue; - std::string snfg_path = "snfgs/" + Sails::Utils::format_residue_from_site(site, &structure) + ".svg"; - std::ofstream f(snfg_path); - f << snfg.create_snfg(glycan, site); - f.close(); - } + +// auto o = find_o_mannosylation_sites(structure, sa_map); +// std::string a = "package/src/sails/data"; +// auto output = run_cycle(o, structure, smtz, 1, a, true, true); +// Sails::Utils::save_structure_to_file(output.structure, "o-mannose-strict.cif"); +// std::cout << output.log << std::endl; } // testbed diff --git a/package/src/include/sails-glycan.h b/package/src/include/sails-glycan.h index cac60ff..b5d50e7 100644 --- a/package/src/include/sails-glycan.h +++ b/package/src/include/sails-glycan.h @@ -43,7 +43,7 @@ namespace Sails { acceptor_atom(acceptor_atom) { std::string donor_number_s = {donor_atom[donor_atom.size()-1]}; - donor_number = std::stoi(donor_number_s); + donor_number = std::isdigit(donor_number_s[0]) ? std::stoi(donor_number_s): 1; } Sugar *donor_sugar; diff --git a/package/src/include/sails-sequence.h b/package/src/include/sails-sequence.h index ac3b68c..17f0229 100644 --- a/package/src/include/sails-sequence.h +++ b/package/src/include/sails-sequence.h @@ -41,6 +41,10 @@ namespace Sails { * If no C-glycosylation sites are found, an empty vector is returned. */ Glycosites find_c_glycosylation_sites(const gemmi::Structure &structure); + + + + Glycosites find_o_mannosylation_sites(const gemmi::Structure& structure, std::map& solvent_accessibility_map); } #endif //SAILS_SAILS_SEQUENCE_H diff --git a/package/src/include/sails-solvent.h b/package/src/include/sails-solvent.h index cbd6a5e..fd48988 100644 --- a/package/src/include/sails-solvent.h +++ b/package/src/include/sails-solvent.h @@ -57,7 +57,7 @@ namespace Sails { * * @return A map containing the solvent accessibility value for each glycosite. */ - std::map calculate_solvent_accessibility(); + [[nodiscard]] std::map calculate_solvent_accessibility(); /** * @brief Calculates the bounding box of the structure. diff --git a/package/src/sails/__init__.py b/package/src/sails/__init__.py index 127d44f..061e2a3 100644 --- a/package/src/sails/__init__.py +++ b/package/src/sails/__init__.py @@ -1,7 +1,7 @@ from .sails_module import (HKL, Reflection, Pair, Structure, Model, Chain, Residue, Atom, Position, Element, SeqId, - n_glycosylate_from_objects, c_glycosylate_from_objects, Cell, MTZ, GlycoSite, Dot, test_snfg, - get_snfg, get_all_snfgs) + n_glycosylate_from_objects, c_glycosylate_from_objects, o_mannosylate_from_objects, + Cell, MTZ, GlycoSite, Dot, test_snfg, get_snfg, get_all_snfgs) from .__version__ import __version__ -from .glycosylate import glycosylate +from .glycosylate import glycosylate, Type from .interface import extract_gemmi_mtz, extract_sails_mtz, extract_gemmi_structure, extract_sails_structure, \ get_sails_structure, get_sails_mtz diff --git a/package/src/sails/data/data.json b/package/src/sails/data/data.json index 3426d88..45f92d6 100644 --- a/package/src/sails/data/data.json +++ b/package/src/sails/data/data.json @@ -174,8 +174,41 @@ } ], "acceptorSets": [] + }, + { + "name": "SER", + "snfgShape": "square", + "snfgColour": "white", + "preferredDepths": [ + 0 + ], + "donorSets": [ + { + "atom1": "CA", + "atom2": "CB", + "atom3": "OG", + "identifier": 1 + } + ], + "acceptorSets": [] + }, + { + "name": "THR", + "snfgShape": "square", + "snfgColour": "white", + "preferredDepths": [ + 0 + ], + "donorSets": [ + { + "atom1": "CA", + "atom2": "CB", + "atom3": "OG1", + "identifier": 1 + } + ], + "acceptorSets": [] } - ], "linkages": [ { @@ -232,20 +265,74 @@ "clusters": [ { "angles": { - "alphaMean": 120, - "alphaStdDev": 10, - "betaMean": 115, - "betaStdDev": 10, - "gammaMean": 110, - "gammaStdDev": 10 + "alphaMean": 127.838, + "alphaStdDev": 5.582, + "betaMean": 109.84, + "betaStdDev": 5.582, + "gammaMean": 116.699, + "gammaStdDev": 2.541 + }, + "torsions": { + "phiMean": 116.884, + "phiStdDev": 25.889, + "psiMean": -176.651, + "psiStdDev": 11.025, + "omegaMean": 162.145, + "omegaStdDev": 35.401 + } + } + ] + }, + { + "donorResidue": "SER", + "acceptorResidue": "MAN", + "donorNumber": 1, + "acceptorNumber": 1, + "length": 1.4, + "clusters": [ + { + "angles": { + "alphaMean": 113.548, + "alphaStdDev": 5.876, + "betaMean": 111.95, + "betaStdDev": 5.876, + "gammaMean": 114.725, + "gammaStdDev": 1.774 + }, + "torsions": { + "phiMean": 72.866, + "phiStdDev": 28.094, + "psiMean": 175.3, + "psiStdDev": 33.92, + "omegaMean": 60.137, + "omegaStdDev": 10.249 + } + } + ] + }, + { + "donorResidue": "THR", + "acceptorResidue": "MAN", + "donorNumber": 1, + "acceptorNumber": 1, + "length": 1.4, + "clusters": [ + { + "angles": { + "alphaMean": 113.367, + "alphaStdDev": 6.634, + "betaMean": 111.89, + "betaStdDev": 6.634, + "gammaMean": 114.592, + "gammaStdDev": 2.038 }, "torsions": { - "phiMean": 130, - "phiStdDev": 15, - "psiMean": 180, - "psiStdDev": 15, - "omegaMean": 180, - "omegaStdDev": 15 + "phiMean": 86.251, + "phiStdDev": 27.802, + "psiMean": 130.215, + "psiStdDev": 25.722, + "omegaMean": 61.975, + "omegaStdDev": 11.282 } } ] diff --git a/package/src/sails/glycosylate.py b/package/src/sails/glycosylate.py index 8fc5e37..f9ba921 100644 --- a/package/src/sails/glycosylate.py +++ b/package/src/sails/glycosylate.py @@ -1,7 +1,9 @@ import argparse +import enum import logging from typing import Tuple, Callable, List -from sails import (interface, n_glycosylate_from_objects, c_glycosylate_from_objects, Dot, GlycoSite, __version__) +from sails import (interface, n_glycosylate_from_objects, c_glycosylate_from_objects, o_mannosylate_from_objects, Dot, + GlycoSite, __version__) import time import gemmi from pathlib import Path @@ -9,8 +11,37 @@ import importlib.resources +class Type(enum.IntEnum): + n_glycosylate = 1 + c_glycosylate = 2 + o_mannosylate = 3 + + def __str__(self): + return self.name + + @staticmethod + def from_string(s: str): + try: + return Type[s] + except KeyError: + raise ValueError("Invalid Type") + + +def map_type_to_function(type: Type): + if type == Type.n_glycosylate: + return n_glycosylate_from_objects + + if type == Type.c_glycosylate: + return c_glycosylate_from_objects + + if type == Type.o_mannosylate: + return o_mannosylate_from_objects + + raise TypeError("Type not found") + + def glycosylate(structure: gemmi.Structure | Path | str, mtz: gemmi.Mtz | Path | str, cycles: int, f: str, sigf: str, - fwt: str, phwt: str, func: Callable = n_glycosylate_from_objects, verbose: bool = False) -> Tuple[ + fwt: str, phwt: str, type: Type = Type.n_glycosylate, verbose: bool = False) -> Tuple[ gemmi.Structure, gemmi.Mtz, dict, dict]: """ :param structure: The input structure file in gemmi.Structure, Path, or str format. @@ -20,7 +51,7 @@ def glycosylate(structure: gemmi.Structure | Path | str, mtz: gemmi.Mtz | Path | :param sigf: The column label for the structure factor uncertainties. :param fwt: The column label for the structure factor amplitude weights (potentially None). :param phwt: The column label for the structure factor phase weights (potentially None). - :param func: The function to use for glycosylation. Default is n_glycosylate_from_objects. + :param type: The type of glycosylation to perform. Default is n_glycosylate. :param verbose: Flag specifying whether to print verbose output. Default is False. :return: A tuple containing the glycosylated structure in gemmi.Structure format, the glycosylated MTZ file in gemmi.Mtz format, the log as a string, and a dictionary of snfgs. @@ -28,6 +59,8 @@ def glycosylate(structure: gemmi.Structure | Path | str, mtz: gemmi.Mtz | Path | sails_structure = interface.get_sails_structure(structure) sails_mtz = interface.get_sails_mtz(mtz, f, sigf, fwt, phwt) resource = importlib.resources.files('sails').joinpath("data") + + func = map_type_to_function(type) result = func(sails_structure, sails_mtz, cycles, str(resource), verbose) return (interface.extract_sails_structure(result.structure), interface.extract_sails_mtz(result.mtz), @@ -87,9 +120,8 @@ def run_cli(): labels = get_column_labels(args.colin_fo, args.colin_fwt) - func = c_glycosylate_from_objects if args.cglycan else n_glycosylate_from_objects - cycles = 1 if args.cglycan else args.cycles - structure, mtz, log, snfgs = glycosylate(args.pdbin, args.mtzin, cycles, *labels, func, args.v) + cycles = args.cycles if args.type == Type.n_glycosylate else 1 + structure, mtz, log, snfgs = glycosylate(args.pdbin, args.mtzin, cycles, *labels, args.type, args.v) if args.snfgout: save_snfgs(snfgs, Path(args.snfgout)) @@ -115,8 +147,7 @@ def parse_args(): parser.add_argument("-colin-fo", type=str, required=False, default="FP,SIGFP") parser.add_argument("-colin-fwt", type=str, required=False, default="") parser.add_argument("-cycles", type=int, required=False, default=2) - parser.add_argument("-nglycan", action=argparse.BooleanOptionalAction) - parser.add_argument("-cglycan", action=argparse.BooleanOptionalAction) + parser.add_argument("-type", type=Type.from_string, choices=list(Type), default=Type.n_glycosylate) parser.add_argument("-v", action=argparse.BooleanOptionalAction, default=False) parser.add_argument("--version", action="version", version=__version__) diff --git a/package/tests/test_glycosylation.py b/package/tests/test_glycosylation.py index d88f2f4..e5210ee 100644 --- a/package/tests/test_glycosylation.py +++ b/package/tests/test_glycosylation.py @@ -19,7 +19,7 @@ def cglycan(data_base_path): s = gemmi.read_structure(str(s_path)) m = gemmi.read_mtz_file(str(m_path)) - return s, m, 1, "FP", "SIGFP", "", "", sails.c_glycosylate_from_objects + return s, m, 1, "FP", "SIGFP", "", "", sails.Type.c_glycosylate def test_cglycosylation(cglycan):