Download model/prediction_result_file.py from OneScience-Group/Chainsaw: direct link, hf CLI and curl.
- Browser
- Download file 5.37 kB
-
https://huggingface.co/OneScience-Group/Chainsaw/resolve/main/model/prediction_result_file.py
- Command line
-
hf download hf://OneScience-Group/Chainsaw/model/prediction_result_file.py
-
curl -L -o prediction_result_file.py https://huggingface.co/OneScience-Group/Chainsaw/resolve/main/model/prediction_result_file.py
5.37 kB
| """ | |
| Class that represents a file with the prediction results | |
| * allows prediction results to be appended to the file in chunks | |
| * allows results to be skipped if they already exist in the file | |
| """ | |
| import csv | |
| from typing import List, OrderedDict | |
| from pathlib import Path | |
| import logging | |
| from .models.results import PredictionResult | |
| from .errors import PredictionResultExistsError, FileExistsError | |
| LOG = logging.getLogger(__name__) | |
| class PredictionResultsFileIter: | |
| def __init__(self, results_file_class): | |
| self._results = results_file_class.get_results() | |
| self._results_size = len(self._results) | |
| self._current_index = 0 | |
| def __iter__(self): | |
| return self | |
| def __next__(self): | |
| if self._current_index < self._results_size: | |
| member = self._results[self._current_index] | |
| self._current_index += 1 | |
| return member | |
| raise StopIteration | |
| class PredictionResultsFile: | |
| """ | |
| Writes prediction results to a file in chunks | |
| """ | |
| COLNAMES = ['chain_id', 'sequence_md5', 'nres', 'ndom', 'chopping', 'confidence', 'time_sec'] | |
| def __init__(self, | |
| csv_path: Path, *, | |
| chunk_size: int=20, | |
| write_header: bool=True, | |
| allow_append: bool=False, | |
| allow_skip: bool=False): | |
| self.csv_path = Path(str(csv_path)).absolute() | |
| self.chunk_size = chunk_size | |
| self.write_header = write_header | |
| self.allow_append = allow_append | |
| self.allow_skip = allow_skip | |
| self._results_by_id: OrderedDict[PredictionResult] = OrderedDict() | |
| self._unflushed_results_by_id: OrderedDict[PredictionResult] = OrderedDict() | |
| self._written_header = False | |
| self._init() | |
| def _init(self): | |
| if self.csv_path.exists(): | |
| msg = f"file '{self.csv_path}' already exists (allow_append={self.allow_append}))" | |
| LOG.warning(msg) | |
| if not self.allow_append: | |
| raise FileExistsError(msg) | |
| self._read_results() | |
| def _read_results(self): | |
| """ | |
| Read the results from the file | |
| """ | |
| with self.csv_path.open('r') as fp: | |
| reader = self.get_csv_reader(fp) | |
| for row in reader: | |
| if row['chain_id'] == 'chain_id': | |
| continue | |
| pdb_path = Path(row['chain_id'] + '.pdb') | |
| result = PredictionResult(pdb_path=pdb_path, **row) | |
| self._results_by_id[result.chain_id] = result | |
| def get_flushed_results(self): | |
| self.flush() | |
| return self._results_by_id.values() | |
| def get_csv_reader(self, fp): | |
| return csv.DictReader(fp, delimiter='\t', fieldnames=self.COLNAMES) | |
| def get_csv_writer(self, fp): | |
| return csv.DictWriter(fp, delimiter='\t', fieldnames=self.COLNAMES) | |
| def write_csv_result(self, csv_writer, res: PredictionResult): | |
| """ | |
| Render PredictionResult result to file pointer | |
| """ | |
| row = { | |
| 'chain_id': res.chain_id, | |
| 'sequence_md5': res.sequence_md5, | |
| 'nres': res.nres, | |
| 'ndom': res.ndom, | |
| 'chopping': res.chopping if res.chopping is not None else 'NULL', | |
| 'confidence': f'{res.confidence:.3g}' if res.confidence is not None else 'NULL', | |
| 'time_sec': f'{res.time_sec}' if res.time_sec is not None else 'NULL', | |
| } | |
| csv_writer.writerow(row) | |
| def flush(self): | |
| """ | |
| Write unflushed results to the output file | |
| """ | |
| if len(self._unflushed_results_by_id) == 0: | |
| return | |
| with self.csv_path.open('a') as fp: | |
| csv_writer = self.get_csv_writer(fp) | |
| if self.write_header and not self._written_header and len(self._results_by_id) == 0: | |
| csv_writer.writeheader() | |
| self._written_header = True | |
| for result in self._unflushed_results_by_id.values(): | |
| self.write_csv_result(csv_writer, result) | |
| def has_result(self, result: PredictionResult): | |
| """ | |
| Check if the prediction result already exists in the file | |
| """ | |
| return self.has_result_for_chain_id(result.chain_id) | |
| def has_result_for_chain_id(self, chain_id: str): | |
| """ | |
| Check if the chain_id already exists in the file | |
| """ | |
| if chain_id in self._results_by_id: | |
| return True | |
| if chain_id in self._unflushed_results_by_id: | |
| return True | |
| return False | |
| def add_result(self, result: PredictionResult): | |
| """ | |
| Add a result to the buffer (and possibly flush the buffer) | |
| """ | |
| if self.has_result(result): | |
| msg = f"result '{result.chain_id}' already exists in file '{self.csv_path}'" | |
| raise PredictionResultExistsError(msg) | |
| self._unflushed_results_by_id[result.chain_id] = result | |
| if len(self._unflushed_results_by_id) >= self.chunk_size: | |
| self.flush() | |
| self._results_by_id.update(self._unflushed_results_by_id) | |
| self._unflushed_results_by_id = OrderedDict() | |
| def add_results(self, results: List[PredictionResult]): | |
| for res in results: | |
| self.add_result(res) | |
| def __iter__(self): | |
| return PredictionResultsFileIter(self) | |