@@ -86,6 +86,15 @@ class ExternalLookupItem {
8686 * Get the data
8787 */
8888 Image<T> get_data () const {
89+ if (generator_ != boost::python::object ()) {
90+ auto generated = generator_ ();
91+ // Only replace data if we got "None" from this generator
92+ if (generated != boost::python::object ()) {
93+ data_ = boost::python::extract<Image<T>>(generated)();
94+ }
95+ // Discard the generator, no matter what
96+ generator_ = boost::python::object ();
97+ }
8998 return data_;
9099 }
91100
@@ -97,9 +106,18 @@ class ExternalLookupItem {
97106 data_ = data;
98107 }
99108
109+ // / Set a generator, to only load the external item data on first use
110+ // /
111+ // / This is a Python Callable[[], Image<T>] function. The function will
112+ // / be discarded after first use.
113+ void set_data_generator (boost::python::object generator) {
114+ generator_ = generator;
115+ }
116+
100117protected:
101118 std::string filename_;
102- Image<T> data_;
119+ mutable Image<T> data_;
120+ mutable boost::python::object generator_;
103121};
104122
105123/* *
@@ -171,12 +189,22 @@ class ImageSetData {
171189 ImageSetData (boost::python::object reader, masker_ptr masker)
172190 : reader_(reader),
173191 masker_ (masker),
192+ masker_obj_(),
174193 beams_(boost::python::len(reader)),
175194 detectors_(boost::python::len(reader)),
176195 goniometers_(boost::python::len(reader)),
177196 scans_(boost::python::len(reader)),
178197 reject_(boost::python::len(reader)) {}
179198
199+ ImageSetData (boost::python::object reader, boost::python::object masker)
200+ : reader_(reader),
201+ masker_(),
202+ masker_obj_(masker),
203+ beams_(boost::python::len(reader)),
204+ detectors_(boost::python::len(reader)),
205+ goniometers_(boost::python::len(reader)),
206+ scans_(boost::python::len(reader)),
207+ reject_(boost::python::len(reader)) {}
180208 /* *
181209 * @returns The reader object
182210 */
@@ -188,14 +216,19 @@ class ImageSetData {
188216 * @returns The masker object
189217 */
190218 masker_ptr masker () {
219+ if (masker_ == nullptr && masker_obj_ != boost::python::object ()) {
220+ masker_ = boost::python::extract<ImageSetData::masker_ptr>(masker_obj_ ())();
221+ masker_obj_ = boost::python::object ();
222+ }
223+
191224 return masker_;
192225 }
193226
194227 /* *
195228 * @returns Does the imageset have a dynamic mask.
196229 */
197230 bool has_dynamic_mask () const {
198- return masker_ != NULL ;
231+ return masker_ != nullptr || masker_obj_ != boost::python::object () ;
199232 }
200233
201234 /* *
@@ -440,7 +473,12 @@ class ImageSetData {
440473 std::size_t first,
441474 std::size_t last) const {
442475 DXTBX_ASSERT (last > first);
443- ImageSetData partial = ImageSetData (reader, masker_);
476+ ImageSetData partial;
477+ if (masker_ == nullptr && masker_obj_ != boost::python::object ()) {
478+ partial = ImageSetData (reader, masker_obj_);
479+ } else {
480+ partial = ImageSetData (reader, masker_);
481+ }
444482 for (size_t i = 0 ; i < last - first; i++) {
445483 partial.beams_ [i] = beams_[i + first];
446484 partial.detectors_ [i] = detectors_[i + first];
@@ -513,11 +551,18 @@ class ImageSetData {
513551 flex_type a = boost::python::extract<flex_type>(obj)();
514552
515553 // Return the image tile
516- return ImageTile<T>(scitbx::af::versa<T, scitbx::af::c_grid<2 > >(
554+ return ImageTile<T>(scitbx::af::versa<T, scitbx::af::c_grid<2 >>(
517555 a.handle (), scitbx::af::c_grid<2 >(a.accessor ())));
518556 }
519557
520558 boost::python::object reader_;
559+ // / Hold an object that can be called to get the masker.
560+ // /
561+ // / This won't be called until the masker is actually required, under
562+ // / the assumption that accessing the masker requires accessing the raw
563+ // / data file.
564+ boost::python::object masker_obj_;
565+ // / The Goniometer Masker object, if loaded (or present)
521566 std::shared_ptr<GoniometerShadowMasker> masker_;
522567 scitbx::af::shared<beam_ptr> beams_;
523568 scitbx::af::shared<detector_ptr> detectors_;
@@ -660,8 +705,8 @@ class ImageSet {
660705 * @returns The corrected data array
661706 */
662707 Image<double > get_corrected_data (std::size_t index) {
663- typedef scitbx::af::versa<double , scitbx::af::c_grid<2 > > array_type;
664- typedef scitbx::af::const_ref<double , scitbx::af::c_grid<2 > > const_ref_type;
708+ typedef scitbx::af::versa<double , scitbx::af::c_grid<2 >> array_type;
709+ typedef scitbx::af::const_ref<double , scitbx::af::c_grid<2 >> const_ref_type;
665710
666711 // Get the multi-tile data, gain and pedestal
667712 DXTBX_ASSERT (index < indices_.size ());
@@ -758,7 +803,7 @@ class ImageSet {
758803 std::size_t xsize = detector[i].get_image_size ()[0 ];
759804 std::size_t ysize = detector[i].get_image_size ()[1 ];
760805 scitbx::af::c_grid<2 > grid (ysize, xsize);
761- scitbx::af::versa<double , scitbx::af::c_grid<2 > > data (grid, gain[i]);
806+ scitbx::af::versa<double , scitbx::af::c_grid<2 >> data (grid, gain[i]);
762807 result.push_back (ImageTile<double >(data));
763808 }
764809 return result;
@@ -797,7 +842,7 @@ class ImageSet {
797842 std::size_t xsize = detector[i].get_image_size ()[0 ];
798843 std::size_t ysize = detector[i].get_image_size ()[1 ];
799844 scitbx::af::c_grid<2 > grid (ysize, xsize);
800- scitbx::af::versa<double , scitbx::af::c_grid<2 > > data (grid, pedestal[i]);
845+ scitbx::af::versa<double , scitbx::af::c_grid<2 >> data (grid, pedestal[i]);
801846 result.push_back (ImageTile<double >(data));
802847 }
803848 return result;
@@ -824,7 +869,7 @@ class ImageSet {
824869 for (std::size_t i = 0 ; i < detector.size (); ++i) {
825870 std::size_t xsize = detector[i].get_image_size ()[0 ];
826871 std::size_t ysize = detector[i].get_image_size ()[1 ];
827- mask.push_back (ImageTile<bool >(scitbx::af::versa<bool , scitbx::af::c_grid<2 > >(
872+ mask.push_back (ImageTile<bool >(scitbx::af::versa<bool , scitbx::af::c_grid<2 >>(
828873 scitbx::af::c_grid<2 >(ysize, xsize), true )));
829874 }
830875 return mask;
@@ -854,8 +899,8 @@ class ImageSet {
854899 if (!external_mask.empty ()) {
855900 DXTBX_ASSERT (external_mask.n_tiles () == mask.n_tiles ());
856901 for (std::size_t i = 0 ; i < mask.n_tiles (); ++i) {
857- scitbx::af::ref<bool , scitbx::af::c_grid<2 > > m1 = mask.tile (i).data ().ref ();
858- scitbx::af::const_ref<bool , scitbx::af::c_grid<2 > > m2 =
902+ scitbx::af::ref<bool , scitbx::af::c_grid<2 >> m1 = mask.tile (i).data ().ref ();
903+ scitbx::af::const_ref<bool , scitbx::af::c_grid<2 >> m2 =
859904 external_mask.tile (i).data ().const_ref ();
860905 DXTBX_ASSERT (m1.accessor ().all_eq (m2.accessor ()));
861906 for (std::size_t j = 0 ; j < m1.size (); ++j) {
@@ -1102,14 +1147,14 @@ class ImageSet {
11021147 */
11031148 void clear_cache () {
11041149 data_cache_ = DataCache<ImageBuffer>();
1105- double_raw_data_cache_ = DataCache<Image<double > >();
1150+ double_raw_data_cache_ = DataCache<Image<double >>();
11061151 }
11071152
11081153protected:
11091154 ImageSetData data_;
11101155 scitbx::af::shared<std::size_t > indices_;
11111156 DataCache<ImageBuffer> data_cache_;
1112- DataCache<Image<double > > double_raw_data_cache_;
1157+ DataCache<Image<double >> double_raw_data_cache_;
11131158
11141159 Image<double > get_raw_data_as_double (std::size_t index) {
11151160 DXTBX_ASSERT (index < indices_.size ());
0 commit comments