Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added more detailed instructions for installing analysisUtils (#340).
- Included initial documentation (#348).
- Add badges to README.md (#358).
- Add tests for utilsLines, and tidy up formatting (#363).

### Changed

Expand Down
187 changes: 107 additions & 80 deletions phangsPipeline/utilsLists.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
"""
General purpose utilities.
"""


def select_from_list(
master_list,
first=None,
last=None,
skip=[],
only=[],
loose=True,
):
master_list: list,
first: str | None = None,
last: str | None = None,
skip: str | list | None = None,
only: str | list | None = None,
loose: bool = True,
) -> list:
"""
Select only part of a list.

Args:
master_list (list): List of elements
first (str): First element to select in list. Defaults to None,
which will run from start of list
last (str): Last element to select in list. Defaults to None,
which will run to end of list
skip (str, list): List of elements to skip. Defaults
to None, which will not filter
only (str, list): List of only elements to include. Defaults
to None, which will not filter
loose (bool): If False, for skip/only, will match on case.
Otherwise, will be case agnostic. Defaults to True

Returns:
list: Sorted list of filtered elements
"""

sorted_list = sorted(master_list,key=lambda s: s.lower())
if not isinstance(master_list, list):
raise TypeError("master_list must be a list")

sub_list = []
# Start by sorting the list
sorted_list = sorted(
master_list,
key=lambda s: s.lower(),
)

if first is not None:
before_first = True
Expand All @@ -29,118 +45,129 @@ def select_from_list(
else:
after_last = False

if skip is None:
skip = []
if isinstance(skip, str):
skip = [skip]

if only is None:
only = []
if isinstance(only, str):
only = [only]

if loose:
skip = [s.lower() for s in skip]
only = [s.lower() for s in only]

sub_list = []

for element in sorted_list:

# Check if we're before or after first/last element
if first is not None:
if loose:
if element.lower() >= first.lower():
before_first = False
else:
if element.lower() == first.lower():
before_first = False
if element.lower() >= first.lower():
before_first = False

if last is not None:
if loose:
if element.lower() > last.lower():
after_last = True
if element.lower() > last.lower():
after_last = True

if before_first:
# If we're before first or after last, skip
if before_first or after_last:
continue

if after_last:
continue
# Check skip
if len(skip) > 0:
match = False

if skip is not None:
if len(skip) > 0:
match = False
if loose:
for this_skip in skip:
if element.lower() == this_skip.lower():
match = True
else:
if element in skip:
match = True
if match:
continue

if only is not None:
if len(only) > 0:
match = False
if loose:
for this_only in only:
if element.lower() == this_only.lower():
match = True
else:
if element in only:
match = True
if not match:
continue

sub_list.append(element)
# If we're loose, we've already lowercase-d skip
if loose:
if element.lower() in skip:
match = True

if last is not None:
if not loose:
if element.lower() == last.lower():
after_last = True
# Else, match exactly
else:
if element in skip:
match = True

return(sub_list)

def lohi_vecs_to_pairs(lovec, hivec):
"""
Convert a low and hi
"""
# If we've found a match, skip
if match:
continue

# Check only
if len(only) > 0:
match = False

# If we're loose, we've already lowercase-d only
if loose:
if element.lower() in only:
match = True

# Else, match exactly
else:
if element in only:
match = True

# Add some error checking
# If we haven't found a match, skip
if not match:
continue

pairs = []
sub_list.append(element)

for ii in range(lovec):
pairs.append((lovec[ii], hivec[ii]))
return sub_list

return(pairs)

def merge_pairs(pairs):
def merge_pairs(
pairs: list,
) -> list:
"""
Accepted a matched list lo/hi pairs and returns the list of pairs
Accept a matched list lo/hi pairs and returns the list of pairs
merged until convergence.

Args:
pairs (list): list of pairs

Returns:
list: list of pairs, as tuples
"""

# Add some error checking

if not isinstance(pairs, list):
raise TypeError("pairs must be a list")

# Sort on the x coordinate
pairs = sorted(pairs)

# Start the list of new pairs
new_pairs = [pairs[0]]
new_pairs = [tuple(pairs[0])]
i = 1

# Iterate
while i <= len(pairs)-1:
while i <= len(pairs) - 1:

# Pick the last new pair for comparison
x1,y1 = new_pairs[-1]
x1, y1 = new_pairs[-1]

# Compare to the current pair
x2,y2 = pairs[i]
x2, y2 = pairs[i]

# Since we are sorted by x, we know x2>=x1. If y2 is less than
# y1, the current window already spans the range.
if y2 <= y1:
i += 1 # included
i += 1 # included
continue

# If x2 is less than y1, the comparison window begins inside
# the end point, then we might extend the window. Span to the
# maximum of y1, y2.
if x2 <= y1:
new_pairs[-1] = (x1,max(y1,y2)) # grow
new_pairs[-1] = (x1, max(y1, y2)) # grow
continue
else:
# Otherwise, the new window begins outside the previous
# window. In that case, we move to a new part of the
# sequence. Now use that pair for comparison instead.
new_pairs.append((x2,y2)) # new
new_pairs.append((x2, y2)) # new
i += 1
continue

return(new_pairs)
return new_pairs
Loading
Loading