ENPICOM Logo API Docs Python SDK Docs Events

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)
class BasketApi:
 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)
def get_baskets(self) -> list[enpi_api.l2.types.basket.Basket]:
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:
Example:

Get all available Baskets.

with EnpiApiClient() as enpi_client:
    baskets = enpi_client.basket_api.get_baskets()
    print(baskets)
def get_basket( self, basket_id: enpi_api.l2.types.basket.BasketId) -> enpi_api.l2.types.basket.Basket:
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:
Returns:

enpi_api.l2.types.basket.Basket: Basket matching the provided ID.

Raises:
Example:

Get a single Basket.

with EnpiApiClient() as enpi_client:
    id = BasketId(id)
    basket = enpi_client.basket_api.get_basket(id)
    print(basket)
def create_basket( self, name: str, shared: bool | None = True, description: str | None = '') -> enpi_api.l2.types.basket.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:
Example:

Create a new Basket.

with EnpiApiClient() as enpi_client:
    name = "New Basket"
    basket = enpi_client.basket_api.create_basket(name)
    print(basket)
def update_basket( self, basket_id: enpi_api.l2.types.basket.BasketId, name: str | None = None, shared: bool | None = None, description: str | None = None) -> None:
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:
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)
def delete_basket(self, basket_id: enpi_api.l2.types.basket.BasketId) -> None:
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:
Raises:
Example:

Delete a Basket.

with EnpiApiClient() as enpi_client:
    id = BasketId(id)
    enpi_client.basket_api.delete_basket(id)
def add_clones_to_basket( self, basket_id: enpi_api.l2.types.basket.BasketId, clone_ids: list[enpi_api.l2.types.clone.CloneId] | None = None, sequence_ids: list[enpi_api.l2.types.sequence.SequenceId] | None = None) -> enpi_api.l2.types.execution.Execution[NoneType]:
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:
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()
def remove_clones_from_basket( self, basket_id: enpi_api.l2.types.basket.BasketId, clone_ids: list[enpi_api.l2.types.clone.CloneId]) -> enpi_api.l2.types.execution.Execution[NoneType]:
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:
Returns:

enpi_api.l2.types.execution.Execution[None]: An awaitable execution.

Raises:
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()
def export_basket_clones_as_tsv( self, basket_id: enpi_api.l2.types.basket.BasketId, tsv_config: enpi_api.l2.types.basket.TsvExportConfig | None = None, output_directory: pathlib.Path | str | None = None) -> enpi_api.l2.types.execution.Execution[Path]:
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:
Returns:

enpi_api.l2.types.execution.Execution[Path]: An awaitable execution that returns the local file path to the exported file when awaited.

Raises:
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)
def export_basket_clones_as_df( self, basket_id: enpi_api.l2.types.basket.BasketId, tsv_config: enpi_api.l2.types.basket.TsvExportConfig | None = None) -> enpi_api.l2.types.execution.Execution[DataFrame]:
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:
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:
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)
def export_basket_clones_as_fasta( self, basket_id: enpi_api.l2.types.basket.BasketId, fasta_config: enpi_api.l2.types.basket.FastaExportConfig, output_directory: pathlib.Path | str | None = None) -> enpi_api.l2.types.execution.Execution[Path]:
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:
Returns:

enpi_api.l2.types.execution.Execution[Path]: An awaitable that returns information about clones added to the Basket when awaited.

Raises:
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)