enpi_api.l2.client.api.basket_api
1import tempfile 2from pathlib import Path 3 4import pandas as pd 5from loguru import logger 6 7from enpi_api.l1 import openapi_client 8from enpi_api.l2.client.api.file_api import FileApi 9from enpi_api.l2.events.workflow_execution_task_waitable import WorkflowExecutionTaskWaitable 10from enpi_api.l2.types.api_error import ApiErrorContext 11from enpi_api.l2.types.basket import Basket, BasketExportFormat, BasketId, FastaExportConfig, TsvExportConfig 12from enpi_api.l2.types.clone import CloneId 13from enpi_api.l2.types.execution import Execution 14from enpi_api.l2.types.log import LogLevel 15from enpi_api.l2.types.sequence import SequenceId 16from enpi_api.l2.types.task import TaskState 17from enpi_api.l2.types.workflow import WorkflowExecutionId, WorkflowExecutionTaskId, WorkflowTaskTemplateName 18 19 20class BasketApi: 21 _inner_api_client: openapi_client.ApiClient 22 _log_level: LogLevel 23 24 def __init__(self, inner_api_client: openapi_client.ApiClient, log_level: LogLevel): 25 """@private""" 26 self._inner_api_client = inner_api_client 27 self._log_level = log_level 28 29 def get_baskets(self) -> list[Basket]: 30 """Get all Baskets that belong to the user or were 31 shared to them by other users. 32 33 Returns: 34 list[enpi_api.l2.types.basket.Basket]: Available Baskets. 35 36 Raises: 37 enpi_api.l2.types.api_error.ApiError: If API request fails. 38 39 Example: 40 Get all available Baskets. 41 ```python 42 with EnpiApiClient() as enpi_client: 43 baskets = enpi_client.basket_api.get_baskets() 44 print(baskets) 45 ``` 46 """ 47 48 logger.info("Getting all available Baskets...") 49 50 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 51 52 with ApiErrorContext(): 53 get_baskets_response = basket_api_instance.get_baskets() 54 55 logger.success(f"Successfully got {len(get_baskets_response.baskets)} Baskets.") 56 57 return [Basket.from_raw(basket) for basket in get_baskets_response.baskets] 58 59 def get_basket(self, basket_id: BasketId) -> Basket: 60 """Get a single Basket matched with the provided Basket ID. 61 62 Args: 63 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to get. 64 65 Returns: 66 enpi_api.l2.types.basket.Basket: Basket matching the provided ID. 67 68 Raises: 69 enpi_api.l2.types.api_error.ApiError: If API request fails. 70 71 Example: 72 Get a single Basket. 73 ```python 74 with EnpiApiClient() as enpi_client: 75 id = BasketId(id) 76 basket = enpi_client.basket_api.get_basket(id) 77 print(basket) 78 ``` 79 """ 80 81 logger.info(f"Getting Basket with ID: '{basket_id}'...") 82 83 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 84 85 with ApiErrorContext(): 86 get_basket_response = basket_api_instance.get_basket(basket_id) 87 88 logger.success(f"Successfully got Basket with ID: '{basket_id}'.") 89 90 return Basket.from_raw(get_basket_response.basket) 91 92 def create_basket(self, name: str, shared: bool | None = True, description: str | None = "") -> Basket: 93 """Create a new Basket. 94 95 Args: 96 name (str): The name of the new Basket. 97 shared (bool | None): Determines if the new Basket will be shared to other users in the organization. 98 By default, all Baskets created via this function are being shared to other users. 99 description (str | None): Description for the Basket. 100 101 Returns: 102 enpi_api.l2.types.basket.Basket: Newly created Basket. 103 104 Raises: 105 enpi_api.l2.types.api_error.ApiError: If API request fails. 106 107 Example: 108 Create a new Basket. 109 ```python 110 with EnpiApiClient() as enpi_client: 111 name = "New Basket" 112 basket = enpi_client.basket_api.create_basket(name) 113 print(basket) 114 ``` 115 """ 116 117 logger.info(f"Creating a new {'shared' if shared else 'private'} Basket with name: '{name}'...") 118 119 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 120 121 payload = openapi_client.CreateBasketRequestBody(name=name, shared=shared, description=description) 122 123 with ApiErrorContext(): 124 create_basket_response = basket_api_instance.create_basket(payload) 125 126 logger.success(f"Successfully created a new Basket named: '{name}'.") 127 128 return Basket.from_raw(create_basket_response.basket) 129 130 def update_basket( 131 self, 132 basket_id: BasketId, 133 name: str | None = None, 134 shared: bool | None = None, 135 description: str | None = None, 136 ) -> None: 137 """Update properties of a Basket matched with the provided Basket ID. 138 139 Args: 140 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be updated. 141 name (str | None): New name for the Basket. If no value is provided, Basket's name won't be changed. 142 shared (bool | None): Determines if a Basket will be shared to other users in the organization. 143 If no value is provided, Basket's shared status won't be changed. 144 description (str | None): New description for the Basket. If no value is provided, Basket's description won't be changed. 145 146 Raises: 147 enpi_api.l2.types.api_error.ApiError: If API request fails. 148 149 Example: 150 Update an existing Basket. 151 ```python 152 with EnpiApiClient() as enpi_client: 153 id = BasketId(id) 154 new_name = "Basket (renamed)" 155 is_basket_shared = True 156 enpi_client.basket_api.update_basket(id, new_name, is_basket_shared) 157 ``` 158 """ 159 160 logger.info(f"Updating Basket with ID: '{basket_id}'...") 161 162 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 163 164 payload = openapi_client.UpdateBasketRequestBody(name=name, shared=shared, description=description) 165 166 with ApiErrorContext(): 167 basket_api_instance.update_basket(basket_id, payload) 168 169 logger.success(f"Successfully updated Basket with ID: '{basket_id}'.") 170 171 def delete_basket(self, basket_id: BasketId) -> None: 172 """Delete a Basket matched with the provided Basket ID. 173 174 Args: 175 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be deleted. 176 177 Raises: 178 enpi_api.l2.types.api_error.ApiError: If API request fails. 179 180 Example: 181 Delete a Basket. 182 ```python 183 with EnpiApiClient() as enpi_client: 184 id = BasketId(id) 185 enpi_client.basket_api.delete_basket(id) 186 ``` 187 """ 188 189 logger.info(f"Deleting Basket with ID: '{basket_id}'...") 190 191 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 192 193 with ApiErrorContext(): 194 basket_api_instance.delete_basket(basket_id) 195 196 logger.info(f"Successfully deleted Basket with ID:'{basket_id}'.") 197 198 def add_clones_to_basket( 199 self, 200 basket_id: BasketId, 201 clone_ids: list[CloneId] | None = None, 202 sequence_ids: list[SequenceId] | None = None, 203 ) -> Execution[None]: 204 """Resolve clones matched with provided clone and sequence IDs, 205 then add them into the target Basket. 206 207 > This functionality uses clone resolving.\n 208 > Clone resolving uses passed clone and sequence IDs in order to resolve clones. 209 > For each clone, a maximum of one *big* chain and one *small* chain sequence will be picked, resulting in a 210 maximum of two sequences per clone. 211 > Sequences matched with passed sequence IDs have priority over internally resolved sequences, meaning that if 212 possible, they will be picked as sequences for the resolved clones. 213 214 Args: 215 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to add clones to. 216 clone_ids (list[enpi_api.l2.types.clone.CloneId]): Clone IDs based on which clones will be resolved and added into the target Basket. 217 sequence_ids (list[enpi_api.l2.types.sequence.SequenceId]): Sequence IDs based on which clones will be resolved and added into 218 the target Basket. If clone resolving based on clone IDs and sequence IDs results in the same, "overlapping" clones (with the same clone IDs) 219 but potentially different sequences within, clones resolved with use of sequence IDs will be picked over the ones resolved with clone IDs. 220 221 Returns: 222 enpi_api.l2.types.execution.Execution[None]: An awaitable execution. 223 224 Raises: 225 ValueError: If the provided clone and/or sequence ID arrays are empty or invalid. 226 enpi_api.l2.types.api_error.ApiError: If API request fails. 227 228 Example: 229 Insert clones into a Basket. 230 ```python 231 with EnpiApiClient() as enpi_client: 232 basket_id = BasketId(1) 233 clone_ids = [ 234 CloneId(id) for id in [ 235 "d0c6982d-34cd-47cd-b465-a603dec0530c", 236 "1c19fcbc-ec84-4baa-a641-42058df18303", 237 ] 238 ] 239 sequence_ids = [SequenceId(id) for id in [100, 101, 102]] 240 enpi_client.basket_api.add_clones_to_basket(basket_id, clone_ids, sequence_ids).wait() 241 ``` 242 """ 243 244 logger.info(f"Adding clones to Basket with ID: '{basket_id}'...") 245 246 # Check if we got any ids to work with 247 if (clone_ids is None or len(clone_ids) == 0) and (sequence_ids is None or len(sequence_ids) == 0): 248 raise ValueError("Both clone and sequence IDs arrays are null, at least one of them needs to contain proper values.") 249 250 # Validate if ID types are right 251 if clone_ids is not None and not all([isinstance(id, str) for id in clone_ids]): 252 raise ValueError("Some of the passed clone IDs are not strings.") 253 elif sequence_ids is not None and not all([isinstance(id, int) for id in sequence_ids]): 254 raise ValueError("Some of the passed sequence IDs are not integers.") 255 256 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 257 258 payload = openapi_client.AddClonesRequestBody( 259 clone_ids=None if clone_ids is None else [str(id) for id in clone_ids], 260 sequence_ids=None if sequence_ids is None else [int(id) for id in sequence_ids], 261 ) 262 263 with ApiErrorContext(): 264 add_clones_response = basket_api_instance.add_clones(basket_id, payload) 265 assert add_clones_response.workflow_execution_id is not None 266 267 workflow_execution_id = WorkflowExecutionId(add_clones_response.workflow_execution_id) 268 waitable = WorkflowExecutionTaskWaitable[None]( 269 workflow_execution_id=workflow_execution_id, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_ADD_CLONES, on_complete=None 270 ) 271 272 return Execution(wait=waitable.wait, check_execution_state=waitable.check_execution_state) 273 274 def remove_clones_from_basket(self, basket_id: BasketId, clone_ids: list[CloneId]) -> Execution[None]: 275 """Remove clones matches with provided clone IDs from the target Basket. 276 277 Args: 278 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be removed. 279 clone_ids (list[enpi_api.l2.types.clone.CloneId]): IDs of clones that will be removed from target Basket. 280 281 Returns: 282 enpi_api.l2.types.execution.Execution[None]: An awaitable execution. 283 284 Raises: 285 ValueError: If the provided clone IDs array is invalid. 286 enpi_api.l2.types.api_error.ApiError: If API request fails. 287 288 Example: 289 Remove clones from a Basket. 290 ```python 291 with EnpiApiClient() as enpi_client: 292 basket_id = BasketId(1) 293 clone_ids = [ 294 CloneId(id) for id in [ 295 "d0c6982d-34cd-47cd-b465-a603dec0530c", 296 "1c19fcbc-ec84-4baa-a641-42058df18303", 297 ] 298 ] 299 enpi_client.basket_api.remove_clones_from_basket(basket_id, clone_ids).wait() 300 ``` 301 """ 302 303 n_of_clone_ids = len(clone_ids) 304 logger.info(f"Removing {n_of_clone_ids} clone{'' if n_of_clone_ids == 1 else 's'} from Basket with id: '{basket_id}'") 305 306 # Check if we got any ids to work with 307 if len(clone_ids) == 0: 308 raise ValueError("Provided clone IDs array is empty.") 309 310 # Validate if ID types are right 311 if not all([isinstance(id, str) for id in clone_ids]): 312 raise ValueError("Some of the passed clone IDs are not strings.") 313 314 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 315 316 payload = openapi_client.RemoveClonesRequestBody( 317 clone_ids=[str(id) for id in clone_ids], 318 ) 319 320 with ApiErrorContext(): 321 remove_clones_response = basket_api_instance.remove_clones(basket_id, payload) 322 assert remove_clones_response.workflow_execution_id is not None 323 324 workflow_execution_id = WorkflowExecutionId(remove_clones_response.workflow_execution_id) 325 326 waitable = WorkflowExecutionTaskWaitable[None]( 327 workflow_execution_id=workflow_execution_id, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_REMOVE_CLONES, on_complete=None 328 ) 329 330 return Execution(wait=waitable.wait, check_execution_state=waitable.check_execution_state) 331 332 def export_basket_clones_as_tsv( 333 self, 334 basket_id: BasketId, 335 tsv_config: TsvExportConfig | None = None, 336 output_directory: Path | str | None = None, 337 ) -> Execution[Path]: 338 """Start a Basket clones export in a TSV format, download the result file and return a path to it. 339 340 Args: 341 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 342 tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export. 343 output_directory (Path | str | None): Path to the directory in which the downloaded file will be stored. 344 If not provided, a temporary directory will be created. 345 346 Returns: 347 enpi_api.l2.types.execution.Execution[Path]: An awaitable execution that returns the local file path to the 348 exported file when awaited. 349 350 Raises: 351 enpi_api.l2.types.api_error.ApiError: If API request fails. 352 353 Example: 354 Export Basket clones into a TSV file. 355 ```python 356 with EnpiApiClient() as enpi_client: 357 id = BasketId(1) 358 export_dir = os.path.join(os.path.dirname(__file__), "example_dir") 359 path = enpi_client.basket_api.export_basket_clones_as_tsv(id, export_dir).wait() 360 print(path) 361 ``` 362 """ 363 364 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a TSV file...") 365 366 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 367 368 payload = openapi_client.StartClonesExportRequestBody( 369 openapi_client.StartTsvClonesExportRequestBody( 370 format=BasketExportFormat.TSV, tsv_config=tsv_config.to_api_payload() if tsv_config is not None else None 371 ) 372 ) 373 374 with ApiErrorContext(): 375 data = basket_api_instance.start_clones_export(basket_id, payload) 376 assert data.workflow_execution_id is not None 377 378 workflow_execution_id = WorkflowExecutionId(data.workflow_execution_id) 379 380 def on_complete(task_id: WorkflowExecutionTaskId, task_state: TaskState) -> Path: 381 with ApiErrorContext(): 382 file_api = FileApi(self._inner_api_client, self._log_level) 383 file_path = file_api.download_export_by_workflow_execution_task_id(task_id=task_id, output_directory=output_directory) 384 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a TSV file: '{file_path}'.") 385 return file_path 386 387 waitable = WorkflowExecutionTaskWaitable[Path]( 388 workflow_execution_id=workflow_execution_id, on_complete=on_complete, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_EXPORT 389 ) 390 391 return Execution(wait=waitable.wait_and_return_result, check_execution_state=waitable.check_execution_state) 392 393 def export_basket_clones_as_df(self, basket_id: BasketId, tsv_config: TsvExportConfig | None = None) -> Execution[pd.DataFrame]: 394 """Start a Basket clones export in a TSV format, download the result and return 395 the data from it in a DataFrame object. 396 397 Args: 398 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 399 tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export. 400 401 Returns: 402 enpi_api.l2.types.execution.Execution[pd.DataFrame]: An awaitable execution that returns a pandas DataFrame 403 object containing the exported data when awaited. 404 405 Raises: 406 enpi_api.l2.types.api_error.ApiError: If API request fails. 407 408 Example: 409 Export Basket clones into a DataFrame. 410 ```python 411 with EnpiApiClient() as client: 412 id = BasketId(1) 413 df = client.basket_api.export_basket_clones_as_df(id).wait() 414 print(df) 415 ``` 416 """ 417 418 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a DataFrame...") 419 420 with tempfile.TemporaryDirectory() as temp_dir: 421 execution = self.export_basket_clones_as_tsv(basket_id=basket_id, tsv_config=tsv_config, output_directory=temp_dir) 422 423 def wait() -> pd.DataFrame: 424 tmp_file_path = execution.wait() 425 df = pd.read_csv(tmp_file_path, delimiter="\t") 426 427 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a DataFrame.") 428 429 return df 430 431 return Execution(wait=wait, check_execution_state=execution.check_execution_state) 432 433 def export_basket_clones_as_fasta( 434 self, 435 basket_id: BasketId, 436 fasta_config: FastaExportConfig, 437 output_directory: Path | str | None = None, 438 ) -> Execution[Path]: 439 """Start a Basket clones export in a FASTA format, download the result and return the filepath to the file. 440 441 Args: 442 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 443 fasta_config (enpi_api.l2.types.basket.FastaExportConfig): Configuration of the Basket FASTA export, determining the 444 shape of FASTA file headers and sequences. The enpi_api.l2.types.basket.fasta_config function is the prefered way of 445 a configuration object creation. 446 output_directory (Path | str | None): Path to a directory in which the downloaded file will be stored. 447 If not provided, a temporary directory will be created. 448 449 Returns: 450 enpi_api.l2.types.execution.Execution[Path]: An awaitable that returns information about clones added to the 451 Basket when awaited. 452 453 Raises: 454 enpi_api.l2.types.api_error.ApiError: If API request fails. 455 456 Example: 457 Export Basket clones into a FASTA file. 458 ```python 459 with EnpiApiClient() as client: 460 id = BasketId(1) 461 export_dir = os.path.join(os.path.dirname(__file__), "example_dir") 462 path = client.basket_api.export_basket_clones_as_fasta( 463 basket_id, 464 fasta_config( 465 include_unique_clone_id_header=True, 466 include_unique_sequence_id_header=True, 467 include_chain_header=True, 468 header_tag_keys=[ 469 "Full Sequence Amino Acids", 470 "Organism", 471 ], 472 sequences=[ 473 FastaSequence( 474 chain=Chain.HEAVY, 475 tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, 476 ), 477 FastaSequence( 478 chain=Chain.KAPPA, 479 tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, 480 ), 481 ], 482 ), 483 output_directory=export_dir, 484 ).wait() 485 print(path) 486 ``` 487 """ 488 489 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a FASTA file...") 490 491 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 492 493 payload = openapi_client.StartClonesExportRequestBody( 494 openapi_client.StartFastaClonesExportRequestBody( 495 format=BasketExportFormat.FASTA, 496 fasta_config=fasta_config.to_api_payload(), 497 ) 498 ) 499 500 with ApiErrorContext(): 501 data = basket_api_instance.start_clones_export(basket_id, payload) 502 assert data.workflow_execution_id is not None 503 504 workflow_execution_id = WorkflowExecutionId(data.workflow_execution_id) 505 506 def on_complete(task_id: WorkflowExecutionTaskId, task_state: TaskState) -> Path: 507 file_api = FileApi(self._inner_api_client, self._log_level) 508 file_path = file_api.download_export_by_workflow_execution_task_id(task_id=task_id, output_directory=output_directory) 509 510 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a FASTA file: '{file_path}'.") 511 return file_path 512 513 waitable = WorkflowExecutionTaskWaitable( 514 workflow_execution_id=workflow_execution_id, on_complete=on_complete, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_EXPORT_FASTA 515 ) 516 517 return Execution(wait=waitable.wait_and_return_result, check_execution_state=waitable.check_execution_state)
21class BasketApi: 22 _inner_api_client: openapi_client.ApiClient 23 _log_level: LogLevel 24 25 def __init__(self, inner_api_client: openapi_client.ApiClient, log_level: LogLevel): 26 """@private""" 27 self._inner_api_client = inner_api_client 28 self._log_level = log_level 29 30 def get_baskets(self) -> list[Basket]: 31 """Get all Baskets that belong to the user or were 32 shared to them by other users. 33 34 Returns: 35 list[enpi_api.l2.types.basket.Basket]: Available Baskets. 36 37 Raises: 38 enpi_api.l2.types.api_error.ApiError: If API request fails. 39 40 Example: 41 Get all available Baskets. 42 ```python 43 with EnpiApiClient() as enpi_client: 44 baskets = enpi_client.basket_api.get_baskets() 45 print(baskets) 46 ``` 47 """ 48 49 logger.info("Getting all available Baskets...") 50 51 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 52 53 with ApiErrorContext(): 54 get_baskets_response = basket_api_instance.get_baskets() 55 56 logger.success(f"Successfully got {len(get_baskets_response.baskets)} Baskets.") 57 58 return [Basket.from_raw(basket) for basket in get_baskets_response.baskets] 59 60 def get_basket(self, basket_id: BasketId) -> Basket: 61 """Get a single Basket matched with the provided Basket ID. 62 63 Args: 64 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to get. 65 66 Returns: 67 enpi_api.l2.types.basket.Basket: Basket matching the provided ID. 68 69 Raises: 70 enpi_api.l2.types.api_error.ApiError: If API request fails. 71 72 Example: 73 Get a single Basket. 74 ```python 75 with EnpiApiClient() as enpi_client: 76 id = BasketId(id) 77 basket = enpi_client.basket_api.get_basket(id) 78 print(basket) 79 ``` 80 """ 81 82 logger.info(f"Getting Basket with ID: '{basket_id}'...") 83 84 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 85 86 with ApiErrorContext(): 87 get_basket_response = basket_api_instance.get_basket(basket_id) 88 89 logger.success(f"Successfully got Basket with ID: '{basket_id}'.") 90 91 return Basket.from_raw(get_basket_response.basket) 92 93 def create_basket(self, name: str, shared: bool | None = True, description: str | None = "") -> Basket: 94 """Create a new Basket. 95 96 Args: 97 name (str): The name of the new Basket. 98 shared (bool | None): Determines if the new Basket will be shared to other users in the organization. 99 By default, all Baskets created via this function are being shared to other users. 100 description (str | None): Description for the Basket. 101 102 Returns: 103 enpi_api.l2.types.basket.Basket: Newly created Basket. 104 105 Raises: 106 enpi_api.l2.types.api_error.ApiError: If API request fails. 107 108 Example: 109 Create a new Basket. 110 ```python 111 with EnpiApiClient() as enpi_client: 112 name = "New Basket" 113 basket = enpi_client.basket_api.create_basket(name) 114 print(basket) 115 ``` 116 """ 117 118 logger.info(f"Creating a new {'shared' if shared else 'private'} Basket with name: '{name}'...") 119 120 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 121 122 payload = openapi_client.CreateBasketRequestBody(name=name, shared=shared, description=description) 123 124 with ApiErrorContext(): 125 create_basket_response = basket_api_instance.create_basket(payload) 126 127 logger.success(f"Successfully created a new Basket named: '{name}'.") 128 129 return Basket.from_raw(create_basket_response.basket) 130 131 def update_basket( 132 self, 133 basket_id: BasketId, 134 name: str | None = None, 135 shared: bool | None = None, 136 description: str | None = None, 137 ) -> None: 138 """Update properties of a Basket matched with the provided Basket ID. 139 140 Args: 141 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be updated. 142 name (str | None): New name for the Basket. If no value is provided, Basket's name won't be changed. 143 shared (bool | None): Determines if a Basket will be shared to other users in the organization. 144 If no value is provided, Basket's shared status won't be changed. 145 description (str | None): New description for the Basket. If no value is provided, Basket's description won't be changed. 146 147 Raises: 148 enpi_api.l2.types.api_error.ApiError: If API request fails. 149 150 Example: 151 Update an existing Basket. 152 ```python 153 with EnpiApiClient() as enpi_client: 154 id = BasketId(id) 155 new_name = "Basket (renamed)" 156 is_basket_shared = True 157 enpi_client.basket_api.update_basket(id, new_name, is_basket_shared) 158 ``` 159 """ 160 161 logger.info(f"Updating Basket with ID: '{basket_id}'...") 162 163 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 164 165 payload = openapi_client.UpdateBasketRequestBody(name=name, shared=shared, description=description) 166 167 with ApiErrorContext(): 168 basket_api_instance.update_basket(basket_id, payload) 169 170 logger.success(f"Successfully updated Basket with ID: '{basket_id}'.") 171 172 def delete_basket(self, basket_id: BasketId) -> None: 173 """Delete a Basket matched with the provided Basket ID. 174 175 Args: 176 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be deleted. 177 178 Raises: 179 enpi_api.l2.types.api_error.ApiError: If API request fails. 180 181 Example: 182 Delete a Basket. 183 ```python 184 with EnpiApiClient() as enpi_client: 185 id = BasketId(id) 186 enpi_client.basket_api.delete_basket(id) 187 ``` 188 """ 189 190 logger.info(f"Deleting Basket with ID: '{basket_id}'...") 191 192 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 193 194 with ApiErrorContext(): 195 basket_api_instance.delete_basket(basket_id) 196 197 logger.info(f"Successfully deleted Basket with ID:'{basket_id}'.") 198 199 def add_clones_to_basket( 200 self, 201 basket_id: BasketId, 202 clone_ids: list[CloneId] | None = None, 203 sequence_ids: list[SequenceId] | None = None, 204 ) -> Execution[None]: 205 """Resolve clones matched with provided clone and sequence IDs, 206 then add them into the target Basket. 207 208 > This functionality uses clone resolving.\n 209 > Clone resolving uses passed clone and sequence IDs in order to resolve clones. 210 > For each clone, a maximum of one *big* chain and one *small* chain sequence will be picked, resulting in a 211 maximum of two sequences per clone. 212 > Sequences matched with passed sequence IDs have priority over internally resolved sequences, meaning that if 213 possible, they will be picked as sequences for the resolved clones. 214 215 Args: 216 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to add clones to. 217 clone_ids (list[enpi_api.l2.types.clone.CloneId]): Clone IDs based on which clones will be resolved and added into the target Basket. 218 sequence_ids (list[enpi_api.l2.types.sequence.SequenceId]): Sequence IDs based on which clones will be resolved and added into 219 the target Basket. If clone resolving based on clone IDs and sequence IDs results in the same, "overlapping" clones (with the same clone IDs) 220 but potentially different sequences within, clones resolved with use of sequence IDs will be picked over the ones resolved with clone IDs. 221 222 Returns: 223 enpi_api.l2.types.execution.Execution[None]: An awaitable execution. 224 225 Raises: 226 ValueError: If the provided clone and/or sequence ID arrays are empty or invalid. 227 enpi_api.l2.types.api_error.ApiError: If API request fails. 228 229 Example: 230 Insert clones into a Basket. 231 ```python 232 with EnpiApiClient() as enpi_client: 233 basket_id = BasketId(1) 234 clone_ids = [ 235 CloneId(id) for id in [ 236 "d0c6982d-34cd-47cd-b465-a603dec0530c", 237 "1c19fcbc-ec84-4baa-a641-42058df18303", 238 ] 239 ] 240 sequence_ids = [SequenceId(id) for id in [100, 101, 102]] 241 enpi_client.basket_api.add_clones_to_basket(basket_id, clone_ids, sequence_ids).wait() 242 ``` 243 """ 244 245 logger.info(f"Adding clones to Basket with ID: '{basket_id}'...") 246 247 # Check if we got any ids to work with 248 if (clone_ids is None or len(clone_ids) == 0) and (sequence_ids is None or len(sequence_ids) == 0): 249 raise ValueError("Both clone and sequence IDs arrays are null, at least one of them needs to contain proper values.") 250 251 # Validate if ID types are right 252 if clone_ids is not None and not all([isinstance(id, str) for id in clone_ids]): 253 raise ValueError("Some of the passed clone IDs are not strings.") 254 elif sequence_ids is not None and not all([isinstance(id, int) for id in sequence_ids]): 255 raise ValueError("Some of the passed sequence IDs are not integers.") 256 257 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 258 259 payload = openapi_client.AddClonesRequestBody( 260 clone_ids=None if clone_ids is None else [str(id) for id in clone_ids], 261 sequence_ids=None if sequence_ids is None else [int(id) for id in sequence_ids], 262 ) 263 264 with ApiErrorContext(): 265 add_clones_response = basket_api_instance.add_clones(basket_id, payload) 266 assert add_clones_response.workflow_execution_id is not None 267 268 workflow_execution_id = WorkflowExecutionId(add_clones_response.workflow_execution_id) 269 waitable = WorkflowExecutionTaskWaitable[None]( 270 workflow_execution_id=workflow_execution_id, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_ADD_CLONES, on_complete=None 271 ) 272 273 return Execution(wait=waitable.wait, check_execution_state=waitable.check_execution_state) 274 275 def remove_clones_from_basket(self, basket_id: BasketId, clone_ids: list[CloneId]) -> Execution[None]: 276 """Remove clones matches with provided clone IDs from the target Basket. 277 278 Args: 279 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be removed. 280 clone_ids (list[enpi_api.l2.types.clone.CloneId]): IDs of clones that will be removed from target Basket. 281 282 Returns: 283 enpi_api.l2.types.execution.Execution[None]: An awaitable execution. 284 285 Raises: 286 ValueError: If the provided clone IDs array is invalid. 287 enpi_api.l2.types.api_error.ApiError: If API request fails. 288 289 Example: 290 Remove clones from a Basket. 291 ```python 292 with EnpiApiClient() as enpi_client: 293 basket_id = BasketId(1) 294 clone_ids = [ 295 CloneId(id) for id in [ 296 "d0c6982d-34cd-47cd-b465-a603dec0530c", 297 "1c19fcbc-ec84-4baa-a641-42058df18303", 298 ] 299 ] 300 enpi_client.basket_api.remove_clones_from_basket(basket_id, clone_ids).wait() 301 ``` 302 """ 303 304 n_of_clone_ids = len(clone_ids) 305 logger.info(f"Removing {n_of_clone_ids} clone{'' if n_of_clone_ids == 1 else 's'} from Basket with id: '{basket_id}'") 306 307 # Check if we got any ids to work with 308 if len(clone_ids) == 0: 309 raise ValueError("Provided clone IDs array is empty.") 310 311 # Validate if ID types are right 312 if not all([isinstance(id, str) for id in clone_ids]): 313 raise ValueError("Some of the passed clone IDs are not strings.") 314 315 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 316 317 payload = openapi_client.RemoveClonesRequestBody( 318 clone_ids=[str(id) for id in clone_ids], 319 ) 320 321 with ApiErrorContext(): 322 remove_clones_response = basket_api_instance.remove_clones(basket_id, payload) 323 assert remove_clones_response.workflow_execution_id is not None 324 325 workflow_execution_id = WorkflowExecutionId(remove_clones_response.workflow_execution_id) 326 327 waitable = WorkflowExecutionTaskWaitable[None]( 328 workflow_execution_id=workflow_execution_id, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_REMOVE_CLONES, on_complete=None 329 ) 330 331 return Execution(wait=waitable.wait, check_execution_state=waitable.check_execution_state) 332 333 def export_basket_clones_as_tsv( 334 self, 335 basket_id: BasketId, 336 tsv_config: TsvExportConfig | None = None, 337 output_directory: Path | str | None = None, 338 ) -> Execution[Path]: 339 """Start a Basket clones export in a TSV format, download the result file and return a path to it. 340 341 Args: 342 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 343 tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export. 344 output_directory (Path | str | None): Path to the directory in which the downloaded file will be stored. 345 If not provided, a temporary directory will be created. 346 347 Returns: 348 enpi_api.l2.types.execution.Execution[Path]: An awaitable execution that returns the local file path to the 349 exported file when awaited. 350 351 Raises: 352 enpi_api.l2.types.api_error.ApiError: If API request fails. 353 354 Example: 355 Export Basket clones into a TSV file. 356 ```python 357 with EnpiApiClient() as enpi_client: 358 id = BasketId(1) 359 export_dir = os.path.join(os.path.dirname(__file__), "example_dir") 360 path = enpi_client.basket_api.export_basket_clones_as_tsv(id, export_dir).wait() 361 print(path) 362 ``` 363 """ 364 365 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a TSV file...") 366 367 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 368 369 payload = openapi_client.StartClonesExportRequestBody( 370 openapi_client.StartTsvClonesExportRequestBody( 371 format=BasketExportFormat.TSV, tsv_config=tsv_config.to_api_payload() if tsv_config is not None else None 372 ) 373 ) 374 375 with ApiErrorContext(): 376 data = basket_api_instance.start_clones_export(basket_id, payload) 377 assert data.workflow_execution_id is not None 378 379 workflow_execution_id = WorkflowExecutionId(data.workflow_execution_id) 380 381 def on_complete(task_id: WorkflowExecutionTaskId, task_state: TaskState) -> Path: 382 with ApiErrorContext(): 383 file_api = FileApi(self._inner_api_client, self._log_level) 384 file_path = file_api.download_export_by_workflow_execution_task_id(task_id=task_id, output_directory=output_directory) 385 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a TSV file: '{file_path}'.") 386 return file_path 387 388 waitable = WorkflowExecutionTaskWaitable[Path]( 389 workflow_execution_id=workflow_execution_id, on_complete=on_complete, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_EXPORT 390 ) 391 392 return Execution(wait=waitable.wait_and_return_result, check_execution_state=waitable.check_execution_state) 393 394 def export_basket_clones_as_df(self, basket_id: BasketId, tsv_config: TsvExportConfig | None = None) -> Execution[pd.DataFrame]: 395 """Start a Basket clones export in a TSV format, download the result and return 396 the data from it in a DataFrame object. 397 398 Args: 399 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 400 tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export. 401 402 Returns: 403 enpi_api.l2.types.execution.Execution[pd.DataFrame]: An awaitable execution that returns a pandas DataFrame 404 object containing the exported data when awaited. 405 406 Raises: 407 enpi_api.l2.types.api_error.ApiError: If API request fails. 408 409 Example: 410 Export Basket clones into a DataFrame. 411 ```python 412 with EnpiApiClient() as client: 413 id = BasketId(1) 414 df = client.basket_api.export_basket_clones_as_df(id).wait() 415 print(df) 416 ``` 417 """ 418 419 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a DataFrame...") 420 421 with tempfile.TemporaryDirectory() as temp_dir: 422 execution = self.export_basket_clones_as_tsv(basket_id=basket_id, tsv_config=tsv_config, output_directory=temp_dir) 423 424 def wait() -> pd.DataFrame: 425 tmp_file_path = execution.wait() 426 df = pd.read_csv(tmp_file_path, delimiter="\t") 427 428 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a DataFrame.") 429 430 return df 431 432 return Execution(wait=wait, check_execution_state=execution.check_execution_state) 433 434 def export_basket_clones_as_fasta( 435 self, 436 basket_id: BasketId, 437 fasta_config: FastaExportConfig, 438 output_directory: Path | str | None = None, 439 ) -> Execution[Path]: 440 """Start a Basket clones export in a FASTA format, download the result and return the filepath to the file. 441 442 Args: 443 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 444 fasta_config (enpi_api.l2.types.basket.FastaExportConfig): Configuration of the Basket FASTA export, determining the 445 shape of FASTA file headers and sequences. The enpi_api.l2.types.basket.fasta_config function is the prefered way of 446 a configuration object creation. 447 output_directory (Path | str | None): Path to a directory in which the downloaded file will be stored. 448 If not provided, a temporary directory will be created. 449 450 Returns: 451 enpi_api.l2.types.execution.Execution[Path]: An awaitable that returns information about clones added to the 452 Basket when awaited. 453 454 Raises: 455 enpi_api.l2.types.api_error.ApiError: If API request fails. 456 457 Example: 458 Export Basket clones into a FASTA file. 459 ```python 460 with EnpiApiClient() as client: 461 id = BasketId(1) 462 export_dir = os.path.join(os.path.dirname(__file__), "example_dir") 463 path = client.basket_api.export_basket_clones_as_fasta( 464 basket_id, 465 fasta_config( 466 include_unique_clone_id_header=True, 467 include_unique_sequence_id_header=True, 468 include_chain_header=True, 469 header_tag_keys=[ 470 "Full Sequence Amino Acids", 471 "Organism", 472 ], 473 sequences=[ 474 FastaSequence( 475 chain=Chain.HEAVY, 476 tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, 477 ), 478 FastaSequence( 479 chain=Chain.KAPPA, 480 tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, 481 ), 482 ], 483 ), 484 output_directory=export_dir, 485 ).wait() 486 print(path) 487 ``` 488 """ 489 490 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a FASTA file...") 491 492 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 493 494 payload = openapi_client.StartClonesExportRequestBody( 495 openapi_client.StartFastaClonesExportRequestBody( 496 format=BasketExportFormat.FASTA, 497 fasta_config=fasta_config.to_api_payload(), 498 ) 499 ) 500 501 with ApiErrorContext(): 502 data = basket_api_instance.start_clones_export(basket_id, payload) 503 assert data.workflow_execution_id is not None 504 505 workflow_execution_id = WorkflowExecutionId(data.workflow_execution_id) 506 507 def on_complete(task_id: WorkflowExecutionTaskId, task_state: TaskState) -> Path: 508 file_api = FileApi(self._inner_api_client, self._log_level) 509 file_path = file_api.download_export_by_workflow_execution_task_id(task_id=task_id, output_directory=output_directory) 510 511 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a FASTA file: '{file_path}'.") 512 return file_path 513 514 waitable = WorkflowExecutionTaskWaitable( 515 workflow_execution_id=workflow_execution_id, on_complete=on_complete, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_EXPORT_FASTA 516 ) 517 518 return Execution(wait=waitable.wait_and_return_result, check_execution_state=waitable.check_execution_state)
30 def get_baskets(self) -> list[Basket]: 31 """Get all Baskets that belong to the user or were 32 shared to them by other users. 33 34 Returns: 35 list[enpi_api.l2.types.basket.Basket]: Available Baskets. 36 37 Raises: 38 enpi_api.l2.types.api_error.ApiError: If API request fails. 39 40 Example: 41 Get all available Baskets. 42 ```python 43 with EnpiApiClient() as enpi_client: 44 baskets = enpi_client.basket_api.get_baskets() 45 print(baskets) 46 ``` 47 """ 48 49 logger.info("Getting all available Baskets...") 50 51 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 52 53 with ApiErrorContext(): 54 get_baskets_response = basket_api_instance.get_baskets() 55 56 logger.success(f"Successfully got {len(get_baskets_response.baskets)} Baskets.") 57 58 return [Basket.from_raw(basket) for basket in get_baskets_response.baskets]
Get all Baskets that belong to the user or were shared to them by other users.
Returns:
list[enpi_api.l2.types.basket.Basket]: Available Baskets.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Get all available Baskets.
with EnpiApiClient() as enpi_client: baskets = enpi_client.basket_api.get_baskets() print(baskets)
60 def get_basket(self, basket_id: BasketId) -> Basket: 61 """Get a single Basket matched with the provided Basket ID. 62 63 Args: 64 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to get. 65 66 Returns: 67 enpi_api.l2.types.basket.Basket: Basket matching the provided ID. 68 69 Raises: 70 enpi_api.l2.types.api_error.ApiError: If API request fails. 71 72 Example: 73 Get a single Basket. 74 ```python 75 with EnpiApiClient() as enpi_client: 76 id = BasketId(id) 77 basket = enpi_client.basket_api.get_basket(id) 78 print(basket) 79 ``` 80 """ 81 82 logger.info(f"Getting Basket with ID: '{basket_id}'...") 83 84 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 85 86 with ApiErrorContext(): 87 get_basket_response = basket_api_instance.get_basket(basket_id) 88 89 logger.success(f"Successfully got Basket with ID: '{basket_id}'.") 90 91 return Basket.from_raw(get_basket_response.basket)
Get a single Basket matched with the provided Basket ID.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to get.
Returns:
enpi_api.l2.types.basket.Basket: Basket matching the provided ID.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Get a single Basket.
with EnpiApiClient() as enpi_client: id = BasketId(id) basket = enpi_client.basket_api.get_basket(id) print(basket)
93 def create_basket(self, name: str, shared: bool | None = True, description: str | None = "") -> Basket: 94 """Create a new Basket. 95 96 Args: 97 name (str): The name of the new Basket. 98 shared (bool | None): Determines if the new Basket will be shared to other users in the organization. 99 By default, all Baskets created via this function are being shared to other users. 100 description (str | None): Description for the Basket. 101 102 Returns: 103 enpi_api.l2.types.basket.Basket: Newly created Basket. 104 105 Raises: 106 enpi_api.l2.types.api_error.ApiError: If API request fails. 107 108 Example: 109 Create a new Basket. 110 ```python 111 with EnpiApiClient() as enpi_client: 112 name = "New Basket" 113 basket = enpi_client.basket_api.create_basket(name) 114 print(basket) 115 ``` 116 """ 117 118 logger.info(f"Creating a new {'shared' if shared else 'private'} Basket with name: '{name}'...") 119 120 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 121 122 payload = openapi_client.CreateBasketRequestBody(name=name, shared=shared, description=description) 123 124 with ApiErrorContext(): 125 create_basket_response = basket_api_instance.create_basket(payload) 126 127 logger.success(f"Successfully created a new Basket named: '{name}'.") 128 129 return Basket.from_raw(create_basket_response.basket)
Create a new Basket.
Arguments:
- name (str): The name of the new Basket.
- shared (bool | None): Determines if the new Basket will be shared to other users in the organization. By default, all Baskets created via this function are being shared to other users.
- description (str | None): Description for the Basket.
Returns:
enpi_api.l2.types.basket.Basket: Newly created Basket.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Create a new Basket.
with EnpiApiClient() as enpi_client: name = "New Basket" basket = enpi_client.basket_api.create_basket(name) print(basket)
131 def update_basket( 132 self, 133 basket_id: BasketId, 134 name: str | None = None, 135 shared: bool | None = None, 136 description: str | None = None, 137 ) -> None: 138 """Update properties of a Basket matched with the provided Basket ID. 139 140 Args: 141 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be updated. 142 name (str | None): New name for the Basket. If no value is provided, Basket's name won't be changed. 143 shared (bool | None): Determines if a Basket will be shared to other users in the organization. 144 If no value is provided, Basket's shared status won't be changed. 145 description (str | None): New description for the Basket. If no value is provided, Basket's description won't be changed. 146 147 Raises: 148 enpi_api.l2.types.api_error.ApiError: If API request fails. 149 150 Example: 151 Update an existing Basket. 152 ```python 153 with EnpiApiClient() as enpi_client: 154 id = BasketId(id) 155 new_name = "Basket (renamed)" 156 is_basket_shared = True 157 enpi_client.basket_api.update_basket(id, new_name, is_basket_shared) 158 ``` 159 """ 160 161 logger.info(f"Updating Basket with ID: '{basket_id}'...") 162 163 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 164 165 payload = openapi_client.UpdateBasketRequestBody(name=name, shared=shared, description=description) 166 167 with ApiErrorContext(): 168 basket_api_instance.update_basket(basket_id, payload) 169 170 logger.success(f"Successfully updated Basket with ID: '{basket_id}'.")
Update properties of a Basket matched with the provided Basket ID.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be updated.
- name (str | None): New name for the Basket. If no value is provided, Basket's name won't be changed.
- shared (bool | None): Determines if a Basket will be shared to other users in the organization. If no value is provided, Basket's shared status won't be changed.
- description (str | None): New description for the Basket. If no value is provided, Basket's description won't be changed.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Update an existing Basket.
with EnpiApiClient() as enpi_client: id = BasketId(id) new_name = "Basket (renamed)" is_basket_shared = True enpi_client.basket_api.update_basket(id, new_name, is_basket_shared)
172 def delete_basket(self, basket_id: BasketId) -> None: 173 """Delete a Basket matched with the provided Basket ID. 174 175 Args: 176 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be deleted. 177 178 Raises: 179 enpi_api.l2.types.api_error.ApiError: If API request fails. 180 181 Example: 182 Delete a Basket. 183 ```python 184 with EnpiApiClient() as enpi_client: 185 id = BasketId(id) 186 enpi_client.basket_api.delete_basket(id) 187 ``` 188 """ 189 190 logger.info(f"Deleting Basket with ID: '{basket_id}'...") 191 192 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 193 194 with ApiErrorContext(): 195 basket_api_instance.delete_basket(basket_id) 196 197 logger.info(f"Successfully deleted Basket with ID:'{basket_id}'.")
Delete a Basket matched with the provided Basket ID.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to be deleted.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Delete a Basket.
with EnpiApiClient() as enpi_client: id = BasketId(id) enpi_client.basket_api.delete_basket(id)
199 def add_clones_to_basket( 200 self, 201 basket_id: BasketId, 202 clone_ids: list[CloneId] | None = None, 203 sequence_ids: list[SequenceId] | None = None, 204 ) -> Execution[None]: 205 """Resolve clones matched with provided clone and sequence IDs, 206 then add them into the target Basket. 207 208 > This functionality uses clone resolving.\n 209 > Clone resolving uses passed clone and sequence IDs in order to resolve clones. 210 > For each clone, a maximum of one *big* chain and one *small* chain sequence will be picked, resulting in a 211 maximum of two sequences per clone. 212 > Sequences matched with passed sequence IDs have priority over internally resolved sequences, meaning that if 213 possible, they will be picked as sequences for the resolved clones. 214 215 Args: 216 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to add clones to. 217 clone_ids (list[enpi_api.l2.types.clone.CloneId]): Clone IDs based on which clones will be resolved and added into the target Basket. 218 sequence_ids (list[enpi_api.l2.types.sequence.SequenceId]): Sequence IDs based on which clones will be resolved and added into 219 the target Basket. If clone resolving based on clone IDs and sequence IDs results in the same, "overlapping" clones (with the same clone IDs) 220 but potentially different sequences within, clones resolved with use of sequence IDs will be picked over the ones resolved with clone IDs. 221 222 Returns: 223 enpi_api.l2.types.execution.Execution[None]: An awaitable execution. 224 225 Raises: 226 ValueError: If the provided clone and/or sequence ID arrays are empty or invalid. 227 enpi_api.l2.types.api_error.ApiError: If API request fails. 228 229 Example: 230 Insert clones into a Basket. 231 ```python 232 with EnpiApiClient() as enpi_client: 233 basket_id = BasketId(1) 234 clone_ids = [ 235 CloneId(id) for id in [ 236 "d0c6982d-34cd-47cd-b465-a603dec0530c", 237 "1c19fcbc-ec84-4baa-a641-42058df18303", 238 ] 239 ] 240 sequence_ids = [SequenceId(id) for id in [100, 101, 102]] 241 enpi_client.basket_api.add_clones_to_basket(basket_id, clone_ids, sequence_ids).wait() 242 ``` 243 """ 244 245 logger.info(f"Adding clones to Basket with ID: '{basket_id}'...") 246 247 # Check if we got any ids to work with 248 if (clone_ids is None or len(clone_ids) == 0) and (sequence_ids is None or len(sequence_ids) == 0): 249 raise ValueError("Both clone and sequence IDs arrays are null, at least one of them needs to contain proper values.") 250 251 # Validate if ID types are right 252 if clone_ids is not None and not all([isinstance(id, str) for id in clone_ids]): 253 raise ValueError("Some of the passed clone IDs are not strings.") 254 elif sequence_ids is not None and not all([isinstance(id, int) for id in sequence_ids]): 255 raise ValueError("Some of the passed sequence IDs are not integers.") 256 257 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 258 259 payload = openapi_client.AddClonesRequestBody( 260 clone_ids=None if clone_ids is None else [str(id) for id in clone_ids], 261 sequence_ids=None if sequence_ids is None else [int(id) for id in sequence_ids], 262 ) 263 264 with ApiErrorContext(): 265 add_clones_response = basket_api_instance.add_clones(basket_id, payload) 266 assert add_clones_response.workflow_execution_id is not None 267 268 workflow_execution_id = WorkflowExecutionId(add_clones_response.workflow_execution_id) 269 waitable = WorkflowExecutionTaskWaitable[None]( 270 workflow_execution_id=workflow_execution_id, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_ADD_CLONES, on_complete=None 271 ) 272 273 return Execution(wait=waitable.wait, check_execution_state=waitable.check_execution_state)
Resolve clones matched with provided clone and sequence IDs, then add them into the target Basket.
This functionality uses clone resolving.
Clone resolving uses passed clone and sequence IDs in order to resolve clones. For each clone, a maximum of one big chain and one small chain sequence will be picked, resulting in a maximum of two sequences per clone. Sequences matched with passed sequence IDs have priority over internally resolved sequences, meaning that if possible, they will be picked as sequences for the resolved clones.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket to add clones to.
- clone_ids (list[enpi_api.l2.types.clone.CloneId]): Clone IDs based on which clones will be resolved and added into the target Basket.
- sequence_ids (list[enpi_api.l2.types.sequence.SequenceId]): Sequence IDs based on which clones will be resolved and added into
- the target Basket. If clone resolving based on clone IDs and sequence IDs results in the same, "overlapping" clones (with the same clone IDs)
- but potentially different sequences within, clones resolved with use of sequence IDs will be picked over the ones resolved with clone IDs.
Returns:
enpi_api.l2.types.execution.Execution[None]: An awaitable execution.
Raises:
- ValueError: If the provided clone and/or sequence ID arrays are empty or invalid.
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Insert clones into a Basket.
with EnpiApiClient() as enpi_client: basket_id = BasketId(1) clone_ids = [ CloneId(id) for id in [ "d0c6982d-34cd-47cd-b465-a603dec0530c", "1c19fcbc-ec84-4baa-a641-42058df18303", ] ] sequence_ids = [SequenceId(id) for id in [100, 101, 102]] enpi_client.basket_api.add_clones_to_basket(basket_id, clone_ids, sequence_ids).wait()
275 def remove_clones_from_basket(self, basket_id: BasketId, clone_ids: list[CloneId]) -> Execution[None]: 276 """Remove clones matches with provided clone IDs from the target Basket. 277 278 Args: 279 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be removed. 280 clone_ids (list[enpi_api.l2.types.clone.CloneId]): IDs of clones that will be removed from target Basket. 281 282 Returns: 283 enpi_api.l2.types.execution.Execution[None]: An awaitable execution. 284 285 Raises: 286 ValueError: If the provided clone IDs array is invalid. 287 enpi_api.l2.types.api_error.ApiError: If API request fails. 288 289 Example: 290 Remove clones from a Basket. 291 ```python 292 with EnpiApiClient() as enpi_client: 293 basket_id = BasketId(1) 294 clone_ids = [ 295 CloneId(id) for id in [ 296 "d0c6982d-34cd-47cd-b465-a603dec0530c", 297 "1c19fcbc-ec84-4baa-a641-42058df18303", 298 ] 299 ] 300 enpi_client.basket_api.remove_clones_from_basket(basket_id, clone_ids).wait() 301 ``` 302 """ 303 304 n_of_clone_ids = len(clone_ids) 305 logger.info(f"Removing {n_of_clone_ids} clone{'' if n_of_clone_ids == 1 else 's'} from Basket with id: '{basket_id}'") 306 307 # Check if we got any ids to work with 308 if len(clone_ids) == 0: 309 raise ValueError("Provided clone IDs array is empty.") 310 311 # Validate if ID types are right 312 if not all([isinstance(id, str) for id in clone_ids]): 313 raise ValueError("Some of the passed clone IDs are not strings.") 314 315 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 316 317 payload = openapi_client.RemoveClonesRequestBody( 318 clone_ids=[str(id) for id in clone_ids], 319 ) 320 321 with ApiErrorContext(): 322 remove_clones_response = basket_api_instance.remove_clones(basket_id, payload) 323 assert remove_clones_response.workflow_execution_id is not None 324 325 workflow_execution_id = WorkflowExecutionId(remove_clones_response.workflow_execution_id) 326 327 waitable = WorkflowExecutionTaskWaitable[None]( 328 workflow_execution_id=workflow_execution_id, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_REMOVE_CLONES, on_complete=None 329 ) 330 331 return Execution(wait=waitable.wait, check_execution_state=waitable.check_execution_state)
Remove clones matches with provided clone IDs from the target Basket.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be removed.
- clone_ids (list[enpi_api.l2.types.clone.CloneId]): IDs of clones that will be removed from target Basket.
Returns:
enpi_api.l2.types.execution.Execution[None]: An awaitable execution.
Raises:
- ValueError: If the provided clone IDs array is invalid.
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Remove clones from a Basket.
with EnpiApiClient() as enpi_client: basket_id = BasketId(1) clone_ids = [ CloneId(id) for id in [ "d0c6982d-34cd-47cd-b465-a603dec0530c", "1c19fcbc-ec84-4baa-a641-42058df18303", ] ] enpi_client.basket_api.remove_clones_from_basket(basket_id, clone_ids).wait()
333 def export_basket_clones_as_tsv( 334 self, 335 basket_id: BasketId, 336 tsv_config: TsvExportConfig | None = None, 337 output_directory: Path | str | None = None, 338 ) -> Execution[Path]: 339 """Start a Basket clones export in a TSV format, download the result file and return a path to it. 340 341 Args: 342 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 343 tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export. 344 output_directory (Path | str | None): Path to the directory in which the downloaded file will be stored. 345 If not provided, a temporary directory will be created. 346 347 Returns: 348 enpi_api.l2.types.execution.Execution[Path]: An awaitable execution that returns the local file path to the 349 exported file when awaited. 350 351 Raises: 352 enpi_api.l2.types.api_error.ApiError: If API request fails. 353 354 Example: 355 Export Basket clones into a TSV file. 356 ```python 357 with EnpiApiClient() as enpi_client: 358 id = BasketId(1) 359 export_dir = os.path.join(os.path.dirname(__file__), "example_dir") 360 path = enpi_client.basket_api.export_basket_clones_as_tsv(id, export_dir).wait() 361 print(path) 362 ``` 363 """ 364 365 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a TSV file...") 366 367 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 368 369 payload = openapi_client.StartClonesExportRequestBody( 370 openapi_client.StartTsvClonesExportRequestBody( 371 format=BasketExportFormat.TSV, tsv_config=tsv_config.to_api_payload() if tsv_config is not None else None 372 ) 373 ) 374 375 with ApiErrorContext(): 376 data = basket_api_instance.start_clones_export(basket_id, payload) 377 assert data.workflow_execution_id is not None 378 379 workflow_execution_id = WorkflowExecutionId(data.workflow_execution_id) 380 381 def on_complete(task_id: WorkflowExecutionTaskId, task_state: TaskState) -> Path: 382 with ApiErrorContext(): 383 file_api = FileApi(self._inner_api_client, self._log_level) 384 file_path = file_api.download_export_by_workflow_execution_task_id(task_id=task_id, output_directory=output_directory) 385 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a TSV file: '{file_path}'.") 386 return file_path 387 388 waitable = WorkflowExecutionTaskWaitable[Path]( 389 workflow_execution_id=workflow_execution_id, on_complete=on_complete, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_EXPORT 390 ) 391 392 return Execution(wait=waitable.wait_and_return_result, check_execution_state=waitable.check_execution_state)
Start a Basket clones export in a TSV format, download the result file and return a path to it.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported.
- tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export.
- output_directory (Path | str | None): Path to the directory in which the downloaded file will be stored. If not provided, a temporary directory will be created.
Returns:
enpi_api.l2.types.execution.Execution[Path]: An awaitable execution that returns the local file path to the exported file when awaited.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Export Basket clones into a TSV file.
with EnpiApiClient() as enpi_client: id = BasketId(1) export_dir = os.path.join(os.path.dirname(__file__), "example_dir") path = enpi_client.basket_api.export_basket_clones_as_tsv(id, export_dir).wait() print(path)
394 def export_basket_clones_as_df(self, basket_id: BasketId, tsv_config: TsvExportConfig | None = None) -> Execution[pd.DataFrame]: 395 """Start a Basket clones export in a TSV format, download the result and return 396 the data from it in a DataFrame object. 397 398 Args: 399 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 400 tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export. 401 402 Returns: 403 enpi_api.l2.types.execution.Execution[pd.DataFrame]: An awaitable execution that returns a pandas DataFrame 404 object containing the exported data when awaited. 405 406 Raises: 407 enpi_api.l2.types.api_error.ApiError: If API request fails. 408 409 Example: 410 Export Basket clones into a DataFrame. 411 ```python 412 with EnpiApiClient() as client: 413 id = BasketId(1) 414 df = client.basket_api.export_basket_clones_as_df(id).wait() 415 print(df) 416 ``` 417 """ 418 419 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a DataFrame...") 420 421 with tempfile.TemporaryDirectory() as temp_dir: 422 execution = self.export_basket_clones_as_tsv(basket_id=basket_id, tsv_config=tsv_config, output_directory=temp_dir) 423 424 def wait() -> pd.DataFrame: 425 tmp_file_path = execution.wait() 426 df = pd.read_csv(tmp_file_path, delimiter="\t") 427 428 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a DataFrame.") 429 430 return df 431 432 return Execution(wait=wait, check_execution_state=execution.check_execution_state)
Start a Basket clones export in a TSV format, download the result and return the data from it in a DataFrame object.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported.
- tsv_config (enpi_api.l2.types.basket.TsvExportConfig | None): The configuration for the TSV export.
Returns:
enpi_api.l2.types.execution.Execution[pd.DataFrame]: An awaitable execution that returns a pandas DataFrame object containing the exported data when awaited.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Export Basket clones into a DataFrame.
with EnpiApiClient() as client: id = BasketId(1) df = client.basket_api.export_basket_clones_as_df(id).wait() print(df)
434 def export_basket_clones_as_fasta( 435 self, 436 basket_id: BasketId, 437 fasta_config: FastaExportConfig, 438 output_directory: Path | str | None = None, 439 ) -> Execution[Path]: 440 """Start a Basket clones export in a FASTA format, download the result and return the filepath to the file. 441 442 Args: 443 basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported. 444 fasta_config (enpi_api.l2.types.basket.FastaExportConfig): Configuration of the Basket FASTA export, determining the 445 shape of FASTA file headers and sequences. The enpi_api.l2.types.basket.fasta_config function is the prefered way of 446 a configuration object creation. 447 output_directory (Path | str | None): Path to a directory in which the downloaded file will be stored. 448 If not provided, a temporary directory will be created. 449 450 Returns: 451 enpi_api.l2.types.execution.Execution[Path]: An awaitable that returns information about clones added to the 452 Basket when awaited. 453 454 Raises: 455 enpi_api.l2.types.api_error.ApiError: If API request fails. 456 457 Example: 458 Export Basket clones into a FASTA file. 459 ```python 460 with EnpiApiClient() as client: 461 id = BasketId(1) 462 export_dir = os.path.join(os.path.dirname(__file__), "example_dir") 463 path = client.basket_api.export_basket_clones_as_fasta( 464 basket_id, 465 fasta_config( 466 include_unique_clone_id_header=True, 467 include_unique_sequence_id_header=True, 468 include_chain_header=True, 469 header_tag_keys=[ 470 "Full Sequence Amino Acids", 471 "Organism", 472 ], 473 sequences=[ 474 FastaSequence( 475 chain=Chain.HEAVY, 476 tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, 477 ), 478 FastaSequence( 479 chain=Chain.KAPPA, 480 tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, 481 ), 482 ], 483 ), 484 output_directory=export_dir, 485 ).wait() 486 print(path) 487 ``` 488 """ 489 490 logger.info(f"Exporting clones from Basket with ID: '{basket_id}' into a FASTA file...") 491 492 basket_api_instance = openapi_client.BasketApi(self._inner_api_client) 493 494 payload = openapi_client.StartClonesExportRequestBody( 495 openapi_client.StartFastaClonesExportRequestBody( 496 format=BasketExportFormat.FASTA, 497 fasta_config=fasta_config.to_api_payload(), 498 ) 499 ) 500 501 with ApiErrorContext(): 502 data = basket_api_instance.start_clones_export(basket_id, payload) 503 assert data.workflow_execution_id is not None 504 505 workflow_execution_id = WorkflowExecutionId(data.workflow_execution_id) 506 507 def on_complete(task_id: WorkflowExecutionTaskId, task_state: TaskState) -> Path: 508 file_api = FileApi(self._inner_api_client, self._log_level) 509 file_path = file_api.download_export_by_workflow_execution_task_id(task_id=task_id, output_directory=output_directory) 510 511 logger.success(f"Successfully exported clones from Basket with ID: '{basket_id}' into a FASTA file: '{file_path}'.") 512 return file_path 513 514 waitable = WorkflowExecutionTaskWaitable( 515 workflow_execution_id=workflow_execution_id, on_complete=on_complete, task_template_name=WorkflowTaskTemplateName.ENPI_APP_BASKET_EXPORT_FASTA 516 ) 517 518 return Execution(wait=waitable.wait_and_return_result, check_execution_state=waitable.check_execution_state)
Start a Basket clones export in a FASTA format, download the result and return the filepath to the file.
Arguments:
- basket_id (enpi_api.l2.types.basket.BasketId): ID of a Basket from which clones will be exported.
- fasta_config (enpi_api.l2.types.basket.FastaExportConfig): Configuration of the Basket FASTA export, determining the shape of FASTA file headers and sequences. The enpi_api.l2.types.basket.fasta_config function is the prefered way of a configuration object creation.
- output_directory (Path | str | None): Path to a directory in which the downloaded file will be stored. If not provided, a temporary directory will be created.
Returns:
enpi_api.l2.types.execution.Execution[Path]: An awaitable that returns information about clones added to the Basket when awaited.
Raises:
- enpi_api.l2.types.api_error.ApiError: If API request fails.
Example:
Export Basket clones into a FASTA file.
with EnpiApiClient() as client: id = BasketId(1) export_dir = os.path.join(os.path.dirname(__file__), "example_dir") path = client.basket_api.export_basket_clones_as_fasta( basket_id, fasta_config( include_unique_clone_id_header=True, include_unique_sequence_id_header=True, include_chain_header=True, header_tag_keys=[ "Full Sequence Amino Acids", "Organism", ], sequences=[ FastaSequence( chain=Chain.HEAVY, tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, ), FastaSequence( chain=Chain.KAPPA, tag_key=FastaExportSequenceKey.CDR3_AMINO_ACIDS, ), ], ), output_directory=export_dir, ).wait() print(path)