def test_pseudoknot_orders(seed): """ Generate a random set of basepairs. Assert that increasing pseudoknot orders contain less or equal base pairs. Furthermore, assert that each individual order only contains unknotted base pairs. """ # Generate Random set of basepairs np.random.seed(seed) bases = range(100) basepairs = np.random.choice(bases, size=(20, 2), replace=False) # Get pseudoknot order for each basepair solutions = struc.pseudoknots(basepairs) # Iterate through the solutions for solution in solutions: # Number of base pairs in the previous order previous_order = -1 for order in range(np.max(solution) + 1): # Ensure that the base pairs of the same order are unknotted assert (struc.pseudoknots(basepairs[solution == order]) == 0).all() # Number of base pairs in the current order this_order = len(solution[solution == order]) # Ensure that that higher orders contain less or equal base # pairs than lower orders if previous_order != -1: assert this_order <= previous_order previous_order = this_order
def test_pseudoknot_removal(name): """ Test the implementation of the dynamic programming algorithm referenced in :func:`pseudoknots()` against the original implementation. The reference solutions were created with the following tool: https://www.ibi.vu.nl/programs/k2nwww/ The original purpose was to remove pseudoknots. Thus, the reference solutions contain unknotted basepairs. """ # Get base pairs and reference solutions basepairs, reference_solutions = load_test(name) # Calculate solutions from the base pairs raw_solutions = struc.pseudoknots(basepairs, max_pseudoknot_order=0) # The number of solutions calculated solutions_count = 0 # Verify that each solution is in the reference solutions for raw_solution in raw_solutions: solution = set() for basepair, order in zip(basepairs, raw_solution): if order == -1: continue solution.add(tuple(sorted(basepair))) solutions_count += 1 assert solution in reference_solutions # Verify that the number of solutions matches the reference assert len(reference_solutions) == solutions_count
def test_pseudoknots(nuc_sample_array): """ Check the output of :func:`pseudoknots()`. """ # Known base pairs with pseudoknot-order = 1: pseudoknot_order_one = [{2, 74}, {58, 72}, {59, 71}, {60, 70}] # Known base pairs that can either be of order one or two pseudoknot_order_one_or_two = [{9, 48}, {10, 49}] order_one_count = (len(pseudoknot_order_one) + (len(pseudoknot_order_one_or_two) / 2)) order_two_count = len(pseudoknot_order_one_or_two) / 2 base_pairs = struc.base_pairs(nuc_sample_array) pseudoknot_order = struc.pseudoknots(base_pairs) # Sample structure should have two optimal solutions with default # scoring parameters assert len(pseudoknot_order) == 2 for optimal_solution in pseudoknot_order: # Assert that the right number of pseudoknots is present for # each order assert len(base_pairs) == len(optimal_solution) assert np.count_nonzero(optimal_solution == 1) == order_one_count assert np.count_nonzero(optimal_solution == 2) == order_two_count assert np.max(optimal_solution) == 2 # Assert that the each base pair has the right pseudoknot order for base_pair, order in zip(nuc_sample_array[base_pairs].res_id, optimal_solution): if (order == 1): assert (set(base_pair) in pseudoknot_order_one or set(base_pair) in pseudoknot_order_one_or_two) elif (order == 2): assert (set(base_pair) in pseudoknot_order_one_or_two)
def plot_rna(pdb_id, axes): # Download the PDB file and read the structure pdb_file_path = rcsb.fetch(pdb_id, "pdb", gettempdir()) pdb_file = pdb.PDBFile.read(pdb_file_path) atom_array = pdb.get_structure(pdb_file)[0] nucleotides = atom_array[struc.filter_nucleotides(atom_array)] # Compute the base pairs and their pseudoknot order base_pairs = struc.base_pairs(nucleotides) base_pairs = struc.get_residue_positions( nucleotides, base_pairs.flatten() ).reshape(base_pairs.shape) pseudoknot_order = struc.pseudoknots(base_pairs)[0] # Set the linestyle according to the pseudoknot order linestyles = np.full(base_pairs.shape[0], '-', dtype=object) linestyles[pseudoknot_order == 1] = '--' linestyles[pseudoknot_order == 2] = ':' # Indicate canonical nucleotides with an upper case one-letter-code # and non-canonical nucleotides with a lower case one-letter-code base_labels = [] for base in struc.residue_iter(nucleotides): one_letter_code, exact = struc.map_nucleotide(base) if exact: base_labels.append(one_letter_code) else: base_labels.append(one_letter_code.lower()) # Color canonical Watson-Crick base pairs with a darker orange and # non-canonical base pairs with a lighter orange colors = np.full(base_pairs.shape[0], biotite.colors['brightorange']) for i, (base1, base2) in enumerate(base_pairs): name1 = base_labels[base1] name2 = base_labels[base2] if sorted([name1, name2]) in [["A", "U"], ["C", "G"]]: colors[i] = biotite.colors["dimorange"] # Plot the secondary structure graphics.plot_nucleotide_secondary_structure( axes, base_labels, base_pairs, struc.get_residue_count(nucleotides), pseudoknot_order=pseudoknot_order, bond_linestyle=linestyles, bond_color=colors, # Margin to compensate for reduced axis limits in shared axis border=0.13 ) # Use the PDB ID to label each plot axes.set_title(pdb_id, loc="left")
ax.set_ylim(0, len(residue_ids)/2 + 0.5) ax.set_aspect("equal") ax.xaxis.set_major_locator(ticker.MultipleLocator(3)) ax.tick_params(axis='both', which='major', labelsize=8) ax.set_yticks([]) # Remove the frame plt.box(False) # Plot the residue names in order for residue_name, residue_id in zip(residue_names, residue_ids): ax.text(residue_id, 0, residue_name, ha='center', fontsize=8) # Compute the basepairs and pseudknot order (first result) base_pairs = struc.base_pairs(nucleotides) pseudoknot_order = struc.pseudoknots(base_pairs)[0] # Draw the arcs between basepairs for (base1, base2), order in zip(base_pairs, pseudoknot_order): arc_center = ( np.mean((nucleotides.res_id[base1],nucleotides.res_id[base2])), 1.5 ) arc_diameter = abs(nucleotides.res_id[base2] - nucleotides.res_id[base1]) name1 = nucleotides.res_name[base1] name2 = nucleotides.res_name[base2] if sorted([name1, name2]) in [["A", "U"], ["C", "G"]]: color = biotite.colors["dimorange"] else: color = biotite.colors["brightorange"] if order == 0: linestyle = "-"