diff -pruN 2.3.0-1/README.md 2.4.0-1/README.md
--- 2.3.0-1/README.md	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/README.md	2025-09-02 12:47:29.000000000 +0000
@@ -38,13 +38,20 @@ Or in a directory containing multiple mo
 prodigy <directory_with_molecules>
 ```
 
-To get a list of all the possible options.
+Or using a multi-model input PDB file (an ensemble)
 
 ```bash
+prodigy <multi_model.pdb>
+```
 
+> If you are running several structures, try using the `-np` argument to run
+> in multiple processors
+
+To get a list of all the possible options.
+
+```bash
 $ prodigy -h
-usage: prodigy [-h] [--distance-cutoff DISTANCE_CUTOFF] [--acc-threshold ACC_THRESHOLD]
-               [--temperature TEMPERATURE] [--contact_list] [--pymol_selection] [-q]
+usage: prodigy [-h] [--distance-cutoff DISTANCE_CUTOFF] [--acc-threshold ACC_THRESHOLD] [--temperature TEMPERATURE] [--contact_list] [--pymol_selection] [-q] [-np NUMBER_OF_PROCESSORS]
                [--selection A B [A,B C ...]]
                input_path
 
@@ -66,6 +73,8 @@ options:
   --contact_list        Output a list of contacts
   --pymol_selection     Output a script to highlight the interface (pymol)
   -q, --quiet           Outputs only the predicted affinity value
+  -np, --number-of-processors NUMBER_OF_PROCESSORS
+                        Number of processors to use (default: 1)
 
 Selection Options:
 
@@ -83,8 +92,6 @@ Selection Options:
   --selection A B => Contacts calculated (only) between chains A and B.
   --selection A,B C => Contacts calculated (only) between     chains A and C; and B and C.
   --selection A B C => Contacts calculated (only) between     chains A and B; B and C; and A and C.
-
-  --selection A B [A,B C ...]
 ```
 
 ## Example single structure
@@ -127,10 +134,11 @@ curl -o input/2oob.pdb https://files.rcs
 curl -o input/1ppe.pdb https://files.rcsb.org/download/1PPE.pdb
 ```
 
-Run `prodigy` with the `quiet` option, so it is easier to parse the output later:
+Run `prodigy` with the `quiet` option, so it is easier to parse the output later
+and run it with 2 processors via the `np` option.
 
 ```bash
-$ prodigy -q input/
+$ prodigy -q -np 2 input/
 3bzd  -9.373
 2oob  -6.230
 1ppe -14.727
diff -pruN 2.3.0-1/debian/changelog 2.4.0-1/debian/changelog
--- 2.3.0-1/debian/changelog	2025-08-26 11:48:01.000000000 +0000
+++ 2.4.0-1/debian/changelog	2025-09-08 07:23:03.000000000 +0000
@@ -1,3 +1,9 @@
+python-prodigy (2.4.0-1) unstable; urgency=medium
+
+  * New upstream version 2.4.0
+
+ -- Andrius Merkys <merkys@debian.org>  Mon, 08 Sep 2025 03:23:03 -0400
+
 python-prodigy (2.3.0-1) unstable; urgency=medium
 
   * Upload to unstable.
diff -pruN 2.3.0-1/pyproject.toml 2.4.0-1/pyproject.toml
--- 2.3.0-1/pyproject.toml	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/pyproject.toml	2025-09-02 12:47:29.000000000 +0000
@@ -1,7 +1,7 @@
 [project]
 name = "prodigy-prot"
 license = "Apache-2.0"
-version = "2.3.0"
+version = "2.4.0"
 description = "PROtein binDIng enerGY prediction"
 authors = [
   { name = "Anna Vangone" },
diff -pruN 2.3.0-1/src/prodigy_prot/cli.py 2.4.0-1/src/prodigy_prot/cli.py
--- 2.3.0-1/src/prodigy_prot/cli.py	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/src/prodigy_prot/cli.py	2025-09-02 12:47:29.000000000 +0000
@@ -6,12 +6,13 @@ import argparse
 import logging
 import sys
 from argparse import RawTextHelpFormatter
+from concurrent.futures import ProcessPoolExecutor, as_completed
+from io import StringIO
 from pathlib import Path
 
-from Bio.PDB.Structure import Structure
+from Bio.PDB.Model import Model
 
-from prodigy_prot.modules.parsers import (get_parser, parse_structure,
-                                          validate_structure)
+from prodigy_prot.modules.parsers import parse_structure
 from prodigy_prot.modules.prodigy import Prodigy
 
 # setup logging
@@ -54,6 +55,14 @@ ap.add_argument(
     action="store_true",
     help="Outputs only the predicted affinity value",
 )
+ap.add_argument(
+    "-np",
+    "--number-of-processors",
+    type=int,
+    action="store",
+    help="Number of processors to use (default: 1)",
+    default=1,
+)
 _co_help = """
 By default, all intermolecular contacts are taken into consideration,
 a molecule being defined as an isolated group of amino acids sharing
@@ -99,28 +108,80 @@ def main():
         log.error(f"Input path {struct_path} is neither a valid file nor a directory")
         sys.exit(1)
 
+    # Collect all tasks
+    tasks = []
     for input_f in input_list:
-        structure, n_chains, n_res = parse_structure(str(input_f))
-
-        if len(input_list) > 1:
-            log.info("#" * 42)
+        models, _, _ = parse_structure(str(input_f))
+        struct_path = Path(input_f)
 
+        for model in models:
+            identifier = f"{struct_path.stem}_model{model.id}"
+            tasks.append((model, identifier, args, struct_path))
+
+    # Execute in parallel
+    total_tasks = len(tasks)
+    if total_tasks == 0:
+        log.error("No valid structures found")
+        sys.exit(1)
+    max_workers = min(args.number_of_processors, total_tasks)
+    log.info(f"[+] Executing {total_tasks} task(s) in total")
+    if max_workers != args.number_of_processors:
+        log.info("[+] Adjusting number of processors based on number of tasks")
         log.info(
-            "[+] Parsed structure file {0} ({1} chains, {2} residues)".format(
-                structure.id, n_chains, n_res
-            )
+            f"[+] Using {max_workers} processor(s) instead of {args.number_of_processors}"
+        )
+
+    # Execute and collect results
+    results = []
+    with ProcessPoolExecutor(max_workers=max_workers) as executor:
+        futures = [executor.submit(process_model, *task) for task in tasks]
+        for future in as_completed(futures):
+            try:
+                result = future.result()
+                results.append(result)
+            except Exception as e:
+                log.error(f"Error processing model: {e}")
+
+    # Sort by identifier, then model.id
+    results.sort(key=lambda x: (x[0], x[1]))
+    # Print all outputs sequentially
+    for identifier, _, output in results:
+        print(output, end="")
+
+
+def process_model(model: Model, identifier: str, args: argparse.Namespace, struct_path):
+    """Process a single model"""
+    # Capture stdout
+    output_buffer = StringIO()
+
+    old_stdout = sys.stdout
+    sys.stdout = output_buffer
+    try:
+        if not args.quiet:
+            print("#" * 42)
+            print(f"[+] Processing structure {identifier}")
+        prodigy = Prodigy(
+            model=model,
+            name=identifier,
+            selection=args.selection,
+            temp=args.temperature,
         )
-        prodigy = Prodigy(structure, args.selection, args.temperature)
         prodigy.predict(
             distance_cutoff=args.distance_cutoff, acc_threshold=args.acc_threshold
         )
         prodigy.print_prediction(quiet=args.quiet)
+    finally:
+        sys.stdout = old_stdout
 
-        if args.contact_list:
-            prodigy.print_contacts(outfile=str(struct_path.with_suffix(".ic")))
+    if args.contact_list:
+        contact_list_f = struct_path.with_suffix(".ic")
+        prodigy.print_contacts(outfile=str(contact_list_f))
+
+    if args.pymol_selection:
+        pymol_script_f = struct_path.with_suffix(".pml")
+        prodigy.print_pymol_script(outfile=str(pymol_script_f))
 
-        if args.pymol_selection:
-            prodigy.print_pymol_script(outfile=str(struct_path.with_suffix(".pml")))
+    return identifier, model.id, output_buffer.getvalue()
 
 
 if __name__ == "__main__":
diff -pruN 2.3.0-1/src/prodigy_prot/modules/freesasa_tools.py 2.4.0-1/src/prodigy_prot/modules/freesasa_tools.py
--- 2.3.0-1/src/prodigy_prot/modules/freesasa_tools.py	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/src/prodigy_prot/modules/freesasa_tools.py	2025-09-02 12:47:29.000000000 +0000
@@ -5,6 +5,7 @@ Functions to execute freesasa and parse
 import os
 
 import freesasa
+from Bio.PDB.Model import Model
 from Bio.PDB.Structure import Structure
 from freesasa import Classifier, calc, structureFromBioPDB
 
@@ -14,7 +15,7 @@ from prodigy_prot.modules.aa_properties
 freesasa.setVerbosity(freesasa.nowarnings)
 
 
-def execute_freesasa_api(structure: Structure) -> tuple[dict, dict]:
+def execute_freesasa_api(model: Model) -> tuple[dict, dict]:
     """
     Calls freesasa using its Python API and returns
     per-residue accessibilities.
@@ -26,9 +27,14 @@ def execute_freesasa_api(structure: Stru
 
     classifier = Classifier(str(NACCESS_CONFIG))
 
+    # NOTE: `structureFromBioPDB` requires a Structure object
+    #  so here build one from a model
+    s = Structure(model.id)
+    s.add(model)
+
     try:
         struct = structureFromBioPDB(
-            structure,
+            s,
             classifier,
         )
         result = calc(struct)
diff -pruN 2.3.0-1/src/prodigy_prot/modules/parsers.py 2.4.0-1/src/prodigy_prot/modules/parsers.py
--- 2.3.0-1/src/prodigy_prot/modules/parsers.py	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/src/prodigy_prot/modules/parsers.py	2025-09-02 12:47:29.000000000 +0000
@@ -4,12 +4,15 @@ Functions to read PDB/mmCIF files
 
 import logging
 import sys
+import typing
 import warnings
 from pathlib import Path
 from typing import Optional, Union
 
+from Bio.PDB.Atom import DisorderedAtom
 from Bio.PDB.Chain import Chain
 from Bio.PDB.MMCIFParser import MMCIFParser
+from Bio.PDB.Model import Model
 from Bio.PDB.PDBExceptions import PDBConstructionWarning
 from Bio.PDB.PDBParser import PDBParser
 from Bio.PDB.Polypeptide import PPBuilder, is_aa
@@ -26,112 +29,110 @@ def get_parser(input_f: Path) -> Union[P
         return PDBParser()
 
 
-def validate_structure(
-    s: Structure, selection: Optional[list[str]] = None, clean: bool = True
-) -> Structure:
-
-    # setup logging
-    logger = logging.getLogger("Prodigy")
+def ignore(r):
+    return r.id[0][0] == "W" or r.id[0][0] == "H"
 
-    # Keep first model only
-    if len(s) > 1:
-        logger.warning(
-            (
-                "[!] Structure contains more than one model."
-                " Only the first one will be kept"
-            )
-        )
-        model_one = s[0].id
-        for m in s.child_list[:]:
-            if m.id != model_one:
-                s.detach_child(m.id)
-
-    # process selected chains
-    chains: list[Chain] = list(s.get_chains())
-    chain_ids = set([c.id for c in chains])
-
-    if selection:
-        sel_chains = []
-        # Match selected chain with structure
-        for sel in selection:
-            for c_str in sel.split(","):
-                sel_chains.append(c_str)
-                if c_str not in chain_ids:
-                    raise ValueError(
-                        f"Selected chain not present in provided structure: {c_str}"
-                    )
 
-        # Remove unselected chains
-        def _ignore_helper(x) -> bool:
-            return x.id not in sel_chains
+def validate_structure(
+    input_strcture_obj: Structure,
+    selection: Optional[list[str]] = None,
+    clean: bool = True,
+) -> list[Model]:
+
+    result: list[Model] = []
+    for model in [m for m in input_strcture_obj.child_list]:
+
+        # process selected chains
+        chains: list[Chain] = list(model.get_chains())
+        chain_ids = set([c.id for c in chains])
+
+        if selection:
+            sel_chains = []
+            # Match selected chain with structure
+            for sel in selection:
+                for c_str in sel.split(","):
+                    sel_chains.append(c_str)
+                    if c_str not in chain_ids:
+                        raise ValueError(
+                            f"Selected chain not present in provided structure: {c_str}"
+                        )
+
+            # Remove unselected chains
+            def _ignore_helper(x) -> bool:
+                return x.id not in sel_chains
+
+            for c in chains:
+                if _ignore_helper(c):
+                    if c.parent is not None:
+                        c.parent.detach_child(c.id)
+
+        # Double occupancy check
+        for atom in list(model.get_atoms()):
+            if atom.is_disordered():
+                atom = typing.cast(DisorderedAtom, atom)
+                residue = atom.parent
+                assert residue is not None
+                sel_at = atom.selected_child
+                assert sel_at is not None
+                sel_at.altloc = " "
+                sel_at.disordered_flag = 0
+                residue.detach_child(atom.id)
+                residue.add(sel_at)
 
+        # Insertion code check
         for c in chains:
-            if _ignore_helper(c):
-                if c.parent is not None:
-                    c.parent.detach_child(c.id)
-
-    # Double occupancy check
-    for atom in list(s.get_atoms()):
-        if atom.is_disordered():
-            residue = atom.parent
-            sel_at = atom.selected_child
-            sel_at.altloc = " "
-            sel_at.disordered_flag = 0
-            residue.detach_child(atom.id)
-            residue.add(sel_at)
-
-    # Insertion code check
-    for c in chains:
-        for residue in c.get_residues():
-            if residue.get_id()[2] != " ":
-                c.detach_child(residue.id)
-
-    if clean:
-        # Remove HETATMs and solvent
-        res_list = list(s.get_residues())
-
-        def _ignore(r):
-            return r.id[0][0] == "W" or r.id[0][0] == "H"
-
-        for res in res_list:
-            if _ignore(res):
-                chain = res.parent
-                chain.detach_child(res.id)
-            elif not is_aa(res, standard=True):
-                raise ValueError(
-                    "Unsupported non-standard amino acid found: {0}".format(res.resname)
-                )
+            for residue in c.get_residues():
+                if residue.get_id()[2] != " ":
+                    c.detach_child(residue.id)
+
+        if clean:
+            # Remove HETATMs and solvent
+            res_list = list(model.get_residues())
+
+            for res in res_list:
+                if ignore(res):
+                    chain = res.parent
+                    assert chain is not None
+                    chain.detach_child(res.id)
+                elif not is_aa(res, standard=True):
+                    raise ValueError(
+                        "Unsupported non-standard amino acid found: {0}".format(
+                            res.resname
+                        )
+                    )
 
-        # Remove Hydrogens
-        atom_list = list(s.get_atoms())
+            # Remove Hydrogens
+            atom_list = list(model.get_atoms())
 
-        def _ignore(x):
-            return x.element == "H"
+            def _ignore(x):
+                return x.element == "H"
 
-        for atom in atom_list:
-            if _ignore(atom):
-                residue = atom.parent
-                residue.detach_child(atom.name)
+            for atom in atom_list:
+                if _ignore(atom):
+                    residue = atom.parent
+                    assert residue is not None
+                    residue.detach_child(atom.name)
+
+        # Detect gaps and compare with no. of chains
+        pep_builder = PPBuilder()
+        peptides = pep_builder.build_peptides(model)
+        n_peptides = len(peptides)
+
+        if n_peptides != len(chain_ids):
+            message = "[!] Structure contains gaps:\n"
+            for i_pp, pp in enumerate(peptides):
+                message += (
+                    "\t{1.parent.id} {1.resname}{1.id[1]} < Fragment {0} > "
+                    "{2.parent.id} {2.resname}{2.id[1]}\n".format(i_pp, pp[0], pp[-1])
+                )
+            log.warning(message)
 
-    # Detect gaps and compare with no. of chains
-    pep_builder = PPBuilder()
-    peptides = pep_builder.build_peptides(s)
-    n_peptides = len(peptides)
-
-    if n_peptides != len(chain_ids):
-        message = "[!] Structure contains gaps:\n"
-        for i_pp, pp in enumerate(peptides):
-            message += (
-                "\t{1.parent.id} {1.resname}{1.id[1]} < Fragment {0} > "
-                "{2.parent.id} {2.resname}{2.id[1]}\n".format(i_pp, pp[0], pp[-1])
-            )
-        logger.warning(message)
-        # raise Exception(message)
+        result.append(model)
 
-    return s
+    return result
 
 
-def parse_structure(path: str) -> tuple[Structure, int, int]:
+def parse_structure(path: str) -> tuple[list[Model], int, int]:
     """Return a validated `Structure`, number of chains and number of residues"""
 
     extension = Path(path).suffix
@@ -154,13 +155,33 @@ def parse_structure(path: str) -> tuple[
 
     assert isinstance(original_structure, Structure)
 
-    structure = validate_structure(original_structure)
+    models: list[Model] = validate_structure(original_structure)
 
     # Get number of chains
-    number_of_chains = len(set([c.id for c in structure.get_chains()]))
+    chain_dict = {}
+    res_dict = {}
+    for model in models:
+        chain_dict.update({c.id: c for c in model.get_chains()})
+        res_dict.update({r.id: r for r in model.get_residues()})
+
+    ## Make sure all models have the same chains
+    # Get chain sets for all models
+    chain_sets = [set(chain.id for chain in model.get_chains()) for model in models]
+
+    # Check if all sets are identical
+    if not all(chain_set == chain_sets[0] for chain_set in chain_sets):
+        raise ValueError(
+            "Not all models have the same chains. Found chain sets: "
+            + ", ".join(str(s) for s in chain_sets)
+        )
+
+    res_sets = [set(res.id for res in model.get_residues()) for model in models]
 
-    # Get number of residues
-    number_of_residues = len(list(structure.get_residues()))
+    if not all(res_set == res_sets[0] for res_set in res_sets):
+        raise ValueError(
+            "Not all models have the same residues. Found residue sets: "
+            + ", ".join(str(s) for s in res_sets)
+        )
 
     # structure, n_chains, n_res = parse_structure(path=str(struct_path))
-    return (structure, number_of_chains, number_of_residues)
+    return (models, len(chain_sets[0]), len(res_sets[0]))
diff -pruN 2.3.0-1/src/prodigy_prot/modules/prodigy.py 2.4.0-1/src/prodigy_prot/modules/prodigy.py
--- 2.3.0-1/src/prodigy_prot/modules/prodigy.py	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/src/prodigy_prot/modules/prodigy.py	2025-09-02 12:47:29.000000000 +0000
@@ -2,6 +2,7 @@ import sys
 from io import TextIOWrapper
 from typing import Optional, TextIO, Union
 
+from Bio.PDB.Model import Model
 from Bio.PDB.NeighborSearch import NeighborSearch
 from Bio.PDB.Structure import Structure
 
@@ -12,12 +13,12 @@ from prodigy_prot.modules.utils import d
 
 
 def calculate_ic(
-    struct: Structure, d_cutoff: float = 5.5, selection: Optional[dict[str, int]] = None
+    model: Model, d_cutoff: float = 5.5, selection: Optional[dict[str, int]] = None
 ) -> list:
     """
     Calculates intermolecular contacts in a parsed struct object.
     """
-    atom_list = list(struct.get_atoms())
+    atom_list = list(model.get_atoms())
     ns = NeighborSearch(atom_list)
     all_list = ns.search_all(radius=d_cutoff, level="R")
 
@@ -102,16 +103,18 @@ class Prodigy:
     # init parameters
     def __init__(
         self,
-        struct_obj: Structure,
+        model: Model,
+        name: str = "",
         selection: Optional[list[str]] = None,
         temp: float = 25.0,
     ):
         self.temp = float(temp)
         if selection is None:
-            self.selection = [chain.id for chain in struct_obj.get_chains()]
+            self.selection = [chain.id for chain in model.get_chains()]
         else:
             self.selection = selection
-        self.structure = struct_obj
+        self.model = model
+        self.name = name
         self.ic_network: list = []
         self.bins: dict[str, float] = {
             "CC": 0.0,
@@ -147,13 +150,13 @@ class Prodigy:
 
         # Contacts
         self.ic_network = calculate_ic(
-            self.structure, d_cutoff=distance_cutoff, selection=selection_dict
+            self.model, d_cutoff=distance_cutoff, selection=selection_dict
         )
 
         self.bins = analyse_contacts(self.ic_network)
 
         # SASA
-        _, cmplx_sasa = execute_freesasa_api(self.structure)
+        _, cmplx_sasa = execute_freesasa_api(self.model)
         self.nis_a, self.nis_c, _ = analyse_nis(cmplx_sasa, acc_threshold=acc_threshold)
 
         # Affinity Calculation
@@ -169,7 +172,7 @@ class Prodigy:
 
     def as_dict(self) -> dict:
         return_dict = {
-            "structure": self.structure.id,
+            "model": self.model.id,
             "selection": self.selection,
             "temp": self.temp,
             "ICs": len(self.ic_network),
@@ -189,7 +192,7 @@ class Prodigy:
             handle = sys.stdout
 
         if quiet:
-            handle.write("{0}\t{1:8.3f}\n".format(self.structure.id, self.ba_val))
+            handle.write("{0}\t{1:8.3f}\n".format(self.name, self.ba_val))
         else:
             handle.write(
                 "[+] No. of intermolecular contacts: {0}\n".format(len(self.ic_network))
diff -pruN 2.3.0-1/tests/test_parsers.py 2.4.0-1/tests/test_parsers.py
--- 2.3.0-1/tests/test_parsers.py	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/tests/test_parsers.py	2025-09-02 12:47:29.000000000 +0000
@@ -39,27 +39,28 @@ def test_validate_structure_pdb(input_st
     assert isinstance(structure, Structure)
 
     result = validate_structure(structure)
-    assert result == structure
+    assert result == structure.child_list
 
 
-def test_validate_stucture_cif(input_structure_cif):
+def test_validate_structure_cif(input_structure_cif):
 
     parser = MMCIFParser()
     structure = parser.get_structure("test_structure", input_structure_cif)
     assert isinstance(structure, Structure)
 
     result = validate_structure(structure)
-    assert result == structure
+    assert result == structure.child_list
 
 
 def test_parse_structure_pdb(input_structure_pdb):
 
     parser = PDBParser()
     structure = parser.get_structure(input_structure_pdb.stem, input_structure_pdb)
+    assert isinstance(structure, Structure)
 
     result, num_chains, num_res = parse_structure(input_structure_pdb)
 
-    assert result == structure
+    assert result == structure.child_list
     assert num_chains == 2
     assert num_res == 116
 
@@ -68,9 +69,10 @@ def test_parse_structure_cif(input_struc
 
     parser = MMCIFParser()
     structure = parser.get_structure(input_structure_cif.stem, input_structure_cif)
+    assert isinstance(structure, Structure)
 
     result, num_chains, num_res = parse_structure(input_structure_cif)
 
-    assert result == structure
+    assert result == structure.child_list
     assert num_chains == 2
     assert num_res == 116
diff -pruN 2.3.0-1/tests/test_prodigy.py 2.4.0-1/tests/test_prodigy.py
--- 2.3.0-1/tests/test_prodigy.py	2025-04-15 13:42:12.000000000 +0000
+++ 2.4.0-1/tests/test_prodigy.py	2025-09-02 12:47:29.000000000 +0000
@@ -6,6 +6,7 @@ from os.path import basename, splitext
 from pathlib import Path
 
 import pytest
+from Bio.PDB.Model import Model
 from Bio.PDB.PDBParser import PDBParser
 from Bio.PDB.Residue import Residue
 from Bio.PDB.Structure import Structure
@@ -22,10 +23,12 @@ from . import TEST_DATA
 
 
 @pytest.fixture
-def input_pdb_structure():
+def input_model():
     input_f = Path(TEST_DATA, "2oob.pdb")
     parser = PDBParser()
-    return parser.get_structure(input_f.stem, input_f)
+    structure = parser.get_structure(input_f.stem, input_f)
+    assert isinstance(structure, Structure)
+    return structure.child_list[0]
 
 
 @pytest.fixture
@@ -39,13 +42,13 @@ def expected_dataset_json():
 
 
 @pytest.fixture
-def prodigy_class(input_pdb_structure):
-    yield Prodigy(struct_obj=input_pdb_structure)
+def prodigy_class(input_model):
+    yield Prodigy(input_model)
 
 
-def test_calculate_ic(input_pdb_structure):
+def test_calculate_ic(input_model):
 
-    result = calculate_ic(struct=input_pdb_structure, d_cutoff=5.5)
+    result = calculate_ic(model=input_model, d_cutoff=5.5)
 
     assert len(result) == 78
 
@@ -55,11 +58,9 @@ def test_calculate_ic(input_pdb_structur
     assert first_hit[1].get_resname() == "LYS"
 
 
-def test_calculate_ic_with_selection(input_pdb_structure):
+def test_calculate_ic_with_selection(input_model):
 
-    result = calculate_ic(
-        struct=input_pdb_structure, d_cutoff=5.5, selection={"A": 0, "B": 1}
-    )
+    result = calculate_ic(model=input_model, d_cutoff=5.5, selection={"A": 0, "B": 1})
 
     assert len(result) == 78
 
@@ -69,10 +70,10 @@ def test_calculate_ic_with_selection(inp
     assert first_hit[1].get_resname() == "LYS"
 
 
-def test_analyse_contacts(input_pdb_structure):
+def test_analyse_contacts(input_model):
 
-    res_a = input_pdb_structure[0]["A"][(" ", 931, " ")]
-    res_b = input_pdb_structure[0]["B"][(" ", 6, " ")]
+    res_a = input_model["A"][(" ", 931, " ")]
+    res_b = input_model["B"][(" ", 6, " ")]
     contact = (res_a, res_b)
 
     test_input = [contact]
@@ -143,10 +144,10 @@ def test_prodigy_print_prediction_quiet(
     Path(outfile.name).unlink()
 
 
-def test_prodigy_print_contacts(input_pdb_structure, prodigy_class):
+def test_prodigy_print_contacts(input_model, prodigy_class):
 
-    res_a = input_pdb_structure[0]["A"][(" ", 931, " ")]
-    res_b = input_pdb_structure[0]["B"][(" ", 6, " ")]
+    res_a = input_model["A"][(" ", 931, " ")]
+    res_b = input_model["B"][(" ", 6, " ")]
     prodigy_class.ic_network = [(res_a, res_b)]
 
     outfile = tempfile.NamedTemporaryFile(delete=False)
@@ -158,9 +159,9 @@ def test_prodigy_print_contacts(input_pd
     Path(outfile.name).unlink()
 
 
-def test_print_pymol_script(input_pdb_structure, prodigy_class):
-    res_a = input_pdb_structure[0]["A"][(" ", 931, " ")]
-    res_b = input_pdb_structure[0]["B"][(" ", 6, " ")]
+def test_print_pymol_script(input_model, prodigy_class):
+    res_a = input_model["A"][(" ", 931, " ")]
+    res_b = input_model["B"][(" ", 6, " ")]
     prodigy_class.ic_network = [(res_a, res_b)]
 
     outfile = tempfile.NamedTemporaryFile(delete=False)
@@ -205,26 +206,31 @@ def test_dataset_prediction(compressed_d
         parsed_structure = parser.get_structure(s_name, handle)
         assert isinstance(parsed_structure, Structure)
 
-        s = validate_structure(parsed_structure, selection=["A", "B"])
+        models = validate_structure(parsed_structure, selection=["A", "B"])
 
         # Test for structure object
-        assert isinstance(s, Structure)
+        # Check if it's a list and all elements are Model objects
+        assert isinstance(models, list) and all(
+            isinstance(item, Model) for item in models
+        )
+        # assert isinstance(s, list[Model])
 
         #  run prediction and retrieve result dict
-        prod = Prodigy(s, selection=["A", "B"])
-        prod.predict()
-        results = prod.as_dict()
-
-        # check for equality of prdicted interface residues
-        for k in keys_equal:
-            observed_value = results[k]
-            expected_value = expected_data[s_name][k]
-            assert observed_value == pytest.approx(expected_value)
-
-        # check that NIS and binding afinity values are within 2% of
-        #  expected values and add diffs for summary
-        for k in diffs.keys():
-            delta = abs(results[k] / expected_data[s_name][k] - 1)
-            # assume a difference of less then 2%
-            assert delta == pytest.approx(0, abs=0.02)
-            diffs[k].append(delta)
+        for m in models:
+            prod = Prodigy(m, selection=["A", "B"])
+            prod.predict()
+            results = prod.as_dict()
+
+            # check for equality of prdicted interface residues
+            for k in keys_equal:
+                observed_value = results[k]
+                expected_value = expected_data[s_name][k]
+                assert observed_value == pytest.approx(expected_value)
+
+            # check that NIS and binding afinity values are within 2% of
+            #  expected values and add diffs for summary
+            for k in diffs.keys():
+                delta = abs(results[k] / expected_data[s_name][k] - 1)
+                # assume a difference of less then 2%
+                assert delta == pytest.approx(0, abs=0.02)
+                diffs[k].append(delta)
