Skip to content

flags

boolean_positional_prevent_msg module-attribute

boolean_positional_prevent_msg = format

Use this message in all help keyword arguments using argparse.BooleanOptionalAction with default=True to specify the --no- prefix when the argument should be False

flags_kwargs module-attribute

flags_kwargs = get(parser_name, {})

flags_kwargs has args (flag names) as key and keyword args (flag params) as values

cluster_defaults module-attribute

cluster_defaults = dict(namespace='cluster')

Contains all the arguments and their default parameters used in clustering Poses

design_defaults module-attribute

design_defaults = dict(namespace='design')

Contains all the arguments and their default parameters used in design

dock_defaults module-attribute

dock_defaults = dict(namespace='dock')

Contains all the arguments and their default parameters used in docking

init_defaults module-attribute

init_defaults = dict(namespace='init')

Contains all the arguments and their default parameters used in structure/sequence initialization

predict_defaults module-attribute

predict_defaults = dict(namespace='predict')

Contains all the arguments and their default parameters used in structure prediction

available_modules module-attribute

available_modules = sorted(difference(available_tools))

Contains all the registered modules

FlagStr

Bases: str

Flag instances are strings which represent possible input parameters to the program with additional formatting for program runtime to properly reflect underscore and dashed versions

_ property

_: str

Format a string from the command line format to a program acceptable string

Returns:

  • str

    The flag formatted by replacing any dash '-' with an underscore '_'

long property

long: str

Format a flag for the command line

Returns:

  • str

    The flag formatted by replacing any underscore '_' with a dash '-'

format_for_cmdline

format_for_cmdline(string) -> str

Format a flag for the command line

Parameters:

  • string

    The string to format as a commandline flag

Returns:

  • str

    The string formatted by replacing any underscores '_' with a dash '-'

Source code in symdesign/flags/__init__.py
271
272
273
274
275
276
277
278
279
280
def format_for_cmdline(string) -> str:
    """Format a flag for the command line

    Args:
        string: The string to format as a commandline flag

    Returns:
        The string formatted by replacing any underscores '_' with a dash '-'
    """
    return string.replace('_', argparse_flag_delimiter)

format_from_cmdline

format_from_cmdline(string) -> str

Format a string from the command line format to a program acceptable string

Parameters:

  • string

    The string to format as a python string

Returns:

  • str

    The flag formatted by replacing any dash '-' with an underscore '_'

Source code in symdesign/flags/__init__.py
283
284
285
286
287
288
289
290
291
292
def format_from_cmdline(string) -> str:
    """Format a string from the command line format to a program acceptable string

    Args:
        string: The string to format as a python string

    Returns:
        The flag formatted by replacing any dash '-' with an underscore '_'
    """
    return string.replace(argparse_flag_delimiter, '_')

format_args

format_args(flag_args: Sequence[str]) -> str

Create a string to format different flags for their various acceptance options on the command line

Parameters:

  • flag_args (Sequence[str]) –

    Typically a tuple of allowed flag "keywords" specified using "-" or "--"

Returns:

  • str

    The flag arguments formatted with a "/" between each allowed version

Source code in symdesign/flags/__init__.py
323
324
325
326
327
328
329
330
331
332
def format_args(flag_args: Sequence[str]) -> str:
    """Create a string to format different flags for their various acceptance options on the command line

    Args:
        flag_args: Typically a tuple of allowed flag "keywords" specified using "-" or "--"

    Returns:
        The flag arguments formatted with a "/" between each allowed version
    """
    return '/'.join(flag_args)

parse_weights

parse_weights(weights: list[str] = None, file: AnyStr = None) -> dict[str, list[tuple[Callable, Callable, dict, Any]]]

Given a command line specified set of metrics and values, parse into weights to select DataFrames accordingly

Parameters:

  • weights (list[str], default: None ) –

    The command line collected weight arguments as specified in the weights --help

  • file (AnyStr, default: None ) –

    The path to a file specifying weights in JSON as specified in the weights --help

Returns:

  • dict[str, list[tuple[Callable, Callable, dict, Any]]]

    The parsed metric mapping linking each metric to a specified operation

Source code in symdesign/flags/__init__.py
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
def parse_weights(weights: list[str] = None, file: AnyStr = None) \
        -> dict[str, list[tuple[Callable, Callable, dict, Any]]]:
    """Given a command line specified set of metrics and values, parse into weights to select DataFrames accordingly

    Args:
        weights: The command line collected weight arguments as specified in the weights --help
        file: The path to a file specifying weights in JSON as specified in the weights --help

    Returns:
        The parsed metric mapping linking each metric to a specified operation
    """
    parsed_weights = parse_filters(weights, file=file)
    # Ensure proper formatting of weight specific parameters
    for idx, (metric_name, weight) in enumerate(parsed_weights.items()):
        if len(weight) != 1:
            raise InputError(
                f"Can't assign more than one weight for every provided metric. '{weights[idx]}' is invalid")
        operation, pre_operation, pre_kwargs, value = weight[0]
        if operation != operator.eq:
            raise InputError(
                f"Can't assign a selection weight with the operator '{operator_strings[operation]}'. "
                f"'{weights[idx]}' is invalid")
        if isinstance(value, str):
            raise InputError(
                f"Can't assign a numerical weight to the provided weight '{weights[idx]}'")

    return parsed_weights

parse_filters

parse_filters(filters: list[str] = None, file: AnyStr = None) -> dict[str, list[tuple[Callable, Callable, dict, Any]]]

Given a command line specified set of metrics and values, parse into filters to select DataFrames accordingly

Parameters:

  • filters (list[str], default: None ) –

    The command line collected filter arguments as specified in the filters --help

  • file (AnyStr, default: None ) –

    The path to a file specifying filters in JSON as specified in the filters --help

Returns:

  • dict[str, list[tuple[Callable, Callable, dict, Any]]]

    The parsed metric mapping linking each metric to a specified operation

Source code in symdesign/flags/__init__.py
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
def parse_filters(filters: list[str] = None, file: AnyStr = None) \
        -> dict[str, list[tuple[Callable, Callable, dict, Any]]]:
    """Given a command line specified set of metrics and values, parse into filters to select DataFrames accordingly

    Args:
        filters: The command line collected filter arguments as specified in the filters --help
        file: The path to a file specifying filters in JSON as specified in the filters --help

    Returns:
        The parsed metric mapping linking each metric to a specified operation
    """
    def null(df, **_kwargs):
        """Do nothing and return a passed DataFrame"""
        return df

    if file is not None:
        # parsed_filters = read_json(file)
        filters = to_iterable(file)

    # Parse input filters as individual filtering directives
    parsed_filters = {}
    for filter_str in filters:
        # Make an additional variable to substitute operations as they are found
        _filter_str = filter_str
        # Find the indices of each operation and save to use as slices
        indices = []
        operations_syntax = []
        for syntax in viable_operations:
            # if syntax in filter_str:
            while syntax in _filter_str:
                f_index = _filter_str.find(syntax)
                # It is important that shorter operations do not pull out longer ones i.e. '>' and '>='
                # # Check if equals is the next character and set operation_length
                # if filter_str[f_index + 1] == '=':
                #     operation_length = 2
                # else:
                #     operation_length = 1
                operation_length = len(syntax)
                r_index = f_index + operation_length
                # r_index = filter_str.rfind(syntax)
                indices.append([f_index, r_index])
                operations_syntax.append(syntax)
                # Substitute out the found operation for '`'
                _filter_str = _filter_str[:f_index] + '`' * operation_length + _filter_str[r_index:]

        if not indices:
            raise InputError(
                f"Couldn't create a filter from '{filter_str}'. Ensure that your input contains an operation specifying"
                " the relationship between the filter and the expected value")

        # Sort the indices according to the first index number
        full_indices = []
        for idx_pair in sorted(indices, key=lambda pair: pair[0]):
            full_indices.extend(idx_pair)

        # Separate the filter components along the operations
        unique_components = [filter_str[:full_indices[0]]] \
            + [filter_str[f_index:r_index] for f_index, r_index in zip(full_indices[:-1], full_indices[1:])] \
            + [filter_str[full_indices[-1]:]]

        # Set up function to parse values properly
        def extract_format_value(_value: str) -> Any:
            """Values can be of type int, float, or string. Further, strings could be a list of int/float
            comma separated

            Args:
                _value: The string to format

            Returns:
                The value formatted from a string input to the correct python type for filter evaluation
            """
            try:
                formatted_value = int(_value)
            except ValueError:  # Not simply an integer
                try:
                    formatted_value = float(_value)
                except ValueError:  # Not numeric
                    # This is either a list of numerics or likely a string value
                    _values = [_component.strip() for _component in _value.split(',')]
                    if len(_values) > 1:
                        # We have a list of values
                        formatted_value = [extract_format_value(_value_) for _value_ in _values]
                    else:
                        # This is some type of string value
                        formatted_value = _values[0]
                        # if _value[-1] == '%':
                        #     # This should be treated as a percentage
                        #     formatted_value = extract_format_value(_value)

            return formatted_value

        # Find the values that are metrics and those that are values, then ensure they are parsed correct
        metric = metric_specs = metric_idx = None
        invert_ops = True
        operations_syntax_iter = iter(operations_syntax)
        parsed_values = []
        parsed_operations = []
        parsed_percents = []
        for idx, component in enumerate(unique_components):
            # Value, operation, value, operation, value
            if idx % 2 == 0:  # Zero or even index which must contain metric/values
                # Substitute any numerical characters to test if the provided component is a metric
                substituted_component = component.translate(remove_digit_table)
                logger.debug(f'substituted_component |{substituted_component}|')
                _metric_specs = config.metrics.get(substituted_component.strip())
                if _metric_specs:  # We found in the list of available program metrics
                    logger.debug(f'metric specifications {",".join(f"{k}={v}" for k, v in _metric_specs.items())}')
                    if metric_idx is None:
                        metric_specs = _metric_specs
                        metric = component.strip()
                        metric_idx = idx
                        # if idx != 0:
                        # We must negate operations until the metric is found, i.e. metric > 1 is expected, but
                        # 1 < metric < 10 is allowed. This becomes metric > 1 and metric < 10
                        invert_ops = False
                        continue
                    else:  # We found two metrics...
                        raise ValueError(
                            f"Can't accept more than one metric name per filter")
                else:  # Either a value or bad metric name
                    if component[-1] == '%':
                        # This should be treated as a percentage. Remove and parse
                        component = component[:-1]
                        parsed_percents.append(True)
                    else:
                        parsed_percents.append(False)
                    component = extract_format_value(component)

                    parsed_values.append(component)
                # # This may be required if section is reworked to allow more than one value per filter
                # parsed_values.append(component)
            else:  # This is an operation
                syntax = next(operations_syntax_iter)
                if invert_ops:
                    operation = inverse_operations.get(syntax, viable_operations[syntax])
                else:
                    operation = viable_operations[syntax]

                logger.debug(f'operation is {operation}')
                parsed_operations.append(operation)

        if metric_idx is None:
            possible_metrics = []
            for value in parsed_values:
                if isinstance(value, str):
                    possible_metrics.append(value)
            # Todo find the closest and report to the user!
            raise InputError(
                f"Couldn't coerce{' any of' if len(possible_metrics) > 1 else ''} '{', '.join(possible_metrics)}' to a"
                f" viable metric. Ensure you used the correct spelling")

        # Format the metric for use by select-* protocols
        filter_specification = []
        for value, percent, operation in zip(parsed_values, parsed_percents, parsed_operations):
            if percent:
                # pre_operation = pd.DataFrame.sort_values
                pre_operation = pd.DataFrame.rank
                pre_kwargs = dict(
                    # Whether to sort dataframe with ascending, bigger values (higher rank) on top. Default True
                    # ascending=metric_specs['direction'],
                    # Will determine how ties are sorted which depends on the directional preference of the filter
                    # 'min' makes equal values assume lower percent, 'max' higher percent
                    method=metric_specs['direction'],
                    # Treat the rank as a percent so that a percentage can be used to filter
                    pct=True
                )
            else:
                pre_operation = null
                pre_kwargs = {}

            filter_specification.append((operation, pre_operation, pre_kwargs, value))

        parsed_filters[metric] = filter_specification

    return parsed_filters

temp_gt0

temp_gt0(temp: str) -> float

Convert temperatures flags to float ensuring no 0 value

Source code in symdesign/flags/__init__.py
1430
1431
1432
1433
def temp_gt0(temp: str) -> float:
    """Convert temperatures flags to float ensuring no 0 value"""
    temp = float(temp)
    return temp if temp > 0 else 0.0001

set_up_parser_with_groups

set_up_parser_with_groups(parser: ArgumentParser, parser_groups: dict[str, dict], required: bool = False)

Add the input arguments to the passed ArgumentParser

Parameters:

  • parser (ArgumentParser) –

    The ArgumentParser to add_argument_group() to

  • parser_groups (dict[str, dict]) –

    The groups to add to the ArgumentParser

  • required (bool, default: False ) –

    Whether the mutually exclusive group input is required

Source code in symdesign/flags/__init__.py
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
def set_up_parser_with_groups(parser: argparse.ArgumentParser, parser_groups: dict[str, dict], required: bool = False):
    """Add the input arguments to the passed ArgumentParser

    Args:
        parser: The ArgumentParser to add_argument_group() to
        parser_groups: The groups to add to the ArgumentParser
        required: Whether the mutually exclusive group input is required
    """
    group = None  # Must get added before mutual groups can be added
    for parser_name, parser_kwargs in parser_groups.items():
        flags_kwargs = parser_arguments.get(parser_name, {})
        """flags_kwargs has args (flag names) as key and keyword args (flag params) as values"""
        if mutual_keyword in parser_name:  # Only has a dictionary as parser_arguments
            if group is None:
                # Remove indication to "mutual" of the argparse group by removing any characters after mutual_keyword
                group_parser_kwargs = parser_groups[parser_name[:parser_name.find(mutual_keyword)]]
                group = parser.add_argument_group(**group_parser_kwargs)
            exclusive_parser = group.add_mutually_exclusive_group(required=required, **parser_kwargs)
            for flags_, kwargs in flags_kwargs.items():
                exclusive_parser.add_argument(*flags_, **kwargs)
        else:
            if group is None:
                group = parser.add_argument_group(**parser_kwargs)
            for flags_, kwargs in flags_kwargs.items():
                group.add_argument(*flags_, **kwargs)