Skip to content

Commit fef38a0

Browse files
Yoshanuikabundipre-commit-ci[bot]lilyminiumj-wags
authored
Improvements to record downloading and docstrings (#352)
* Improvements to record downloading and docstrings * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply corrections from code review. Co-authored-by: Lily Wang <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove unused import * restore support for single drivers outside iterable * update releasehistory --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Lily Wang <[email protected]> Co-authored-by: Jeff Wagner <[email protected]>
1 parent 98a56e0 commit fef38a0

File tree

2 files changed

+105
-22
lines changed

2 files changed

+105
-22
lines changed

docs/releasehistory.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ Releases are given with dates in DD-MM-YYYY format.
1111

1212
<!--## Version / Date DD-MM-YYYY -->
1313

14+
## 0.57.0 / 10-02-2025
15+
16+
### API extensions
17+
* [PR #352:] Add `include` argument to `to_records()` to enable users to select which fields to download (and hint to user that not all fields are downloaded by default!)
18+
19+
### Documentation updates
20+
* [PR #352:] Revise docstrings for to_records() to better reflect their purpose
21+
* [PR #352:] Add a note to OptimizationResultCollection.to_records() docstring to explain that the user may want to call .to_basic_result_collection() first
22+
* [PR #352:] Revise docstring of to_basic_result_collection() with more details
23+
1424
## 0.56.0 / 05-19-2025
1525

1626
### Bugfixes

openff/qcsubmit/results/results.py

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,17 @@ def _validate_record_types(
192192
)
193193

194194
@abc.abstractmethod
195-
def to_records(self) -> List[Tuple[BaseRecord, Molecule]]:
196-
"""Returns the native QCPortal record objects for each of the records referenced
197-
in this collection along with a corresponding OpenFF molecule object.
195+
def to_records(self, include: Iterable[str]) -> List[Tuple[BaseRecord, Molecule]]:
196+
"""Download all records referenced in this collection from QCFractal.
197+
198+
Returns the native QCPortal record objects for each of the records
199+
referenced in this collection along with a corresponding OpenFF Molecule
200+
object.
201+
202+
Parameters
203+
==========
204+
include
205+
The fields to download when the record is collected.
198206
"""
199207
raise NotImplementedError()
200208

@@ -388,22 +396,36 @@ def from_server(
388396
spec_name,
389397
)
390398

391-
def to_records(self) -> List[Tuple[SinglepointRecord, Molecule]]:
392-
"""Returns the native QCPortal record objects for each of the records referenced
393-
in this collection along with a corresponding OpenFF molecule object.
399+
def to_records(
400+
self, include: Iterable[str] = ("molecule",)
401+
) -> List[Tuple[SinglepointRecord, Molecule]]:
402+
"""Download all records referenced in this collection from QCFractal.
403+
404+
Returns the native QCPortal record objects for each of the records
405+
referenced in this collection along with a corresponding OpenFF Molecule
406+
object.
394407
395408
Each molecule will contain the conformer referenced by the record.
409+
410+
Parameters
411+
==========
412+
include
413+
The fields to download when the record is collected. The
414+
``"molecule"`` field is always downloaded.
396415
"""
397416
from openff.qcsubmit.utils.utils import _default_portal_client
398417

399418
records_and_molecules = []
400419

420+
if "molecule" not in include:
421+
include = ("molecule", *include)
422+
401423
for client_address, records in self.entries.items():
402424
client = _default_portal_client(client_address)
403425

404426
# TODO - batching/chunking (maybe in portal?)
405427
for record in records:
406-
rec = client.get_singlepoints(record.record_id, include=["molecule"])
428+
rec = client.get_singlepoints(record.record_id, include=include)
407429

408430
# OpenFF molecule
409431
try:
@@ -540,25 +562,45 @@ def from_server(
540562
spec_name,
541563
)
542564

543-
def to_records(self) -> List[Tuple[OptimizationRecord, Molecule]]:
544-
"""Returns the native QCPortal record objects for each of the records referenced
545-
in this collection along with a corresponding OpenFF molecule object.
565+
def to_records(
566+
self,
567+
include: Iterable[str] = ("initial_molecule", "final_molecule"),
568+
) -> List[Tuple[OptimizationRecord, Molecule]]:
569+
"""Download all records referenced in this collection from QCFractal.
570+
571+
Returns the native QCPortal record objects for each of the records
572+
referenced in this collection along with a corresponding OpenFF Molecule
573+
object.
546574
547575
Each molecule will contain the minimum energy conformer referenced by the
548576
record.
577+
578+
Parameters
579+
==========
580+
include
581+
The fields to download when the record is collected. The
582+
``"final_molecule"`` field is always downloaded.
583+
584+
Notes
585+
=====
586+
By default, this function does not download ``"trajectory"`` field,
587+
and so the resulting records do not include any gradients or forces. To
588+
download a complete record of the minimum energy conformer's calculation,
589+
including forces, see :py:meth:`to_basic_result_collection`.
549590
"""
550591
from openff.qcsubmit.utils.utils import _default_portal_client
551592

552593
records_and_molecules = []
553594

595+
if "final_molecule" not in include:
596+
include = ("final_molecule", *include)
597+
554598
for client_address, results in self.entries.items():
555599
client = _default_portal_client(client_address)
556600

557601
rec_ids = [result.record_id for result in results]
558602
# Do one big request to save time
559-
opt_records = client.get_optimizations(
560-
rec_ids, include=["initial_molecule", "final_molecule"]
561-
)
603+
opt_records = client.get_optimizations(rec_ids, include=include)
562604
# Sort out which records from the request line up with which results
563605
opt_rec_id_to_result = dict()
564606
for result in results:
@@ -593,18 +635,34 @@ def to_records(self) -> List[Tuple[OptimizationRecord, Molecule]]:
593635

594636
return records_and_molecules
595637

596-
def to_basic_result_collection(self, driver) -> BasicResultCollection:
597-
"""Returns a basic results collection which references results records which
638+
def to_basic_result_collection(
639+
self,
640+
driver: SinglepointDriver | Iterable[SinglepointDriver] | None = None,
641+
) -> BasicResultCollection:
642+
"""
643+
Get a collection of the single point results from the end of each optimization.
644+
645+
Returns a basic results collection which references results records which
598646
were created from the *final* structure of one of the optimizations in this
599647
collection, and used the same program, method, and basis as the parent
600648
optimization record.
601649
602-
Returns:
603-
The results collection referencing records created from the final optimized
604-
structures referenced by this collection.
650+
Parameters
651+
==========
652+
driver
653+
Return only those records whose driver is in this list. If omitted
654+
or ``None``, include all drivers.
655+
656+
Returns
657+
=======
658+
The results collection referencing records created from the final
659+
optimized structures referenced by this collection.
605660
"""
606661
from openff.qcsubmit.utils.utils import _default_portal_client
607662

663+
# If driver is None, set it to all drivers
664+
driver = tuple(SinglepointDriver) if driver is None else driver
665+
608666
records_and_molecules = self.to_records()
609667

610668
result_records = defaultdict(list)
@@ -812,25 +870,40 @@ def from_server(
812870
spec_name,
813871
)
814872

815-
def to_records(self) -> List[Tuple[TorsiondriveRecord, Molecule]]:
816-
"""Returns the native QCPortal record objects for each of the records referenced
817-
in this collection along with a corresponding OpenFF molecule object.
873+
def to_records(
874+
self,
875+
include: Iterable[str] = ("minimum_optimizations",),
876+
) -> List[Tuple[TorsiondriveRecord, Molecule]]:
877+
"""Download all records referenced in this collection from QCFractal.
878+
879+
Returns the native QCPortal record objects for each of the records
880+
referenced in this collection along with a corresponding OpenFF Molecule
881+
object.
818882
819883
Each molecule will contain the minimum energy conformer referenced by the
820884
record.
885+
886+
Parameters
887+
==========
888+
include
889+
The fields to download when the record is collected. The
890+
``"minimum_optimizations"`` field is always downloaded.
821891
"""
822892
from openff.qcsubmit.utils.utils import _default_portal_client
823893

824894
records_and_molecules = []
825895

896+
if "minimum_optimizations" not in include:
897+
include = ("minimum_optimizations", *include)
898+
826899
for client_address, records in self.entries.items():
827900
client = _default_portal_client(client_address)
828901

829902
# retrieve all torsiondrives at once, including their
830903
# minimum_optimizations
831904
record_ids = [r.record_id for r in records]
832905
torsion_drive_records = client.get_torsiondrives(
833-
record_ids, include=["minimum_optimizations"]
906+
record_ids, include=include
834907
)
835908
for record, rec in zip(records, torsion_drive_records):
836909
# OpenFF molecule

0 commit comments

Comments
 (0)