All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.poznan.put.structure.formats.DefaultConverter Maven / Gradle / Ivy

package pl.poznan.put.structure.formats;

import org.apache.commons.lang3.builder.CompareToBuilder;
import org.immutables.value.Value;
import pl.poznan.put.structure.pseudoknots.PseudoknotFinder;
import pl.poznan.put.structure.pseudoknots.elimination.ImmutableMinGain;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * A default converter from BPSEQ to dot-bracket which iteratively (1) finds non-pseudoknots and
 * assigns the current lowest level, then (2) increases level and (3) treats pseudoknots as the next
 * input to (1) until there are base pairs without level assigned.
 */
@Value.Immutable(singleton = true)
public abstract class DefaultConverter implements Converter {
  private static final char[] BRACKETS_OPENING = "([{ states) {
    for (final State state : states) {
      if (!state.isFinal()) {
        return true;
      }
    }
    return false;
  }

  private static String traceback(final State state) {
    final char[] structure = new char[state.size()];
    Arrays.fill(structure, '.');
    Optional current = state.parent();

    while (current.isPresent()) {
      for (final BpSeq.Entry pairs : current.get().bpSeq().paired()) {
        final int i = pairs.index();
        final int j = pairs.pair();

        if (structure[i - 1] == '.') {
          structure[i - 1] = DefaultConverter.BRACKETS_OPENING[current.get().level()];
          structure[j - 1] = DefaultConverter.BRACKETS_CLOSING[current.get().level()];
        }
      }

      current = current.get().parent();
    }

    return new String(structure);
  }

  /**
   * @return The finder of pseudoknots ({@link
   *     pl.poznan.put.structure.pseudoknots.elimination.MinGain} by default).
   */
  @Value.Default
  public PseudoknotFinder pseudoknotFinder() {
    return ImmutableMinGain.of();
  }

  /** @return The number of solutions to return (1 by default). */
  @Value.Default
  public int maxSolutions() {
    return 1;
  }

  /**
   * Converts the secondary structure in BPSEQ format to dot-bracket. Works level-by-level, see
   * class description.
   *
   * @param bpSeq The data in BPSEQ format.
   * @return The converted dot-bracket.
   */
  @Override
  public final DotBracket convert(final BpSeq bpSeq) {
    List states = new ArrayList<>();
    states.add(ImmutableState.of(Optional.empty(), bpSeq, 0));

    while (DefaultConverter.isProcessingNeeded(states)) {
      states = processStates(states);
    }

    Collections.sort(states);
    final String structure = DefaultConverter.traceback(states.get(0));
    return ImmutableDefaultDotBracket.of(bpSeq.sequence(), structure);
  }

  private List processStates(final Collection states) {
    final List nextStates = new ArrayList<>(states.size());
    for (final State state : states) {
      for (final BpSeq bpSeq : pseudoknotFinder().findPseudoknots(state.bpSeq())) {
        final State nextState = ImmutableState.of(Optional.of(state), bpSeq, state.level() + 1);
        nextStates.add(nextState);

        if (nextStates.size() > maxSolutions()) {
          return nextStates;
        }
      }
    }
    return nextStates;
  }

  @Value.Immutable
  abstract static class State implements Comparable {
    @Value.Parameter(order = 1)
    public abstract Optional parent();

    @Value.Parameter(order = 2)
    public abstract BpSeq bpSeq();

    @Value.Parameter(order = 3)
    public abstract int level();

    @Value.Lazy
    public int score() {
      return bpSeq().paired().size();
    }

    @Override
    public final int compareTo(final State t) {
      return new CompareToBuilder().append(level(), t.level()).append(score(), t.score()).build();
    }

    private boolean isFinal() {
      return score() == 0;
    }

    private int size() {
      return bpSeq().size();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy