1 line
114 KiB
HTML
1 line
114 KiB
HTML
<!DOCTYPE html> <html lang=en data-content_root="./"> <meta charset=utf-8 /> <meta name=viewport content="width=device-width, initial-scale=1.0" /><meta name=viewport content="width=device-width, initial-scale=1" /> <meta name=viewport content="width=device-width,initial-scale=1"> <meta http-equiv=x-ua-compatible content="ie=edge"> <meta name="lang:clipboard.copy" content="Copy to clipboard"> <meta name="lang:clipboard.copied" content="Copied to clipboard"> <meta name="lang:search.language" content=en > <meta name="lang:search.pipeline.stopwords" content=True > <meta name="lang:search.pipeline.trimmer" content=True > <meta name="lang:search.result.none" content="No matching documents"> <meta name="lang:search.result.one" content="1 matching document"> <meta name="lang:search.result.other" content="# matching documents"> <meta name="lang:search.tokenizer" content="[\s\-]+"> <link href="https://fonts.gstatic.com/" rel=preconnect crossorigin> <link href="https://fonts.googleapis.com/css?family=Roboto+Mono:400,500,700|Roboto:300,400,400i,700&display=fallback" rel=stylesheet > <style> body, input { font-family: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif } code, kbd, pre { font-family: "Roboto Mono", "Courier New", Courier, monospace } </style> <link rel=stylesheet href="_static/stylesheets/application.css"/> <link rel=stylesheet href="_static/stylesheets/application-palette.css"/> <link rel=stylesheet href="_static/stylesheets/application-fixes.css"/> <link rel=stylesheet href="_static/fonts/material-icons.css"/> <meta name=theme-color content="#3f51b5"> <script src="_static/javascripts/modernizr.js"></script> <title>CPU-side crystallographic data analysis (Jungfraujoch) — Jungfraujoch 1.0.0-rc.158 documentation</title> <link rel=stylesheet type="text/css" href="_static/pygments.css?v=83e35b93" /> <link rel=stylesheet type="text/css" href="_static/material.css?v=79c92029" /> <script src="_static/documentation_options.js?v=2bb17200"></script> <script src="_static/doctools.js?v=9bcbadda"></script> <script src="_static/sphinx_highlight.js?v=dc90522c"></script> <script>window.MathJax = {"tex": {"tags": "ams", "inlineMath": [["\\(", "\\)"], ["$", "$"]], "displayMath": [["\\[", "\\]"], ["$$", "$$"]], "processEscapes": true}, "options": {"processHtmlClass": "tex2jax_process|mathjax_process|math|output_area"}}</script> <script defer=defer src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> <link rel=icon href="_static/jfjoch.png"/> <link rel=index title=Index href=genindex.html /> <link rel=search title=Search href=search.html /> <link rel=next title=OpenAPI href=OPENAPI.html /> <link rel=prev title="Detector geometry" href=DETECTOR_GEOMETRY.html /> <body dir=ltr data-md-color-primary=indigo data-md-color-accent=lime> <svg class=md-svg > <defs data-children-count=0 > <svg xmlns="http://www.w3.org/2000/svg" width=500 height=500 viewBox="0 0 500 500" id=__gitlab ><path fill=currentColor d="M93.667 473.347l90.684-279.097H2.983l90.684 279.097z" transform="translate(156.198 1.16)"/><path fill=currentColor d="M221.333 473.345L130.649 194.25H3.557l217.776 279.095z" transform="translate(28.531 1.16)" opacity=.7 /><path fill=currentColor d="M32 195.155L4.441 279.97a18.773 18.773 0 0 0 6.821 20.99l238.514 173.29L32 195.155z" transform="translate(.089 .256)" opacity=.5 /><path fill=currentColor d="M2.667-84.844h127.092L75.14-252.942c-2.811-8.649-15.047-8.649-17.856 0L2.667-84.844z" transform="translate(29.422 280.256)"/><path fill=currentColor d="M2.667 473.345L93.351 194.25h127.092L2.667 473.345z" transform="translate(247.198 1.16)" opacity=.7 /><path fill=currentColor d="M221.334 195.155l27.559 84.815a18.772 18.772 0 0 1-6.821 20.99L3.557 474.25l217.777-279.095z" transform="translate(246.307 .256)" opacity=.5 /><path fill=currentColor d="M130.667-84.844H3.575l54.618-168.098c2.811-8.649 15.047-8.649 17.856 0l54.618 168.098z" transform="translate(336.974 280.256)"/></svg> </defs> </svg> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer > <input class=md-toggle data-md-toggle=search type=checkbox id=__search > <label class=md-overlay data-md-component=overlay for=__drawer ></label> <a href="#CPU_DATA_ANALYSIS" tabindex=1 class=md-skip > Skip to content </a> <header class=md-header data-md-component=header > <nav class="md-header-nav md-grid"> <div class="md-flex navheader"> <div class="md-flex__cell md-flex__cell--shrink"> <a href=index.html title="Jungfraujoch 1.0.0-rc.158 documentation" class="md-header-nav__button md-logo"> <i class=md-icon ></i> </a> </div> <div class="md-flex__cell md-flex__cell--shrink"> <label class="md-icon md-icon--menu md-header-nav__button" for=__drawer ></label> </div> <div class="md-flex__cell md-flex__cell--stretch"> <div class="md-flex__ellipsis md-header-nav__title" data-md-component=title > <span class=md-header-nav__topic >PSI Jungfraujoch</span> <span class=md-header-nav__topic > CPU-side crystallographic data analysis (Jungfraujoch) </span> </div> </div> <div class="md-flex__cell md-flex__cell--shrink"> <label class="md-icon md-icon--search md-header-nav__button" for=__search ></label> <div class=md-search data-md-component=search role=dialog > <label class=md-search__overlay for=__search ></label> <div class=md-search__inner role=search > <form class=md-search__form action=search.html method=get name=search > <input type=text class=md-search__input name=q placeholder=""Search"" autocapitalize=off autocomplete=off spellcheck=false data-md-component=query data-md-state=active > <label class="md-icon md-search__icon" for=__search ></label> <button type=reset class="md-icon md-search__icon" data-md-component=reset tabindex=-1 >  </button> </form> <div class=md-search__output > <div class=md-search__scrollwrap data-md-scrollfix> <div class=md-search-result data-md-component=result > <div class=md-search-result__meta > Type to start searching </div> <ol class=md-search-result__list ></ol> </div> </div> </div> </div> </div> </div> <div class="md-flex__cell md-flex__cell--shrink"> <div class=md-header-nav__source > <a href="https://gitea.psi.ch/mx/jungfraujoch" title="Go to repository" class=md-source data-md-source=github > <div class=md-source__icon > <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width=28 height=28 > <use xlink:href="#__gitlab" width=24 height=24 ></use> </svg> </div> <div class=md-source__repository > Jungfraujoch </div> </a> </div> </div> <script src="_static/javascripts/version_dropdown.js"></script> <script> var json_loc = ""versions.json"", target_loc = "../", text = "Versions"; $( document ).ready( add_version_dropdown(json_loc, target_loc, text)); </script> </div> </nav> </header> <div class=md-container > <nav class=md-tabs data-md-component=tabs > <div class="md-tabs__inner md-grid"> <ul class=md-tabs__list > <li class=md-tabs__item ><a href=index.html class=md-tabs__link >Jungfraujoch 1.0.0-rc.158 documentation</a> </ul> </div> </nav> <main class=md-main > <div class="md-main__inner md-grid" data-md-component=container > <div class="md-sidebar md-sidebar--primary" data-md-component=navigation > <div class=md-sidebar__scrollwrap > <div class=md-sidebar__inner > <nav class="md-nav md-nav--primary" data-md-level=0 > <label class="md-nav__title md-nav__title--site" for=__drawer > <a href=index.html title="Jungfraujoch 1.0.0-rc.158 documentation" class="md-nav__button md-logo"> <i class=md-icon ></i> </a> <a href=index.html title="Jungfraujoch 1.0.0-rc.158 documentation">PSI Jungfraujoch</a> </label> <div class=md-nav__source > <a href="https://gitea.psi.ch/mx/jungfraujoch" title="Go to repository" class=md-source data-md-source=github > <div class=md-source__icon > <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width=28 height=28 > <use xlink:href="#__gitlab" width=24 height=24 ></use> </svg> </div> <div class=md-source__repository > Jungfraujoch </div> </a> </div> <ul class=md-nav__list > <li class=md-nav__item > <span class="md-nav__link caption"><span class=caption-text >General</span></span> <li class=md-nav__item > <a href=ACKNOWLEDGEMENT.html class=md-nav__link >Acknowledgements</a> <li class=md-nav__item > <a href=LICENSE.html class=md-nav__link >License</a> <li class=md-nav__item > <a href=THIRD_PARTY_NOTICES.html class=md-nav__link >Third-party software notices</a> <li class=md-nav__item > <a href=DETECTORS.html class=md-nav__link >Supported detectors</a> <li class=md-nav__item > <a href="DETECTORS.html#dectris-detectors" class=md-nav__link >DECTRIS detectors</a> <li class=md-nav__item > <a href=HARDWARE.html class=md-nav__link >Hardware requirements</a> <li class=md-nav__item > <a href=SOFTWARE.html class=md-nav__link >Software requirements</a> <li class=md-nav__item > <a href=VERSIONING.html class=md-nav__link >Semantic versioning</a> <li class=md-nav__item > <a href=DEPLOYMENT.html class=md-nav__link >Deployment</a> <li class=md-nav__item > <a href=REPOSITORIES.html class=md-nav__link >Linux package repositories</a> <li class=md-nav__item > <a href=NAMING.html class=md-nav__link >Naming</a> <li class=md-nav__item > <a href=CHANGELOG.html class=md-nav__link >Changelog</a> <li class=md-nav__item > <span class="md-nav__link caption"><span class=caption-text >Software</span></span> <li class=md-nav__item > <a href=JFJOCH_BROKER.html class=md-nav__link >jfjoch_broker</a> <li class=md-nav__item > <a href=JFJOCH_WRITER.html class=md-nav__link >jfjoch_writer</a> <li class=md-nav__item > <a href=RUGNUX.html class=md-nav__link >rugnux</a> <li class=md-nav__item > <a href=JFJOCH_VIEWER.html class=md-nav__link >jfjoch_viewer</a> <li class=md-nav__item > <a href=SOFTWARE_INTEGRATION.html class=md-nav__link >Integration with MX data processing software</a> <li class=md-nav__item > <a href=TOOLS.html class=md-nav__link >Tools</a> <li class=md-nav__item > <span class="md-nav__link caption"><span class=caption-text >FPGA</span></span> <li class=md-nav__item > <a href=FPGA.html class=md-nav__link >FPGA smartNIC</a> <li class=md-nav__item > <a href=FPGA_LICENSE.html class=md-nav__link >FPGA license</a> <li class=md-nav__item > <a href=FPGA_DESIGN.html class=md-nav__link >FPGA data flow</a> <li class=md-nav__item > <a href=FPGA_NETWORK.html class=md-nav__link >FPGA network</a> <li class=md-nav__item > <a href=FPGA_PCIE_DRIVER.html class=md-nav__link >FPGA PCIe driver</a> <li class=md-nav__item > <a href=FPGA_SETTINGS.html class=md-nav__link >FPGA advanced reference</a> <li class=md-nav__item > <a href=FPGA_DATA_ANALYSIS.html class=md-nav__link >FPGA data analysis</a> <li class=md-nav__item > <span class="md-nav__link caption"><span class=caption-text >Reference</span></span> <li class=md-nav__item > <a href=DETECTOR_GEOMETRY.html class=md-nav__link >Detector geometry</a> <li class=md-nav__item > <input class="md-toggle md-nav__toggle" data-md-toggle=toc type=checkbox id=__toc > <label class="md-nav__link md-nav__link--active" for=__toc > CPU-side crystallographic data analysis (Jungfraujoch) </label> <a href="#" class="md-nav__link md-nav__link--active">CPU-side crystallographic data analysis (Jungfraujoch)</a> <nav class="md-nav md-nav--secondary"> <ul class=md-nav__list data-md-scrollfix=""> </ul> </nav> <ul class=md-nav__list > <li class=md-nav__item > <a href="#references" class=md-nav__link >References</a> <li class=md-nav__item > <a href="#geometry-reciprocal-space-mapping-and-basic-quantities" class=md-nav__link >1. Geometry, reciprocal-space mapping, and basic quantities</a> <li class=md-nav__item > <a href="#azimuthal-integration-radial-profiles" class=md-nav__link >2. Azimuthal integration (radial profiles)</a> <li class=md-nav__item > <a href="#spot-finding-strong-pixels-bragg-spots" class=md-nav__link >3. Spot finding (strong pixels → Bragg spots)</a> <li class=md-nav__item > <a href="#indexing-overview" class=md-nav__link >4. Indexing overview</a> <li class=md-nav__item > <a href="#fft-indexing-unknown-unit-cell" class=md-nav__link >5. FFT indexing (unknown unit cell)</a> <li class=md-nav__item > <a href="#bravais-lattice-centering-inference-lattice-search" class=md-nav__link >6. Bravais lattice / centering inference (“lattice search”)</a> <li class=md-nav__item > <a href="#geometry-and-lattice-refinement" class=md-nav__link >7. Geometry and lattice refinement</a> <li class=md-nav__item > <a href="#reflection-prediction" class=md-nav__link >8. Reflection prediction</a> <li class=md-nav__item > <a href="#d-bragg-integration-profile-fitting-over-a-three-ring-roi" class=md-nav__link >9. 2D Bragg integration (profile fitting over a three-ring ROI)</a> <li class=md-nav__item > <a href="#scaling-and-merging" class=md-nav__link >10. Scaling and merging</a> <li class=md-nav__item > <a href="#mosaicity-and-profile-radius-monitoring" class=md-nav__link >11. Mosaicity and “profile radius” monitoring</a> <li class=md-nav__item > <a href="#auxiliary-statistics-i-i-and-wilson-plot" class=md-nav__link >12. Auxiliary statistics: ⟨I/σ(I)⟩ and Wilson plot</a> <li class=md-nav__item > <a href="#practical-notes-and-limitations" class=md-nav__link >13. Practical notes and limitations</a> </ul> <li class=md-nav__item > <a href=OPENAPI.html class=md-nav__link >OpenAPI</a> <li class=md-nav__item > <a href=OPENAPI_SPECS.html class=md-nav__link >OpenAPI specification</a> <li class=md-nav__item > <a href=CBOR.html class=md-nav__link >CBOR messages</a> <li class=md-nav__item > <a href=HDF5.html class=md-nav__link >HDF5 / NeXus data format</a> <li class=md-nav__item > <a href=IMAGE_STREAM.html class=md-nav__link >Data streams</a> <li class=md-nav__item > <a href=PIXEL_MASK.html class=md-nav__link >Pixel mask</a> <li class=md-nav__item > <a href=WEB_FRONTEND.html class=md-nav__link >Web frontend</a> <li class=md-nav__item > <a href=TESTS.html class=md-nav__link >Tests</a> <li class=md-nav__item > <span class="md-nav__link caption"><span class=caption-text >OpenAPI Python client</span></span> <li class=md-nav__item > <a href="python_client/README.html" class=md-nav__link >jfjoch-client</a> <li class=md-nav__item > <a href="python_client/README.html#license-clarification" class=md-nav__link >License Clarification</a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html" class=md-nav__link >jfjoch_client.DefaultApi</a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#cancel-post" class=md-nav__link ><strong>cancel_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-azim-int-get" class=md-nav__link ><strong>config_azim_int_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-azim-int-put" class=md-nav__link ><strong>config_azim_int_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-bragg-integration-get" class=md-nav__link ><strong>config_bragg_integration_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-bragg-integration-put" class=md-nav__link ><strong>config_bragg_integration_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-dark-mask-get" class=md-nav__link ><strong>config_dark_mask_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-dark-mask-put" class=md-nav__link ><strong>config_dark_mask_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-detector-get" class=md-nav__link ><strong>config_detector_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-detector-put" class=md-nav__link ><strong>config_detector_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-file-writer-get" class=md-nav__link ><strong>config_file_writer_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-file-writer-put" class=md-nav__link ><strong>config_file_writer_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-conversion-post" class=md-nav__link ><strong>config_image_format_conversion_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-get" class=md-nav__link ><strong>config_image_format_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-put" class=md-nav__link ><strong>config_image_format_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-raw-post" class=md-nav__link ><strong>config_image_format_raw_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-indexing-get" class=md-nav__link ><strong>config_indexing_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-indexing-put" class=md-nav__link ><strong>config_indexing_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-instrument-get" class=md-nav__link ><strong>config_instrument_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-instrument-put" class=md-nav__link ><strong>config_instrument_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-internal-generator-image-put" class=md-nav__link ><strong>config_internal_generator_image_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-internal-generator-image-tiff-put" class=md-nav__link ><strong>config_internal_generator_image_tiff_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-mask-get" class=md-nav__link ><strong>config_mask_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-mask-tiff-get" class=md-nav__link ><strong>config_mask_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-roi-get" class=md-nav__link ><strong>config_roi_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-roi-put" class=md-nav__link ><strong>config_roi_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-select-detector-get" class=md-nav__link ><strong>config_select_detector_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-select-detector-put" class=md-nav__link ><strong>config_select_detector_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-spot-finding-get" class=md-nav__link ><strong>config_spot_finding_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-spot-finding-put" class=md-nav__link ><strong>config_spot_finding_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-get" class=md-nav__link ><strong>config_user_mask_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-put" class=md-nav__link ><strong>config_user_mask_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-tiff-get" class=md-nav__link ><strong>config_user_mask_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-tiff-put" class=md-nav__link ><strong>config_user_mask_tiff_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-metadata-get" class=md-nav__link ><strong>config_zeromq_metadata_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-metadata-put" class=md-nav__link ><strong>config_zeromq_metadata_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-preview-get" class=md-nav__link ><strong>config_zeromq_preview_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-preview-put" class=md-nav__link ><strong>config_zeromq_preview_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#deactivate-post" class=md-nav__link ><strong>deactivate_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#detector-status-get" class=md-nav__link ><strong>detector_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#fpga-status-get" class=md-nav__link ><strong>fpga_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-clear-post" class=md-nav__link ><strong>image_buffer_clear_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-image-cbor-get" class=md-nav__link ><strong>image_buffer_image_cbor_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-image-jpeg-get" class=md-nav__link ><strong>image_buffer_image_jpeg_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-image-tiff-get" class=md-nav__link ><strong>image_buffer_image_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-start-cbor-get" class=md-nav__link ><strong>image_buffer_start_cbor_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-status-get" class=md-nav__link ><strong>image_buffer_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-pusher-status-get" class=md-nav__link ><strong>image_pusher_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#initialize-post" class=md-nav__link ><strong>initialize_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#pedestal-post" class=md-nav__link ><strong>pedestal_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#preview-pedestal-tiff-get" class=md-nav__link ><strong>preview_pedestal_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#preview-plot-bin-get" class=md-nav__link ><strong>preview_plot_bin_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#preview-plot-get" class=md-nav__link ><strong>preview_plot_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#result-scan-get" class=md-nav__link ><strong>result_scan_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#start-post" class=md-nav__link ><strong>start_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#statistics-calibration-get" class=md-nav__link ><strong>statistics_calibration_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#statistics-data-collection-get" class=md-nav__link ><strong>statistics_data_collection_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#statistics-get" class=md-nav__link ><strong>statistics_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#status-get" class=md-nav__link ><strong>status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#trigger-post" class=md-nav__link ><strong>trigger_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#version-get" class=md-nav__link ><strong>version_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#wait-till-done-post" class=md-nav__link ><strong>wait_till_done_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#wait-until-running-post" class=md-nav__link ><strong>wait_until_running_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#xfel-event-code-get" class=md-nav__link ><strong>xfel_event_code_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#xfel-pulse-id-get" class=md-nav__link ><strong>xfel_pulse_id_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/AzimIntSettings.html" class=md-nav__link >AzimIntSettings</a> <li class=md-nav__item > <a href="python_client/docs/BrokerStatus.html" class=md-nav__link >BrokerStatus</a> <li class=md-nav__item > <a href="python_client/docs/CalibrationStatisticsInner.html" class=md-nav__link >CalibrationStatisticsInner</a> <li class=md-nav__item > <a href="python_client/docs/ColorScale.html" class=md-nav__link >ColorScale</a> <li class=md-nav__item > <a href="python_client/docs/DarkMaskSettings.html" class=md-nav__link >DarkMaskSettings</a> <li class=md-nav__item > <a href="python_client/docs/DatasetSettings.html" class=md-nav__link >DatasetSettings</a> <li class=md-nav__item > <a href="python_client/docs/DatasetSettingsSmargon.html" class=md-nav__link >DatasetSettingsSmargon</a> <li class=md-nav__item > <a href="python_client/docs/DatasetSettingsUnitCell.html" class=md-nav__link >DatasetSettingsUnitCell</a> <li class=md-nav__item > <a href="python_client/docs/DatasetSettingsXrayFluorescenceSpectrum.html" class=md-nav__link >DatasetSettingsXrayFluorescenceSpectrum</a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html" class=md-nav__link >jfjoch_client.DefaultApi</a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#cancel-post" class=md-nav__link ><strong>cancel_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-azim-int-get" class=md-nav__link ><strong>config_azim_int_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-azim-int-put" class=md-nav__link ><strong>config_azim_int_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-bragg-integration-get" class=md-nav__link ><strong>config_bragg_integration_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-bragg-integration-put" class=md-nav__link ><strong>config_bragg_integration_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-dark-mask-get" class=md-nav__link ><strong>config_dark_mask_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-dark-mask-put" class=md-nav__link ><strong>config_dark_mask_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-detector-get" class=md-nav__link ><strong>config_detector_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-detector-put" class=md-nav__link ><strong>config_detector_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-file-writer-get" class=md-nav__link ><strong>config_file_writer_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-file-writer-put" class=md-nav__link ><strong>config_file_writer_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-conversion-post" class=md-nav__link ><strong>config_image_format_conversion_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-get" class=md-nav__link ><strong>config_image_format_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-put" class=md-nav__link ><strong>config_image_format_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-image-format-raw-post" class=md-nav__link ><strong>config_image_format_raw_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-indexing-get" class=md-nav__link ><strong>config_indexing_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-indexing-put" class=md-nav__link ><strong>config_indexing_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-instrument-get" class=md-nav__link ><strong>config_instrument_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-instrument-put" class=md-nav__link ><strong>config_instrument_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-internal-generator-image-put" class=md-nav__link ><strong>config_internal_generator_image_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-internal-generator-image-tiff-put" class=md-nav__link ><strong>config_internal_generator_image_tiff_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-mask-get" class=md-nav__link ><strong>config_mask_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-mask-tiff-get" class=md-nav__link ><strong>config_mask_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-roi-get" class=md-nav__link ><strong>config_roi_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-roi-put" class=md-nav__link ><strong>config_roi_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-select-detector-get" class=md-nav__link ><strong>config_select_detector_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-select-detector-put" class=md-nav__link ><strong>config_select_detector_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-spot-finding-get" class=md-nav__link ><strong>config_spot_finding_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-spot-finding-put" class=md-nav__link ><strong>config_spot_finding_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-get" class=md-nav__link ><strong>config_user_mask_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-put" class=md-nav__link ><strong>config_user_mask_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-tiff-get" class=md-nav__link ><strong>config_user_mask_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-user-mask-tiff-put" class=md-nav__link ><strong>config_user_mask_tiff_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-metadata-get" class=md-nav__link ><strong>config_zeromq_metadata_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-metadata-put" class=md-nav__link ><strong>config_zeromq_metadata_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-preview-get" class=md-nav__link ><strong>config_zeromq_preview_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#config-zeromq-preview-put" class=md-nav__link ><strong>config_zeromq_preview_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#deactivate-post" class=md-nav__link ><strong>deactivate_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#detector-status-get" class=md-nav__link ><strong>detector_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#fpga-status-get" class=md-nav__link ><strong>fpga_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-clear-post" class=md-nav__link ><strong>image_buffer_clear_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-image-cbor-get" class=md-nav__link ><strong>image_buffer_image_cbor_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-image-jpeg-get" class=md-nav__link ><strong>image_buffer_image_jpeg_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-image-tiff-get" class=md-nav__link ><strong>image_buffer_image_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-start-cbor-get" class=md-nav__link ><strong>image_buffer_start_cbor_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-buffer-status-get" class=md-nav__link ><strong>image_buffer_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#image-pusher-status-get" class=md-nav__link ><strong>image_pusher_status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#initialize-post" class=md-nav__link ><strong>initialize_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#pedestal-post" class=md-nav__link ><strong>pedestal_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#preview-pedestal-tiff-get" class=md-nav__link ><strong>preview_pedestal_tiff_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#preview-plot-bin-get" class=md-nav__link ><strong>preview_plot_bin_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#preview-plot-get" class=md-nav__link ><strong>preview_plot_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#result-scan-get" class=md-nav__link ><strong>result_scan_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#start-post" class=md-nav__link ><strong>start_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#statistics-calibration-get" class=md-nav__link ><strong>statistics_calibration_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#statistics-data-collection-get" class=md-nav__link ><strong>statistics_data_collection_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#statistics-get" class=md-nav__link ><strong>statistics_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#status-get" class=md-nav__link ><strong>status_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#trigger-post" class=md-nav__link ><strong>trigger_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#version-get" class=md-nav__link ><strong>version_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#wait-till-done-post" class=md-nav__link ><strong>wait_till_done_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#wait-until-running-post" class=md-nav__link ><strong>wait_until_running_post</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#xfel-event-code-get" class=md-nav__link ><strong>xfel_event_code_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/DefaultApi.html#xfel-pulse-id-get" class=md-nav__link ><strong>xfel_pulse_id_get</strong></a> <li class=md-nav__item > <a href="python_client/docs/Detector.html" class=md-nav__link >Detector</a> <li class=md-nav__item > <a href="python_client/docs/DetectorList.html" class=md-nav__link >DetectorList</a> <li class=md-nav__item > <a href="python_client/docs/DetectorListDetectorsInner.html" class=md-nav__link >DetectorListDetectorsInner</a> <li class=md-nav__item > <a href="python_client/docs/DetectorListElement.html" class=md-nav__link >DetectorListElement</a> <li class=md-nav__item > <a href="python_client/docs/DetectorModule.html" class=md-nav__link >DetectorModule</a> <li class=md-nav__item > <a href="python_client/docs/DetectorModuleDirection.html" class=md-nav__link >DetectorModuleDirection</a> <li class=md-nav__item > <a href="python_client/docs/DetectorPowerState.html" class=md-nav__link >DetectorPowerState</a> <li class=md-nav__item > <a href="python_client/docs/DetectorSelection.html" class=md-nav__link >DetectorSelection</a> <li class=md-nav__item > <a href="python_client/docs/DetectorSettings.html" class=md-nav__link >DetectorSettings</a> <li class=md-nav__item > <a href="python_client/docs/DetectorState.html" class=md-nav__link >DetectorState</a> <li class=md-nav__item > <a href="python_client/docs/DetectorStatus.html" class=md-nav__link >DetectorStatus</a> <li class=md-nav__item > <a href="python_client/docs/DetectorTiming.html" class=md-nav__link >DetectorTiming</a> <li class=md-nav__item > <a href="python_client/docs/DetectorType.html" class=md-nav__link >DetectorType</a> <li class=md-nav__item > <a href="python_client/docs/ErrorMessage.html" class=md-nav__link >ErrorMessage</a> <li class=md-nav__item > <a href="python_client/docs/FileWriterFormat.html" class=md-nav__link >FileWriterFormat</a> <li class=md-nav__item > <a href="python_client/docs/FileWriterSettings.html" class=md-nav__link >FileWriterSettings</a> <li class=md-nav__item > <a href="python_client/docs/FpgaStatusInner.html" class=md-nav__link >FpgaStatusInner</a> <li class=md-nav__item > <a href="python_client/docs/GeomRefinementAlgorithm.html" class=md-nav__link >GeomRefinementAlgorithm</a> <li class=md-nav__item > <a href="python_client/docs/GridPlot.html" class=md-nav__link >GridPlot</a> <li class=md-nav__item > <a href="python_client/docs/GridPlots.html" class=md-nav__link >GridPlots</a> <li class=md-nav__item > <a href="python_client/docs/GridScan.html" class=md-nav__link >GridScan</a> <li class=md-nav__item > <a href="python_client/docs/GridScanResult.html" class=md-nav__link >GridScanResult</a> <li class=md-nav__item > <a href="python_client/docs/GridScanResultImagesInner.html" class=md-nav__link >GridScanResultImagesInner</a> <li class=md-nav__item > <a href="python_client/docs/ImageBufferStatus.html" class=md-nav__link >ImageBufferStatus</a> <li class=md-nav__item > <a href="python_client/docs/ImageFormatSettings.html" class=md-nav__link >ImageFormatSettings</a> <li class=md-nav__item > <a href="python_client/docs/ImagePusherStatus.html" class=md-nav__link >ImagePusherStatus</a> <li class=md-nav__item > <a href="python_client/docs/ImagePusherType.html" class=md-nav__link >ImagePusherType</a> <li class=md-nav__item > <a href="python_client/docs/IndexingAlgorithm.html" class=md-nav__link >IndexingAlgorithm</a> <li class=md-nav__item > <a href="python_client/docs/IndexingSettings.html" class=md-nav__link >IndexingSettings</a> <li class=md-nav__item > <a href="python_client/docs/InstrumentMetadata.html" class=md-nav__link >InstrumentMetadata</a> <li class=md-nav__item > <a href="python_client/docs/JfjochBrokerApi.html" class=md-nav__link >jfjoch_client.JfjochBrokerApi</a> <li class=md-nav__item > <a href="python_client/docs/JfjochBrokerApi.html#config-zeromq-metadata-put" class=md-nav__link ><strong>config_zeromq_metadata_put</strong></a> <li class=md-nav__item > <a href="python_client/docs/JfjochSettings.html" class=md-nav__link >JfjochSettings</a> <li class=md-nav__item > <a href="python_client/docs/JfjochSettingsSsl.html" class=md-nav__link >JfjochSettingsSsl</a> <li class=md-nav__item > <a href="python_client/docs/JfjochStatistics.html" class=md-nav__link >JfjochStatistics</a> <li class=md-nav__item > <a href="python_client/docs/MeasurementStatistics.html" class=md-nav__link >MeasurementStatistics</a> <li class=md-nav__item > <a href="python_client/docs/PcieDevicesInner.html" class=md-nav__link >PcieDevicesInner</a> <li class=md-nav__item > <a href="python_client/docs/PixelMaskStatistics.html" class=md-nav__link >PixelMaskStatistics</a> <li class=md-nav__item > <a href="python_client/docs/Plot.html" class=md-nav__link >Plot</a> <li class=md-nav__item > <a href="python_client/docs/PlotTypeEnum.html" class=md-nav__link >PlotTypeEnum</a> <li class=md-nav__item > <a href="python_client/docs/PlotUnitX.html" class=md-nav__link >PlotUnitX</a> <li class=md-nav__item > <a href="python_client/docs/Plots.html" class=md-nav__link >Plots</a> <li class=md-nav__item > <a href="python_client/docs/PreviewSettings.html" class=md-nav__link >PreviewSettings</a> <li class=md-nav__item > <a href="python_client/docs/RoiAzimList.html" class=md-nav__link >RoiAzimList</a> <li class=md-nav__item > <a href="python_client/docs/RoiAzimuthal.html" class=md-nav__link >RoiAzimuthal</a> <li class=md-nav__item > <a href="python_client/docs/RoiBox.html" class=md-nav__link >RoiBox</a> <li class=md-nav__item > <a href="python_client/docs/RoiBoxList.html" class=md-nav__link >RoiBoxList</a> <li class=md-nav__item > <a href="python_client/docs/RoiCircle.html" class=md-nav__link >RoiCircle</a> <li class=md-nav__item > <a href="python_client/docs/RoiCircleList.html" class=md-nav__link >RoiCircleList</a> <li class=md-nav__item > <a href="python_client/docs/RoiDefinitions.html" class=md-nav__link >RoiDefinitions</a> <li class=md-nav__item > <a href="python_client/docs/RotationAxis.html" class=md-nav__link >RotationAxis</a> <li class=md-nav__item > <a href="python_client/docs/ScanResult.html" class=md-nav__link >ScanResult</a> <li class=md-nav__item > <a href="python_client/docs/ScanResultImagesInner.html" class=md-nav__link >ScanResultImagesInner</a> <li class=md-nav__item > <a href="python_client/docs/SpotFindingSettings.html" class=md-nav__link >SpotFindingSettings</a> <li class=md-nav__item > <a href="python_client/docs/StandardDetectorGeometry.html" class=md-nav__link >StandardDetectorGeometry</a> <li class=md-nav__item > <a href="python_client/docs/TcpSettings.html" class=md-nav__link >TcpSettings</a> <li class=md-nav__item > <a href="python_client/docs/UnitCell.html" class=md-nav__link >UnitCell</a> <li class=md-nav__item > <a href="python_client/docs/ZeromqMetadataSettings.html" class=md-nav__link >ZeromqMetadataSettings</a> <li class=md-nav__item > <a href="python_client/docs/ZeromqPreviewSettings.html" class=md-nav__link >ZeromqPreviewSettings</a> <li class=md-nav__item > <a href="python_client/docs/ZeromqSettings.html" class=md-nav__link >ZeromqSettings</a> </ul> </nav> </div> </div> </div> <div class="md-sidebar md-sidebar--secondary" data-md-component=toc > <div class=md-sidebar__scrollwrap > <div class=md-sidebar__inner > <nav class="md-nav md-nav--secondary"> <ul class=md-nav__list data-md-scrollfix=""> </ul> </nav> </div> </div> </div> <div class=md-content > <article class="md-content__inner md-typeset" role=main > <section class="tex2jax_ignore mathjax_ignore" id=cpu-side-crystallographic-data-analysis-jungfraujoch > <h1 id=cpu-data-analysis--page-root >CPU-side crystallographic data analysis (Jungfraujoch)<a class=headerlink href="#cpu-data-analysis--page-root" title="Link to this heading">¶</a></h1> <p>This document describes the crystallographic algorithms implemented in Jungfraujoch for <strong>CPU</strong>- and <strong>GPU</strong>-side real‑time and near‑real‑time data analysis.</p> <p><strong>Scope.</strong> The pipeline covered here comprises:</p> <ol class="arabic simple"> <li><p>geometry mapping and corrections,</p> <li><p>azimuthal integration (powder/radial profiles),</p> <li><p>Bragg spot finding (strong pixels → connected components → spot descriptors),</p> <li><p>indexing (still and rotation modes),</p> <li><p>Bravais lattice / centering inference,</p> <li><p>geometry and lattice refinement,</p> <li><p>reflection prediction (still and rotation),</p> <li><p>Bragg integration by either 2D box summation or profile fitting (Kabsch, reference-free),</p> <li><p>scaling and merging,</p> <li><p>merge-level error modelling and outlier rejection,</p> <li><p>auxiliary statistics (Wilson plot, ⟨I/σ(I)⟩, CC1/2, CCref).</p> </ol> <section id=references > <h2 id=references >References<a class=headerlink href="#references" title="Link to this heading">¶</a></h2> <p>The methods are inspired and reuising solutions implemented in:</p> <ul class=simple > <li><p>W. Kabsch, “XDS”, <em>Acta Cryst.</em> <strong>D66</strong> (2010), 125–132 and related XDS papers (rotation geometry, partiality, scaling concepts).</p> <li><p>W. Kabsch, “Integration, scaling, space-group assignment and post-refinement”, <em>Acta Cryst.</em> <strong>D66</strong> (2010), 133–144 (mosaicity/partiality likelihood treatment; notation such as ζ and rotation factors).</p> <li><p>T. A. White et al., CrystFEL method papers (spot finding, three‑ring integration, serial/still diffraction processing concepts).</p> <li><p>J. Kieffer & J. P. Wright, “PyFAI: a Python library for high performance azimuthal integration on GPU”, <em>Powder Diffraction</em> <strong>28</strong> (2013), S339-S350 (detector geometry definition, azimuthal integration)</p> <li><p>H. Powell, “The Rossmann Fourier autoindexing algorithm in MOSFLM”, <em>Acta Cryst.</em> <strong>D55</strong> (1999), 1690-1695 (FFT indexing) (list is not exhaustive)</p> </ul> </section> <section id=geometry-reciprocal-space-mapping-and-basic-quantities > <h2 id=geometry-reciprocal-space-mapping-and-basic-quantities >1. Geometry, reciprocal-space mapping, and basic quantities<a class=headerlink href="#geometry-reciprocal-space-mapping-and-basic-quantities" title="Link to this heading">¶</a></h2> <section id=coordinate-conventions > <h3 id=coordinate-conventions >1.1 Coordinate conventions<a class=headerlink href="#coordinate-conventions" title="Link to this heading">¶</a></h3> <p>For a pixel coordinate <span class="math notranslate nohighlight">\((x,y)\)</span> (in pixels), Jungfraujoch converts to a laboratory direction vector via:</p> <ol class="arabic simple"> <li><p>shift by direct-beam position <span class="math notranslate nohighlight">\((x_\mathrm{beam}, y_\mathrm{beam})\)</span>,</p> <li><p>scale by pixel size <span class="math notranslate nohighlight">\(p\)</span> (mm),</p> <li><p>set detector distance <span class="math notranslate nohighlight">\(D\)</span> (mm),</p> <li><p>apply detector orientation rotation <span class="math notranslate nohighlight">\(R_\mathrm{det}\)</span> (PyFAI-like parameterization).</p> </ol> <p>The unnormalized detector coordinate (mm) is: <span class="math notranslate nohighlight">\( \mathbf{r}_\mathrm{det}(x,y) = \begin{pmatrix} (x-x_\mathrm{beam})p\\ (y-y_\mathrm{beam})p\\ D \end{pmatrix}. \)</span></p> <p>The lab-frame vector is: <span class="math notranslate nohighlight">\( \mathbf{r}_\mathrm{lab} = R_\mathrm{det}\,\mathbf{r}_\mathrm{det}. \)</span></p> <p>Let the incident wavevector magnitude be <span class="math notranslate nohighlight">\(k = 1/\lambda\)</span> in Å<span class="math notranslate nohighlight">\(^{-1}\)</span>, and define: <span class="math notranslate nohighlight">\( \mathbf{S}_0 = (0,0,k). \)</span></p> <p>The <strong>reciprocal-space scattering vector</strong> associated with pixel <span class="math notranslate nohighlight">\((x,y)\)</span> is: <span class="math notranslate nohighlight">\( \mathbf{s}(x,y) = k\,\frac{\mathbf{r}_\mathrm{lab}}{\lVert \mathbf{r}_\mathrm{lab}\rVert} - \mathbf{S}_0. \)</span></p> <p>This <span class="math notranslate nohighlight">\(\mathbf{s}\)</span> is the fundamental quantity used for spot finding (resolution filters), indexing, and refinement.</p> </section> <section id=two-theta-azimuth-resolution-and-q > <h3 id=two-theta-azimuth-resolution-and-q >1.2 Two-theta, azimuth, resolution and <span class="math notranslate nohighlight">\(q\)</span><a class=headerlink href="#two-theta-azimuth-resolution-and-q" title="Link to this heading">¶</a></h3> <p>The scattering angle <span class="math notranslate nohighlight">\(2\theta\)</span> is computed from <span class="math notranslate nohighlight">\(\mathbf{r}_\mathrm{lab}\)</span> via: <span class="math notranslate nohighlight">\( 2\theta = \arctan\!\left(\frac{\sqrt{x_\mathrm{lab}^2 + y_\mathrm{lab}^2}}{z_\mathrm{lab}}\right). \)</span></p> <p>Resolution (Å) at a pixel is: <span class="math notranslate nohighlight">\( d = \frac{\lambda}{2\sin(\theta)} = \frac{\lambda}{2\sin(2\theta/2)}. \)</span></p> <p>The magnitude <span class="math notranslate nohighlight">\(q = 2\pi/d\)</span> is used for radial binning and ice-ring handling.</p> </section> <section id=distance-from-the-ewald-sphere > <h3 id=distance-from-the-ewald-sphere >1.3 Distance from the Ewald sphere<a class=headerlink href="#distance-from-the-ewald-sphere" title="Link to this heading">��</a></h3> <p>For a reciprocal lattice point <span class="math notranslate nohighlight">\(\mathbf{p}\)</span> (Å<span class="math notranslate nohighlight">\(^{-1}\)</span>), define: <span class="math notranslate nohighlight">\( \Delta_\mathrm{Ewald}(\mathbf{p}) = \lVert \mathbf{p} + \mathbf{S}_0\rVert - k. \)</span> Jungfraujoch uses <span class="math notranslate nohighlight">\(|\Delta_\mathrm{Ewald}|\)</span> as an operational proxy for excitation error. This appears in:</p> <ul class=simple > <li><p>still prediction (accept if <span class="math notranslate nohighlight">\(|\Delta_\mathrm{Ewald}|\le \Delta_\mathrm{cut}\)</span>),</p> <li><p>profile radius estimation (see §11.1),</p> <li><p>still partiality option in scaling/merging (§10.2).</p> </ul> </section> </section> <hr class=docutils /> <section id=azimuthal-integration-radial-profiles > <h2 id=azimuthal-integration-radial-profiles >2. Azimuthal integration (radial profiles)<a class=headerlink href="#azimuthal-integration-radial-profiles" title="Link to this heading">¶</a></h2> <p>Azimuthal integration produces a radial profile <span class="math notranslate nohighlight">\(I(q)\)</span> or <span class="math notranslate nohighlight">\(I(d)\)</span> by histogramming pixels into radial bins. Pixels are <strong>not split</strong> across bins; each pixel contributes wholly to a single bin. By default the profile is purely radial (a single azimuthal bin), but the azimuth can optionally be split into up to 512 <span class="math notranslate nohighlight">\(\phi\)</span> sectors (<code class="docutils literal notranslate"><span class=pre >azim_bins</span></code>, <code class="docutils literal notranslate"><span class=pre >--azim-phi-bins</span></code>), giving a <strong>2D <span class="math notranslate nohighlight">\(q\times\phi\)</span> profile</strong> that exposes azimuthal anisotropy such as detector shadowing or sample texture.</p> <section id=histogram-estimator > <h3 id=histogram-estimator >2.1 Histogram estimator<a class=headerlink href="#histogram-estimator" title="Link to this heading">¶</a></h3> <p>Let bin index <span class="math notranslate nohighlight">\(b(x,y)\)</span> be precomputed from <span class="math notranslate nohighlight">\(q(x,y)\)</span> (or equivalently from <span class="math notranslate nohighlight">\(d(x,y)\)</span>) and, when <span class="math notranslate nohighlight">\(\phi\)</span> sectors are enabled, the azimuth <span class="math notranslate nohighlight">\(\phi(x,y)\)</span> — so <span class="math notranslate nohighlight">\(b = b_q + b_\phi B_q\)</span>. For each bin <span class="math notranslate nohighlight">\(b\)</span>:</p> <ul class=simple > <li><p>accumulate corrected intensity and its square: <span class="math notranslate nohighlight">\( S_b = \sum_{(x,y):\,b(x,y)=b} I(x,y)\,C(x,y),\qquad S^{(2)}_b = \sum I(x,y)^2\,C(x,y)^2, \)</span></p> <li><p>and count: <span class="math notranslate nohighlight">\( N_b = \#\{(x,y):\,b(x,y)=b \text{ and pixel is valid}\}. \)</span></p> </ul> <p>The profile reports both the mean <span class="math notranslate nohighlight">\(\bar{I}_b = S_b / N_b\)</span> (when <span class="math notranslate nohighlight">\(N_b>0\)</span>) and a per-bin sample standard deviation <span class="math notranslate nohighlight">\(\sigma_b = \sqrt{(S^{(2)}_b - S_b^2/N_b)/(N_b-1)}\)</span> (a spread/error estimate for each radial point). Invalid pixels (masked, saturated, detector error codes) are excluded.</p> </section> <section id=corrections-applied > <h3 id=corrections-applied >2.2 Corrections applied<a class=headerlink href="#corrections-applied" title="Link to this heading">¶</a></h3> <p>Two standard corrections are available:</p> <p><strong>(i) Solid angle / geometric correction.</strong> A flat pixel’s solid angle falls off with the <strong>incidence angle <span class="math notranslate nohighlight">\(\alpha\)</span> between the scattered ray and the detector normal</strong>. With the in-plane detector offsets <span class="math notranslate nohighlight">\(u=(x-x_\mathrm{beam})p\)</span> and <span class="math notranslate nohighlight">\(v=(y-y_\mathrm{beam})p\)</span> (§1.1) and detector distance <span class="math notranslate nohighlight">\(D\)</span>, <span class="math notranslate nohighlight">\( \cos\alpha = \frac{D}{\sqrt{u^2+v^2+D^2}},\qquad C_\Omega = \cos^3\alpha, \)</span> applied — like the polarization term below — as a <strong>divisor</strong> (intensities are scaled by <span class="math notranslate nohighlight">\(1/\cos^3\alpha\)</span>), so pixels at oblique incidence, which subtend a smaller solid angle, are boosted. Because <span class="math notranslate nohighlight">\(\alpha\)</span> is evaluated in the detector’s own frame it is <strong>invariant under detector tilt</strong> (<span class="math notranslate nohighlight">\(\mathrm{rot1}/\mathrm{rot2}/\mathrm{rot3}\)</span>), matching PyFAI’s <code class="docutils literal notranslate"><span class=pre >solidAngleArray</span></code> and MAX IV azint. It reduces to the commonly quoted <span class="math notranslate nohighlight">\(\cos^3(2\theta)\)</span> form only for an untilted detector, where the incidence angle coincides with the scattering angle.</p> <p><strong>(ii) Polarization correction.</strong> With polarization coefficient <span class="math notranslate nohighlight">\(P\)</span> (beamline dependent) and azimuth <span class="math notranslate nohighlight">\(\phi\)</span>: <span class="math notranslate nohighlight">\( C_\mathrm{pol}(2\theta,\phi) = \frac{1}{2}\left(1+\cos^2(2\theta) - P\cos(2\phi)\left(1-\cos^2(2\theta)\right)\right), \)</span> applied as a divisor to intensities (i.e. scale by <span class="math notranslate nohighlight">\(1/C_\mathrm{pol}\)</span>) when enabled.</p> </section> <section id=background-estimate-for-profiles > <h3 id=background-estimate-for-profiles >2.3 Background estimate for profiles<a class=headerlink href="#background-estimate-for-profiles" title="Link to this heading">¶</a></h3> <p>A background estimate is derived from the profile as its mean intensity over a fixed low-to-mid <span class="math notranslate nohighlight">\(Q\)</span> window (default <span class="math notranslate nohighlight">\(2\pi/5\)</span> to <span class="math notranslate nohighlight">\(2\pi/3\)</span> Å<span class="math notranslate nohighlight">\(^{-1}\)</span>). This background is used for monitoring and diagnostics; it is <strong>not</strong> the same as the local Bragg-spot background used in summation integration (§9.2).</p> </section> </section> <hr class=docutils /> <section id=spot-finding-strong-pixels-bragg-spots > <h2 id=spot-finding-strong-pixels-bragg-spots >3. Spot finding (strong pixels → Bragg spots)<a class=headerlink href="#spot-finding-strong-pixels-bragg-spots" title="Link to this heading">¶</a></h2> <p>Spot finding is a two-stage process:</p> <ol class="arabic simple"> <li><p><strong>Strong-pixel selection</strong> using intensity and/or local signal-to-noise criteria.</p> <li><p><strong>Connected-component labeling (CCL)</strong> to group strong pixels into candidate spots, followed by spot-level filtering and feature extraction.</p> </ol> <section id=strong-pixel-detection-by-local-statistics > <h3 id=strong-pixel-detection-by-local-statistics >3.1 Strong-pixel detection by local statistics<a class=headerlink href="#strong-pixel-detection-by-local-statistics" title="Link to this heading">¶</a></h3> <p>For each pixel <span class="math notranslate nohighlight">\(i\)</span> with value <span class="math notranslate nohighlight">\(v_i\)</span>, consider a square window (nominally <span class="math notranslate nohighlight">\(31\times 31\)</span> pixels) around it. Let the window contain <span class="math notranslate nohighlight">\(n\)</span> valid pixels (excluding masked/bad/saturated), and define: <span class="math notranslate nohighlight">\( \Sigma = \sum v,\qquad \Sigma_2 = \sum v^2. \)</span></p> <p>To avoid biasing the local statistics by the test pixel itself, Jungfraujoch evaluates the pixel against the window with the pixel removed: <span class="math notranslate nohighlight">\( \Sigma' = \Sigma - v_i,\quad \Sigma_2' = \Sigma_2 - v_i^2,\quad n' = n-1. \)</span></p> <p>A variance-like quantity proportional to <span class="math notranslate nohighlight">\(n'^2\)</span> is formed: <span class="math notranslate nohighlight">\( V = n'\Sigma_2' - (\Sigma')^2, \)</span> and the deviation-from-mean quantity: <span class="math notranslate nohighlight">\( \Delta = v_i n' - \Sigma'. \)</span></p> <p>A pixel is considered strong if:</p> <ul class=simple > <li><p>it is above a photon/count threshold, and</p> <li><p>its window contains enough valid neighbours (more than 100), so the local statistics are meaningful, and</p> <li><p><span class="math notranslate nohighlight">\(\Delta>0\)</span>, and</p> <li><p>the squared deviation exceeds a scaled variance: <span class="math notranslate nohighlight">\( \Delta^2 > V\cdot T^2, \)</span> where <span class="math notranslate nohighlight">\(T\)</span> is the configured signal-to-noise threshold.</p> </ul> <p>This is equivalent to a local z-score criterion but implemented in integer arithmetic to be robust and fast.</p> <p>Special cases:</p> <ul class=simple > <li><p>saturated pixels can be forced to “strong” (useful for detecting overloaded Bragg spots),</p> <li><p>invalid pixels are never strong.</p> </ul> </section> <section id=resolution-and-ice-ring-handling > <h3 id=resolution-and-ice-ring-handling >3.2 Resolution and ice-ring handling<a class=headerlink href="#resolution-and-ice-ring-handling" title="Link to this heading">¶</a></h3> <p>Spot finding can be restricted to a resolution range <span class="math notranslate nohighlight">\([d_\mathrm{high}, d_\mathrm{low}]\)</span> by masking pixels outside the range. Optionally, spots in identified ice-ring regions can be tagged so that subsequent indexing/refinement may include or exclude them (see §4 and §6).</p> <p>A single per-image <strong>ice-ring score</strong> is derived from the azimuthally-integrated radial profile: for each hexagonal-ice powder ring (positions <span class="math notranslate nohighlight">\(d\)</span> from Moreau <em>et al.</em>, Acta Cryst D77, 2021), the profile intensity at the ring is divided by a smooth background estimated from the <em>whole</em> profile — a running median of the non-ice bins, interpolated under each ring — and the strongest ring’s ratio is reported (1 = no ice, <span class="math notranslate nohighlight">\(>1\)</span> = ice above background). A whole-profile background is used rather than a couple of adjacent shoulder bins so the estimate is robust to the radial binning: at a coarse Q-spacing a local shoulder can be only ~1 bin and would double-count the ring’s own edge (offline processing defaults to a fine 0.01 1/Å spacing, <code class="docutils literal notranslate"><span class=pre >--azim-q-spacing</span></code>, so the rings are well resolved). (A significance/z-score was considered but is uninformative here: with many photons any real ice ring is highly significant, so the discriminating quantity is the ice <em>magnitude</em>, i.e. this ratio.) It is stored per image (<code class="docutils literal notranslate"><span class=pre >ice_ring_score</span></code>, HDF5 <code class="docutils literal notranslate"><span class=pre >/entry/MX/iceRingScore</span></code>) as a monitoring quantity, distinct from the merge-time ice masking, which is data-driven from the per-ring merged CC1/2.</p> <p>A further optional safeguard removes isolated high-resolution “spur” spots by detecting large gaps in <span class="math notranslate nohighlight">\(1/d\)</span> (or <span class="math notranslate nohighlight">\(q\)</span>) space and discarding spots beyond the gap. This is intended for macromolecular diffraction where edge-of-detector backgrounds can be extremely low.</p> </section> <section id=connected-component-labeling-ccl > <h3 id=connected-component-labeling-ccl >3.3 Connected-component labeling (CCL)<a class=headerlink href="#connected-component-labeling-ccl" title="Link to this heading">¶</a></h3> <p>Strong pixels are grouped into connected components (adjacent strong pixels) using a CCL algorithm. Each component yields a candidate spot with:</p> <ul class=simple > <li><p>centroid <span class="math notranslate nohighlight">\((x,y)\)</span> (often intensity-weighted),</p> <li><p>pixel count (spot size),</p> <li><p>integrated spot intensity proxy (sum of pixel values),</p> <li><p>resolution <span class="math notranslate nohighlight">\(d\)</span> at the centroid (or mean over pixels),</p> <li><p>and quality flags (e.g. ice-ring classification).</p> </ul> <p>Spot-level filters include minimum/maximum pixel count and resolution limits.</p> </section> </section> <hr class=docutils /> <section id=indexing-overview > <h2 id=indexing-overview >4. Indexing overview<a class=headerlink href="#indexing-overview" title="Link to this heading">¶</a></h2> <p>Indexing maps observed reciprocal-space vectors <span class="math notranslate nohighlight">\(\mathbf{s}_i\)</span> to a lattice such that: <span class="math notranslate nohighlight">\( \mathbf{s}_i \approx h_i\mathbf{a}^* + k_i\mathbf{b}^* + l_i\mathbf{c}^*, \)</span> with integer <span class="math notranslate nohighlight">\((h_i,k_i,l_i)\)</span>.</p> <p>Jungfraujoch supports two complementary indexing strategies:</p> <ol class="arabic simple"> <li><p><strong>FFT-based indexing</strong> (Rossmann-type): does not require an a priori unit cell; suitable for unknown samples.</p> <li><p><strong>Fast-feedback indexing</strong> (TORO-like): requires an approximate unit cell; optimized for speed and feedback.</p> </ol> <p>Both feed into a common robust refinement/selection stage which maximizes the number of inliers under an indexing tolerance, and which can return <strong>more than one lattice</strong> per image (multi-lattice indexing; see §5.4).</p> <section id=indexed-spot-decision-inlier-test > <h3 id=indexed-spot-decision-inlier-test >4.1 Indexed-spot decision (inlier test)<a class=headerlink href="#indexed-spot-decision-inlier-test" title="Link to this heading">¶</a></h3> <p>Given a trial lattice with direct basis vectors <span class="math notranslate nohighlight">\(\mathbf{a},\mathbf{b},\mathbf{c}\)</span> (used here as reciprocal-space dot-test vectors), fractional indices are estimated by: <span class="math notranslate nohighlight">\( h_f = \mathbf{s}\cdot\mathbf{a},\quad k_f = \mathbf{s}\cdot\mathbf{b},\quad l_f = \mathbf{s}\cdot\mathbf{c}. \)</span> Let <span class="math notranslate nohighlight">\((h,k,l)=(\mathrm{round}(h_f),\mathrm{round}(k_f),\mathrm{round}(l_f))\)</span> and define the fractional residual: <span class="math notranslate nohighlight">\( \delta^2 = (h_f-h)^2 + (k_f-k)^2 + (l_f-l)^2. \)</span> A spot is indexed if <span class="math notranslate nohighlight">\(\delta^2 < \tau^2\)</span>, where <span class="math notranslate nohighlight">\(\tau\)</span> is the configured tolerance.</p> <p>For indexed spots, the reciprocal lattice point <span class="math notranslate nohighlight">\(\mathbf{p} = h\mathbf{a}^*+k\mathbf{b}^*+l\mathbf{c}^*\)</span> is used to compute <span class="math notranslate nohighlight">\(\Delta_\mathrm{Ewald}(\mathbf{p})\)</span> (stored as a diagnostic and later used in profile-radius estimation).</p> </section> </section> <hr class=docutils /> <section id=fft-indexing-unknown-unit-cell > <h2 id=fft-indexing-unknown-unit-cell >5. FFT indexing (unknown unit cell)<a class=headerlink href="#fft-indexing-unknown-unit-cell" title="Link to this heading">¶</a></h2> <p>FFT indexing follows a classical approach: detect dominant periodicities by projecting reciprocal-space points onto many directions and Fourier transforming the resulting 1D histograms.</p> <section id=directional-projections-and-histograms > <h3 id=directional-projections-and-histograms >5.1 Directional projections and histograms<a class=headerlink href="#directional-projections-and-histograms" title="Link to this heading">¶</a></h3> <p>Choose a set of unit vectors <span class="math notranslate nohighlight">\(\{\mathbf{u}_d\}\)</span> on a half-sphere (a near-uniform distribution generated via a golden-angle construction). For each direction <span class="math notranslate nohighlight">\(d\)</span>, form a histogram in the scalar projection: <span class="math notranslate nohighlight">\( t_{id} = \left|\mathbf{u}_d\cdot \mathbf{s}_i\right|. \)</span></p> <p>Bin width is chosen approximately as: <span class="math notranslate nohighlight">\( \Delta t \approx \frac{1}{2 L_\mathrm{max}}, \)</span> where <span class="math notranslate nohighlight">\(L_\mathrm{max}\)</span> is the maximum expected real-space unit-cell edge (Å). The histogram extent is tied to the maximum <span class="math notranslate nohighlight">\(q\)</span> used (set by a high-resolution cutoff for indexing).</p> </section> <section id=fft-peak-picking-and-candidate-vectors > <h3 id=fft-peak-picking-and-candidate-vectors >5.2 FFT peak picking and candidate vectors<a class=headerlink href="#fft-peak-picking-and-candidate-vectors" title="Link to this heading">¶</a></h3> <p>For each direction, the FFT magnitude spectrum is computed; peaks correspond to periodicities along <span class="math notranslate nohighlight">\(\mathbf{u}_d\)</span>. Each direction yields a candidate real-space length <span class="math notranslate nohighlight">\(L\)</span> chosen <strong>not</strong> by raw magnitude but by <strong>maximum prominence above a running-mean local background</strong> (subtracting the broad low-frequency envelope that otherwise dominates on weak or pink-beam frames), subject to <span class="math notranslate nohighlight">\(L\ge L_\mathrm{min}\)</span>.</p> <p>Candidate vectors are <span class="math notranslate nohighlight">\(\mathbf{v}_d = L_d\,\mathbf{u}_d\)</span>.</p> <p>A collinearity filter removes nearly parallel vectors (e.g. within 5°) and attempts to resolve harmonic ambiguity: shorter “fundamental” vectors may be preferred over longer harmonics if their peak magnitude is sufficiently strong relative to the dominant peak.</p> </section> <section id=lattice-reduction-and-cell-candidates > <h3 id=lattice-reduction-and-cell-candidates >5.3 Lattice reduction and cell candidates<a class=headerlink href="#lattice-reduction-and-cell-candidates" title="Link to this heading">¶</a></h3> <p>Triples of candidate vectors are combined to form candidate bases <span class="math notranslate nohighlight">\((\mathbf{A},\mathbf{B},\mathbf{C})\)</span>, each reduced to its <strong>Niggli-reduced cell</strong> (Gruber-vector reduction) before comparison, and filtered by allowed length and angle ranges. Two passes are run: a standard pass forms shortest-vector triples from the ~30 strongest filtered directions; if the best cell then indexes fewer than half the spots, a <strong>widened fallback</strong> anchors the two shortest axes and lets the third range over up to ~60 candidate vectors (deduplicated by Niggli cell), catching large, elongated or superstructure cells the first pass misses.</p> </section> <section id=robust-refinement-and-best-cell-selection > <h3 id=robust-refinement-and-best-cell-selection >5.4 Robust refinement and best-cell selection<a class=headerlink href="#robust-refinement-and-best-cell-selection" title="Link to this heading">¶</a></h3> <p>Candidate bases are refined against observed spots using an iterative inlier‑focused least‑squares procedure (trimmed/contracting threshold). Candidates are then ranked:</p> <ol class="arabic simple"> <li><p>more indexed spots wins — <strong>unless</strong> two candidates index within ~10 % of each other, in which case</p> <li><p>the <strong>smaller-volume</strong> cell is preferred (when the volumes differ by more than ~5 %), avoiding a doubled supercell, then</p> <li><p>the smaller refinement score, then the spot count again.</p> </ol> <p>Selection is <strong>not limited to a single lattice</strong>: after the best cell is accepted, further lattices are added as separate crystals provided fewer than ~40 % of their indexed spots overlap an already-accepted lattice (up to two extra by default), so split or multi-lattice crystals are indexed rather than discarded.</p> <p>An optional reference unit cell (if supplied) restricts acceptance to cells within a relative distance tolerance in edge lengths (permutation-invariant).</p> </section> </section> <hr class=docutils /> <section id=bravais-lattice-centering-inference-lattice-search > <h2 id=bravais-lattice-centering-inference-lattice-search >6. Bravais lattice / centering inference (“lattice search”)<a class=headerlink href="#bravais-lattice-centering-inference-lattice-search" title="Link to this heading">¶</a></h2> <p>If the space group is supplied by the user, its lattice constraints are assumed for refinement and subsequent processing.</p> <p>If not, Jungfraujoch attempts to infer the most plausible Bravais lattice type from the metric tensor after Niggli reduction:</p> <ol class="arabic simple"> <li><p><strong>Niggli reduction</strong> is performed to obtain a reduced cell in <span class="math notranslate nohighlight">\(G^6\)</span> representation (Gruber vector).</p> <li><p>The reduced cell is compared against a list of Niggli classes corresponding to Bravais lattices and centerings.</p> <li><p>The highest-symmetry class that matches within tolerances is selected (relative metric tolerance and angular tolerance).</p> </ol> <p>The output includes:</p> <ul class=simple > <li><p>a conventional cell,</p> <li><p>crystal system (triclinic, monoclinic, …),</p> <li><p>centering symbol (one of <span class="math notranslate nohighlight">\(P, C, I, F, R\)</span>; the <span class="math notranslate nohighlight">\(A/B\)</span> variants are not emitted here — they are handled only later as prediction absences, §8.4).</p> </ul> <p>This stage provides centering information used for systematic absences in prediction (§8.4) and for reporting.</p> <p><strong>Note.</strong> In ambiguous or special cases, forcing space group to <span class="math notranslate nohighlight">\(P1\)</span> (no symmetry assumptions) is recommended.</p> </section> <hr class=docutils /> <section id=geometry-and-lattice-refinement > <h2 id=geometry-and-lattice-refinement >7. Geometry and lattice refinement<a class=headerlink href="#geometry-and-lattice-refinement" title="Link to this heading">¶</a></h2> <p>Refinement adjusts experimental geometry and crystal parameters to minimize discrepancies between observed spot reciprocal vectors and those predicted by a lattice model with integer indices.</p> <section id=parameterization > <h3 id=parameterization >7.1 Parameterization<a class=headerlink href="#parameterization" title="Link to this heading">¶</a></h3> <p>The refinement jointly optimizes, depending on mode and constraints:</p> <ul class=simple > <li><p>beam center <span class="math notranslate nohighlight">\((x_\mathrm{beam}, y_\mathrm{beam})\)</span>,</p> <li><p>detector distance <span class="math notranslate nohighlight">\(D\)</span>,</p> <li><p>detector tilt angles (two-angle model; third rotation often held at 0),</p> <li><p>rotation axis direction (for rotation datasets),</p> <li><p>crystal orientation (a global rotation),</p> <li><p>unit-cell parameters, with constraints determined by inferred crystal system.</p> </ul> <p>By default only the beam center, unit cell and crystal orientation are refined; the detector distance, tilt angles and rotation-axis direction are held fixed unless explicitly enabled. A lighter <strong>orientation-only</strong> mode refines just the crystal orientation (with a weak small-rotation prior on the poorly-determined out-of-plane component), for stills whose geometry is already trusted.</p> <p>For higher symmetries, constraints are enforced, e.g.</p> <ul class=simple > <li><p>cubic: <span class="math notranslate nohighlight">\(a=b=c,\ \alpha=\beta=\gamma=90^\circ\)</span>,</p> <li><p>tetragonal: <span class="math notranslate nohighlight">\(a=b\)</span>,</p> <li><p>hexagonal: <span class="math notranslate nohighlight">\(a=b,\ \gamma=120^\circ\)</span>,</p> <li><p>monoclinic (unique axis <span class="math notranslate nohighlight">\(b\)</span>): <span class="math notranslate nohighlight">\(\alpha=\gamma=90^\circ\)</span>, <span class="math notranslate nohighlight">\(\beta\)</span> refined.</p> </ul> </section> <section id=residuals-and-objective > <h3 id=residuals-and-objective >7.2 Residuals and objective<a class=headerlink href="#residuals-and-objective" title="Link to this heading">¶</a></h3> <p>For each indexed spot assigned integer <span class="math notranslate nohighlight">\((h,k,l)\)</span>, compute:</p> <ul class=simple > <li><p>observed reciprocal vector <span class="math notranslate nohighlight">\(\mathbf{s}_\mathrm{obs}\)</span> from its detector position and current geometry,</p> <li><p>predicted reciprocal vector <span class="math notranslate nohighlight">\(\mathbf{s}_\mathrm{pred}(h,k,l;\ \text{lattice params})\)</span>.</p> </ul> <p>Residual is: <span class="math notranslate nohighlight">\( \mathbf{r} = \mathbf{s}_\mathrm{obs} - \mathbf{s}_\mathrm{pred}. \)</span></p> <p>A non-linear least squares solver minimizes <span class="math notranslate nohighlight">\(\sum \|\mathbf{r}\|^2\)</span> over all selected inlier spots.</p> </section> <section id=rotation-datasets-bringing-observations-to-a-common-reference-frame > <h3 id=rotation-datasets-bringing-observations-to-a-common-reference-frame >7.3 Rotation datasets: bringing observations to a common reference frame<a class=headerlink href="#rotation-datasets-bringing-observations-to-a-common-reference-frame" title="Link to this heading">¶</a></h3> <p>For oscillation/rotation data, each image corresponds to a rotation angle <span class="math notranslate nohighlight">\(\phi\)</span> about an axis <span class="math notranslate nohighlight">\(\mathbf{m}_2\)</span>. Observed reciprocal vectors are rotated “back to start” so that all images are refined in a single reference crystal frame: <span class="math notranslate nohighlight">\( \mathbf{s}_\mathrm{obs,ref} = R(\phi)\,\mathbf{s}_\mathrm{obs}, \)</span> with <span class="math notranslate nohighlight">\(R(\phi)\)</span> constructed from the axis-angle representation of the goniometer model. The angle <span class="math notranslate nohighlight">\(\phi\)</span> is taken at the centre of each frame’s oscillation (the frame angle plus half the oscillation width).</p> </section> <section id=multi-stage-tightening-of-inlier-tolerance > <h3 id=multi-stage-tightening-of-inlier-tolerance >7.4 Multi-stage tightening of inlier tolerance<a class=headerlink href="#multi-stage-tightening-of-inlier-tolerance" title="Link to this heading">¶</a></h3> <p>Refinement is performed in stages with decreasing acceptance tolerance for including reflections (three stages, indexing tolerance <span class="math notranslate nohighlight">\(0.3\to0.2\to0.1\)</span>), which stabilizes convergence when starting from imperfect indexing and approximate geometry.</p> </section> </section> <hr class=docutils /> <section id=reflection-prediction > <h2 id=reflection-prediction >8. Reflection prediction<a class=headerlink href="#reflection-prediction" title="Link to this heading">¶</a></h2> <p>Jungfraujoch predicts reflection positions for integration by enumerating Miller indices within a resolution cutoff and accepting those that satisfy a diffraction condition model.</p> <section id=enumerating-reciprocal-lattice-points > <h3 id=enumerating-reciprocal-lattice-points >8.1 Enumerating reciprocal lattice points<a class=headerlink href="#enumerating-reciprocal-lattice-points" title="Link to this heading">¶</a></h3> <p>For a maximum resolution <span class="math notranslate nohighlight">\(d_\mathrm{min}\)</span>, accept <span class="math notranslate nohighlight">\((h,k,l)\)</span> such that: <span class="math notranslate nohighlight">\( \lVert \mathbf{p}(h,k,l)\rVert^2 = \lVert h\mathbf{a}^* + k\mathbf{b}^* + l\mathbf{c}^*\rVert^2 \le \left(\frac{1}{d_\mathrm{min}}\right)^2. \)</span></p> </section> <section id=still-prediction-excitation-error-cutoff > <h3 id=still-prediction-excitation-error-cutoff >8.2 Still prediction (excitation-error cutoff)<a class=headerlink href="#still-prediction-excitation-error-cutoff" title="Link to this heading">¶</a></h3> <p>For still images, the diffracting condition is approximated by an excitation-error cutoff: <span class="math notranslate nohighlight">\( \left|\Delta_\mathrm{Ewald}(\mathbf{p})\right| \le \Delta_\mathrm{cut}. \)</span> Accepted reflections are projected to the detector by intersecting the diffracted direction <span class="math notranslate nohighlight">\(\mathbf{S}=\mathbf{S}_0+\mathbf{p}\)</span> with the detector plane, using the current geometry.</p> <p>When the beam has a finite energy bandwidth, this window is <strong>broadened radially per reflection</strong>: the cutoff is combined in quadrature with a bandwidth smear, <span class="math notranslate nohighlight">\(\sqrt{\Delta_\mathrm{cut}^2 + (3\,\sigma_\mathrm{bw})^2}\)</span>, where <span class="math notranslate nohighlight">\(\sigma_\mathrm{bw}\propto|p_z|\)</span> (the reciprocal-space depth along the beam, growing as <span class="math notranslate nohighlight">\(\sim 1/d^2\)</span>). This keeps high-resolution reflections — smeared by the bandwidth into radial streaks — from being clipped. The same <span class="math notranslate nohighlight">\(\sigma_\mathrm{bw}\)</span> is deconvolved from the measured profile radius (§11.1), so it is not double-counted.</p> </section> <section id=rotation-prediction-laue-equation-partiality-model > <h3 id=rotation-prediction-laue-equation-partiality-model >8.3 Rotation prediction (Laue equation + partiality model)<a class=headerlink href="#rotation-prediction-laue-equation-partiality-model" title="Link to this heading">¶</a></h3> <p>For rotation/oscillation datasets, Jungfraujoch solves for rotation angles <span class="math notranslate nohighlight">\(\phi\)</span> where the rotated reciprocal lattice point satisfies the Ewald-sphere condition. In an XDS-like notation, define:</p> <ul class=simple > <li><p>rotation axis unit vector <span class="math notranslate nohighlight">\(\mathbf{m}_2\)</span>,</p> <li><p><span class="math notranslate nohighlight">\(\mathbf{S}_0\)</span> incident vector,</p> <li><p><span class="math notranslate nohighlight">\(\mathbf{S}(\phi)=\mathbf{S}_0+\mathbf{p}(\phi)\)</span>.</p> </ul> <p>A key quantity is: <span class="math notranslate nohighlight">\( \zeta = \left|\mathbf{m}_2\cdot \mathbf{e}_1\right|,\quad \mathbf{e}_1 = \frac{\mathbf{S}\times \mathbf{S}_0}{\lVert \mathbf{S}\times \mathbf{S}_0\rVert}, \)</span> which also appears in XDS as the Lorentz component linked to the rotation axis.</p> <p>A Gaussian mosaicity model yields a partiality fraction over an oscillation width <span class="math notranslate nohighlight">\(\Delta\phi\)</span>:</p> <p><span class="math notranslate nohighlight">\( P(\phi;\sigma_M,\zeta,\Delta\phi) = \frac{1}{2}\left[\mathrm{erf}\!\left(\frac{\phi+\Delta\phi/2}{\sqrt{2}\,\sigma_M/\zeta}\right) - \mathrm{erf}\!\left(\frac{\phi-\Delta\phi/2}{\sqrt{2}\,\sigma_M/\zeta}\right)\right], \)</span></p> <p>with mosaicity <span class="math notranslate nohighlight">\(\sigma_M\)</span> in radians.</p> <p>Reflections are predicted if they meet minimum <span class="math notranslate nohighlight">\(\zeta\)</span> and mosaicity-window criteria, and their predicted detector coordinates fall on the active detector area.</p> </section> <section id=systematic-absences-centering > <h3 id=systematic-absences-centering >8.4 Systematic absences (centering)<a class=headerlink href="#systematic-absences-centering" title="Link to this heading">¶</a></h3> <p>Systematic absences are applied at least at the centering level (prior to full space-group symmetry). For centering symbol <span class="math notranslate nohighlight">\(C\)</span>:</p> <ul class=simple > <li><p><span class="math notranslate nohighlight">\(I\)</span>: absent if <span class="math notranslate nohighlight">\(h+k+l\)</span> odd,</p> <li><p><span class="math notranslate nohighlight">\(A\)</span>: absent if <span class="math notranslate nohighlight">\(k+l\)</span> odd,</p> <li><p><span class="math notranslate nohighlight">\(B\)</span>: absent if <span class="math notranslate nohighlight">\(h+l\)</span> odd,</p> <li><p><span class="math notranslate nohighlight">\(C\)</span>: absent if <span class="math notranslate nohighlight">\(h+k\)</span> odd,</p> <li><p><span class="math notranslate nohighlight">\(F\)</span>: absent if any of <span class="math notranslate nohighlight">\(h+k, h+l, k+l\)</span> is odd,</p> <li><p><span class="math notranslate nohighlight">\(R\)</span>: absent if <span class="math notranslate nohighlight">\((-h+k+l)\bmod 3 \ne 0\)</span>,</p> <li><p><span class="math notranslate nohighlight">\(P\)</span>: no centering absences.</p> </ul> </section> </section> <hr class=docutils /> <section id=d-bragg-integration-profile-fitting-over-a-three-ring-roi > <h2 id=d-bragg-integration-profile-fitting-over-a-three-ring-roi >9. 2D Bragg integration (profile fitting over a three-ring ROI)<a class=headerlink href="#d-bragg-integration-profile-fitting-over-a-three-ring-roi" title="Link to this heading">¶</a></h2> <p>Jungfraujoch integrates each predicted reflection in the detector plane over a CrystFEL-inspired “three-ring” region of interest (§9.1). The <strong>default</strong> extraction is <strong>profile fitting</strong> (Kabsch; §9.3), which weights each pixel by a fitted spot profile and so recovers weak reflections far better than plain summation; plain box summation (§9.2) is retained as the seed for the profile and as a fallback. Both methods share the same ROI and background model, and emit the same per-reflection <span class="math notranslate nohighlight">\((I,\sigma,\text{partiality},d)\)</span>, so scaling, the rotation combine (§10.6) and merging consume either unchanged.</p> <section id=regions-of-interest > <h3 id=regions-of-interest >9.1 Regions of interest<a class=headerlink href="#regions-of-interest" title="Link to this heading">¶</a></h3> <p>For each predicted reflection at <span class="math notranslate nohighlight">\((x_p,y_p)\)</span>, define three radii:</p> <ul class=simple > <li><p><span class="math notranslate nohighlight">\(r_1\)</span>: inner signal radius,</p> <li><p><span class="math notranslate nohighlight">\(r_2\)</span>: inner background radius,</p> <li><p><span class="math notranslate nohighlight">\(r_3\)</span>: outer background radius.</p> </ul> <p>Pixels are classified by their squared distance <span class="math notranslate nohighlight">\(r^2=(x-x_p)^2+(y-y_p)^2\)</span>:</p> <ul class=simple > <li><p><strong>signal region:</strong> <span class="math notranslate nohighlight">\(r^2 < r_1^2\)</span>,</p> <li><p><strong>background annulus:</strong> <span class="math notranslate nohighlight">\(r_2^2 \le r^2 < r_3^2\)</span>.</p> </ul> <p>Invalid pixels (masked/bad/saturated) are excluded from both sums. In addition, pixels lying inside the signal disk (<span class="math notranslate nohighlight">\(r<r_2\)</span>) of any <em>other</em> predicted reflection are removed from this reflection’s background annulus, so a neighbouring spot cannot leak into the background estimate.</p> </section> <section id=box-summation-seed-and-fallback > <h3 id=box-summation-seed-and-fallback >9.2 Box summation (seed and fallback)<a class=headerlink href="#box-summation-seed-and-fallback" title="Link to this heading">¶</a></h3> <p>Let:</p> <ul class=simple > <li><p><span class="math notranslate nohighlight">\(S = \sum I(x,y)\)</span> over signal pixels,</p> <li><p><span class="math notranslate nohighlight">\(n_S\)</span> = number of valid signal pixels,</p> <li><p><span class="math notranslate nohighlight">\(B = \sum I(x,y)\)</span> over background pixels,</p> <li><p><span class="math notranslate nohighlight">\(n_B\)</span> = number of valid background pixels.</p> </ul> <p>Background per pixel and integrated intensity: <span class="math notranslate nohighlight">\( \hat{b} = \frac{B}{n_B},\qquad \hat{I} = S - n_S \hat{b}, \)</span> with a Poisson-like uncertainty <span class="math notranslate nohighlight">\(\sigma(\hat{I})=\max\!\big(1,\ r_\sigma\hat{I},\ \sqrt{S}\big)\)</span>, i.e. <span class="math notranslate nohighlight">\(\sqrt{S}\)</span> floored both at 1 and at a small fraction <span class="math notranslate nohighlight">\(r_\sigma\)</span> of the intensity. A reflection is accepted as “observed” only if all signal pixels were valid and <span class="math notranslate nohighlight">\(n_B\)</span> exceeds a minimum. This box sum is the classical estimator; it is used directly with <code class="docutils literal notranslate"><span class=pre >--integrator</span> <span class=pre >boxsum</span></code>, and otherwise seeds the profile fit below.</p> <p>For the <strong>profile-fit path on broadband (still) data</strong>, the background mean is additionally computed with a single high-outlier reject (drop ring pixels above <span class="math notranslate nohighlight">\(\hat{b}+3\sqrt{\hat{b}}\)</span>, then recompute): a bandwidth-streaked high-resolution spot or a close neighbour can leak into the ring and bias the mean high, over-subtracting and driving weak high-resolution intensities negative. A clean Poisson background is essentially unchanged by the cut. The reject is <strong>not</strong> applied to plain box summation (<code class="docutils literal notranslate"><span class=pre >--integrator</span> <span class=pre >boxsum</span></code>) or to monochromatic/rotation data.</p> </section> <section id=profile-fitted-extraction-default > <h3 id=profile-fitted-extraction-default >9.3 Profile-fitted extraction (default)<a class=headerlink href="#profile-fitted-extraction-default" title="Link to this heading">¶</a></h3> <p>A fixed signal disk captures a <em>width-dependent</em> fraction of each spot, which puts a multiplicative floor on the per-observation precision of strong reflections and weights weak reflections poorly. Profile fitting removes this by extracting each intensity against a fitted spot shape, without needing reference intensities. Per frame:</p> <ol class=arabic > <li><p><strong>Seed.</strong> Box-sum every reflection (§9.2) to get a rough intensity and observed centroid, and select strong spots (significance <span class="math notranslate nohighlight">\(\ge 5\)</span>).</p> <li><p><strong>Build the profile.</strong> For <code class="docutils literal notranslate"><span class=pre >gaussian</span></code> (the default) the width is taken <strong>per resolution shell</strong> from the measured second moment of the strong spots (shell-dependent because spot size grows with resolution); the intrinsic spot is essentially round in the detector plane (per-detector-region and crystal-anisotropy profiles were evaluated and add nothing — the real crystal anisotropy lives in the discarded rocking direction). For <code class="docutils literal notranslate"><span class=pre >empirical</span></code> the profile is instead the averaged, centroid-aligned, background-subtracted pixel grid of the shell’s strong spots. Either way the profile is then <strong>rebuilt for each reflection</strong>, centred on its <strong>sub-pixel predicted position</strong> (the noise-free geometric centre, not the observed centroid) and, where needed, <strong>elongated only along the radial direction</strong> (away from the beam centre) — because two effects stretch a spot radially but not tangentially:</p> <ul class=simple > <li><p>a finite energy <strong>bandwidth</strong> smears each spot by <span class="math notranslate nohighlight">\(\sigma_\mathrm{bw}=\text{bandwidth}\cdot R_\mathrm{px}\)</span> (<span class="math notranslate nohighlight">\(R_\mathrm{px}\)</span> = distance from the beam centre, large at high resolution), and</p> <li><p>sensor <strong>parallax</strong> — the depth over which a photon converts in a thick Si/CdTe sensor — adds a term <span class="math notranslate nohighlight">\(\propto\tan^2(2\theta)\)</span> (material- and energy-dependent), plus, on the monochromatic path, a small fixed weak-spot capture term.</p> </ul> <p>These combine as <span class="math notranslate nohighlight">\(\sigma^2_\mathrm{radial}=\sigma^2_\mathrm{intrinsic}+\sigma_\mathrm{bw}^2+c_\mathrm{par}\tan^2(2\theta)\)</span> (tangential unchanged), on a grid grown to hold the streak — capturing it without the tangential background an isotropic widening would add.</p> <li><p><strong>Fit (Kabsch).</strong> With profile <span class="math notranslate nohighlight">\(P\)</span>, background <span class="math notranslate nohighlight">\(B\)</span> and the shell variance model, the intensity and its uncertainty are <span class="math notranslate nohighlight">\( I = \frac{\sum P\,(c-B)/v}{\sum P^2/v},\qquad \sigma = \sqrt{\frac{1}{\sum P^2/v}},\qquad v = B + \max(I,0)\,P, \)</span> where <span class="math notranslate nohighlight">\(c\)</span> is the pixel value and the de-biased variance <span class="math notranslate nohighlight">\(v\)</span> (background plus model signal, rather than the down-fluctuating observed count) is iterated (a few passes). As a guard, if the profile intensity runs away from the box-sum seed (by more than ~10 box-sum <span class="math notranslate nohighlight">\(\sigma\)</span>) it falls back to the seed, and the variance floors the background at <span class="math notranslate nohighlight">\(1/12\)</span> (the integer-binning pixel-variance floor). The rotation/excitation partiality is carried exactly as in the box-sum path.</p> </ol> <p>The integrator is selected by <code class="docutils literal notranslate"><span class=pre >--integrator</span> <span class=pre >boxsum|gaussian|empirical</span></code> (default <code class="docutils literal notranslate"><span class=pre >gaussian</span></code>).</p> </section> <section id=lorentzpolarization-factor-handling > <h3 id=lorentzpolarization-factor-handling >9.4 Lorentz–polarization factor handling<a class=headerlink href="#lorentzpolarization-factor-handling" title="Link to this heading">¶</a></h3> <p>For integrated reflections, polarization correction can be applied as a multiplicative correction to the reflection scale via the geometry-based polarization term (§2.2). A Lorentz-like factor is carried as <code class="docutils literal notranslate"><span class=pre >rlp</span></code> in predictions, and used during scaling/merging (§10).</p> </section> </section> <hr class=docutils /> <section id=scaling-and-merging > <h2 id=scaling-and-merging >10. Scaling and merging<a class=headerlink href="#scaling-and-merging" title="Link to this heading">¶</a></h2> <p>After per-image integration, Jungfraujoch scales observations and merges them into unique reflections. The design is intentionally compatible with XDS/XSCALE concepts, and handles both still and rotation data.</p> <section id=observation-model > <h3 id=observation-model >10.1 Observation model<a class=headerlink href="#observation-model" title="Link to this heading">¶</a></h3> <p>For an observation <span class="math notranslate nohighlight">\(j\)</span> of a unique reflection <span class="math notranslate nohighlight">\(h\)</span> on image (or image group) <span class="math notranslate nohighlight">\(i\)</span>, the predicted measured intensity is modeled as: <span class="math notranslate nohighlight">\( I_{ij} \approx G_i \, L_{ij}\, P_{ij}\, I_h, \)</span> where:</p> <ul class=simple > <li><p><span class="math notranslate nohighlight">\(G_i\)</span> is the image scale factor,</p> <li><p><span class="math notranslate nohighlight">\(L_{ij}\)</span> is a Lorentz-like / geometry factor (stored as <code class="docutils literal notranslate"><span class=pre >rlp</span></code> or derived),</p> <li><p><span class="math notranslate nohighlight">\(P_{ij}\)</span> is a partiality term (model-dependent),</p> <li><p><span class="math notranslate nohighlight">\(I_h\)</span> is the merged (true) intensity parameter for that unique reflection.</p> </ul> <p>A least-squares objective is minimized: <span class="math notranslate nohighlight">\( \sum_{ij} \left(\frac{I_{ij}^{\mathrm{pred}} - I_{ij}^{\mathrm{obs}}}{\sigma_{ij}}\right)^2 \)</span> solved by robust (Cauchy) weighted least squares, with optional post-fit smoothing of the per-frame scales for rotation series (§10.3).</p> </section> <section id=partiality-models > <h3 id=partiality-models >10.2 Partiality models<a class=headerlink href="#partiality-models" title="Link to this heading">¶</a></h3> <p>The partiality applied is fixed by the data type and scaling stage, not chosen from a user menu:</p> <ol class="arabic simple"> <li><p><strong>Rotation partiality</strong> (XDS-like; see §8.3), used for the per-frame scaling of rotation partials: <span class="math notranslate nohighlight">\( P_{ij} = \frac{1}{2}\left[ \mathrm{erf}\!\left(\frac{\Delta\phi_{ij}+\Delta\phi/2}{\sqrt{2}\,\sigma_{M,i}/\zeta_{ij}}\right) - \mathrm{erf}\!\left(\frac{\Delta\phi_{ij}-\Delta\phi/2}{\sqrt{2}\,\sigma_{M,i}/\zeta_{ij}}\right) \right]. \)</span> The mosaicity <span class="math notranslate nohighlight">\(\sigma_{M,i}\)</span> is <strong>measured once per image at indexing</strong> (MLE, §11.2) and held fixed during scaling — only smoothed in frame order (§10.3), never re-refined (it is degenerate with the scale <span class="math notranslate nohighlight">\(G\)</span>; §11.2).</p> <li><p><strong>Unity</strong> (<span class="math notranslate nohighlight">\(P_{ij}=1\)</span>): used for the scale-on-fulls refit (§10.6), where each observation is already a complete reflection.</p> <li><p><strong>Fixed</strong>: use the per-reflection partiality carried from prediction. Still/serial images are predicted with <span class="math notranslate nohighlight">\(P=1\)</span>, so their scaling is effectively unity/fixed — there is no excitation-error still-partiality model.</p> </ol> <p>Reflections below a minimum partiality can be rejected from merging to avoid unstable corrections.</p> </section> <section id=smoothing-of-per-frame-scales > <h3 id=smoothing-of-per-frame-scales >10.3 Smoothing of per-frame scales<a class=headerlink href="#smoothing-of-per-frame-scales" title="Link to this heading">¶</a></h3> <p>The per-frame scales <span class="math notranslate nohighlight">\(G_i\)</span> are fit by robust (Cauchy) inverse-variance-weighted ratios; there is no explicit <span class="math notranslate nohighlight">\(G\approx1\)</span> prior. For rotation datasets, optional smoothing enforces the expectation that scale and mosaicity vary slowly across a sweep: <strong>after</strong> the per-frame fit, <span class="math notranslate nohighlight">\(\log G_i\)</span> (and the mosaicity) are replaced by a centred <strong>moving average</strong> over a window spanning a configurable rotation range (XDS DELPHI-like; <code class="docutils literal notranslate"><span class=pre >--smooth-g</span></code>, default 5° for rot3d, off otherwise). It is a post-fit smoothing pass, not a curvature penalty inside the least-squares objective.</p> </section> <section id=merging-estimator > <h3 id=merging-estimator >10.4 Merging estimator<a class=headerlink href="#merging-estimator" title="Link to this heading">¶</a></h3> <p>After refinement, corrected observations are formed: <span class="math notranslate nohighlight">\( I^{\mathrm{corr}}_{ij} = \frac{I^{\mathrm{obs}}_{ij}}{G_i L_{ij} P_{ij}},\qquad \sigma^{\mathrm{corr}}_{ij} = \frac{\sigma^{\mathrm{obs}}_{ij}}{G_i L_{ij} P_{ij}}. \)</span></p> <p>Unique intensities are merged by inverse-variance weighted mean: <span class="math notranslate nohighlight">\( I_h = \frac{\sum_j w_j I^{\mathrm{corr}}_{ij}}{\sum_j w_j},\qquad w_j = \frac{1}{(\sigma^{\mathrm{corr}}_{ij})^2}. \)</span></p> <p>An internal-consistency term can inflate uncertainties when multiple observations are present, in the spirit of XSCALE.</p> </section> <section id=merging-statistics > <h3 id=merging-statistics >10.5 Merging statistics<a class=headerlink href="#merging-statistics" title="Link to this heading">¶</a></h3> <p>Per-shell and overall merging statistics are computed on corrected intensities, including:</p> <ul class=simple > <li><p>number of observations and of unique reflections, and multiplicity,</p> <li><p>mean <span class="math notranslate nohighlight">\(I/\sigma(I)\)</span>,</p> <li><p><span class="math notranslate nohighlight">\(R_\mathrm{meas}\)</span> (the redundancy-independent Diederichs–Karplus form) from within‑HKL deviations,</p> <li><p><span class="math notranslate nohighlight">\(\mathrm{CC}_{1/2}\)</span> (half-set correlation) and, when a reference dataset is supplied, <span class="math notranslate nohighlight">\(\mathrm{CC}_\mathrm{ref}\)</span>,</p> <li><p>completeness against the enumerated reflections for the cell and symmetry.</p> </ul> <p>The error model is refined as <span class="math notranslate nohighlight">\(\sigma_\mathrm{corr}^2 = a\,\sigma^2 + (b\,\langle I\rangle)^2\)</span> with a systematic floor <span class="math notranslate nohighlight">\(\sigma\ge b|I|\)</span>; the asymptotic signal-to-noise <span class="math notranslate nohighlight">\(\mathrm{ISa}=1/b\)</span> is reported and written to the output files.</p> </section> <section id=rotation-datasets-combining-partials-into-fulls-3d-integration > <h3 id=rotation-datasets-combining-partials-into-fulls-3d-integration >10.6 Rotation datasets: combining partials into fulls (3D integration)<a class=headerlink href="#rotation-datasets-combining-partials-into-fulls-3d-integration" title="Link to this heading">¶</a></h3> <p>In a rotation scan a reflection is recorded as a series of <em>partials</em> spread across the frames its rocking curve crosses. Merging those partials directly would force the merge error model to absorb the rocking-curve slicing as if it were measurement noise, capping the achievable <span class="math notranslate nohighlight">\(I/\sigma\)</span>. For rotation data Jungfraujoch instead <strong>combines</strong> each reflection’s partials into a single <em>full</em> intensity first, then scales and merges the fulls — a 3D integration over the rocking curve.</p> <p>The combine groups each reflection’s partials into rocking events (contiguous runs of frames) and reduces each event to one full:</p> <ul class=simple > <li><p><strong>De-biased weighted sum.</strong> Partials are combined by inverse-variance weighting, where each partial’s variance is its background-noise component plus the <em>model</em> signal shared across the event (Kabsch profile-fit form). Using the shared model signal rather than the individual down-fluctuating intensity stops weak partials from being over-weighted, which would otherwise inflate the merged error model. The weights depend on the full, so the estimate is iterated.</p> <li><p><strong>Captured fraction.</strong> The partiality summed over the event, <span class="math notranslate nohighlight">\(f=\min(1,\sum_j p_j)\)</span>, measures how completely the rocking curve was sampled. A full whose curve was captured below a threshold (<code class="docutils literal notranslate"><span class=pre >--min-captured-fraction</span></code>, default 0.7 for rotation) is dropped — an event seen over only a small fraction of its curve is unreliable however many frames it spans. (The per-partial minimum-partiality cut of §10.2 still applies upstream, in the per-frame scaling.)</p> <li><p><strong>Capture-aware uncertainty.</strong> A full captured incompletely (<span class="math notranslate nohighlight">\(f<1\)</span>) is extrapolated and biased high. The unobserved fraction is charged as an extra systematic uncertainty, <span class="math notranslate nohighlight">\(\sigma^2 \leftarrow \sigma^2 + \big(c\,(1-f)\,I\big)^2\)</span>, so the merge down-weights these extrapolated fulls and the error model treats their scatter as expected. It is enabled by default for the rotation path.</p> </ul> <p>The fulls are then re-scaled in the XDS sense — a per-image scale refit directly on the complete reflections under the unity partiality model — and merged (§10.4). Because every merged observation is now a counting-statistics-limited full rather than a partiality-divided slice, the error model reaches a far higher asymptotic <span class="math notranslate nohighlight">\(I/\sigma\)</span>.</p> <p>After scale-fulls, two <strong>optional correction surfaces</strong> can be fitted on the combined fulls (rotation only, both <strong>off by default</strong>), each an alternating multiplicative refinement of the per-full scale against the merged reference:</p> <ul class=simple > <li><p><strong>Decay</strong> (<code class="docutils literal notranslate"><span class=pre >-B</span></code>). Radiation damage weakens later frames more at higher resolution — a resolution×time (Debye–Waller) systematic the resolution-flat per-image scale cannot capture. A single global relative-<span class="math notranslate nohighlight">\(B\)</span> rate is fitted, <span class="math notranslate nohighlight">\(\ln(I_\mathrm{ref}/I_\mathrm{obs}) = 2\,(\mathrm{d}B/\mathrm{d}n)\,(n-\bar n)\,s^2\)</span> (frame <span class="math notranslate nohighlight">\(n\)</span>, <span class="math notranslate nohighlight">\(s^2 = 1/4d^2\)</span>), and folded into the scale. It engages only when the total relative-<span class="math notranslate nohighlight">\(B\)</span> over the run exceeds a physical floor (2 Ų); below that the decay is negligible and “correcting” it only spreads symmetry equivalents (which sit at the same <span class="math notranslate nohighlight">\(s^2\)</span> but different frames).</p> <li><p><strong>Absorption</strong> (<code class="docutils literal notranslate"><span class=pre >--absorption</span></code>). A smooth multiplicative factor over the diffracted-beam direction expressed in the goniometer (crystal) frame: each full’s predicted detector position gives the lab diffracted direction, de-rotated by the spindle so a fixed crystal-frame direction is sampled at many rotation angles and its grid cell is well-determined. Negligible at hard X-rays / thin crystals; it matters at low photon energy. Its gain is largest on model-based metrics — a smooth absorption error largely <em>cancels</em> among symmetry mates (small effect on the error model / ISa) but still biases the intensities from their true values (a measurable <span class="math notranslate nohighlight">\(R_\mathrm{free}\)</span> improvement).</p> </ul> <p>Both surfaces are <strong>cross-validated</strong>: fitted on even-numbered frames and kept only if they improve the held-out odd-frame symmetry-equivalent agreement by a clear margin (and vice versa). A surface fitted to noise where its systematic is absent therefore does not generalize and is discarded — an opt-in correction never adds scatter.</p> </section> </section> <hr class=docutils /> <section id=mosaicity-and-profile-radius-monitoring > <h2 id=mosaicity-and-profile-radius-monitoring >11. Mosaicity and “profile radius” monitoring<a class=headerlink href="#mosaicity-and-profile-radius-monitoring" title="Link to this heading">¶</a></h2> <section id=profile-radius-intrinsic-excitation-error-width > <h3 id=profile-radius-intrinsic-excitation-error-width >11.1 Profile radius (intrinsic excitation-error width)<a class=headerlink href="#profile-radius-intrinsic-excitation-error-width" title="Link to this heading">¶</a></h3> <p>The “profile radius” is the intrinsic angular width of a reflection — crystal mosaicity plus beam divergence — estimated from the spread of <span class="math notranslate nohighlight">\(\Delta_\mathrm{Ewald}\)</span> over indexed spots, <span class="math notranslate nohighlight">\( R \approx \sqrt{\tfrac{1}{N}\sum_i \Delta_{\mathrm{Ewald},i}^2}. \)</span> When the beam has a finite energy bandwidth, that bandwidth smears each reflection radially by <span class="math notranslate nohighlight">\(\sigma_\mathrm{bw}\approx \mathrm{bandwidth}\cdot\lambda/2d^2\)</span> (largest at high resolution), which also broadens the measured <span class="math notranslate nohighlight">\(\Delta_\mathrm{Ewald}\)</span> spread. Since prediction re-applies the bandwidth term per reflection (§8.2), this contribution is deconvolved from the estimate — <span class="math notranslate nohighlight">\(R^2 = \langle\Delta_\mathrm{Ewald}^2\rangle - \langle\sigma_\mathrm{bw}^2\rangle\)</span> — so that <span class="math notranslate nohighlight">\(R\)</span> is the intrinsic width and bandwidth is not double-counted. Still predictions use an excitation-error cutoff proportional to <span class="math notranslate nohighlight">\(R\)</span>.</p> </section> <section id=mosaicity-from-rotation-data > <h3 id=mosaicity-from-rotation-data >11.2 Mosaicity from rotation data<a class=headerlink href="#mosaicity-from-rotation-data" title="Link to this heading">¶</a></h3> <p>For rotation data the mosaicity <span class="math notranslate nohighlight">\(\sigma_M\)</span> is estimated by maximum likelihood from the rocking offsets <span class="math notranslate nohighlight">\(\tau\)</span> of indexed spots, using the XDS reflection-fraction model <span class="math notranslate nohighlight">\(R(\tau;\sigma_M/\zeta)\)</span> (Kabsch 2010): each spot’s exact Bragg angle is located near its frame, <span class="math notranslate nohighlight">\(\zeta\)</span> (the rotation-axis Lorentz component) is computed, and <span class="math notranslate nohighlight">\(\sigma_M\)</span> is chosen to maximize <span class="math notranslate nohighlight">\(\sum_i \log R(\tau_i;\sigma_M/\zeta_i)\)</span>.</p> <p>The <span class="math notranslate nohighlight">\(\phi\)</span> search window for the Bragg angle is set <strong>wider than the oscillation</strong>, so that reflections recorded at large rocking offset are included. These tail reflections carry most of the information about the mosaic width; a window limited to the oscillation range would truncate the <span class="math notranslate nohighlight">\(\tau\)</span> distribution and bias <span class="math notranslate nohighlight">\(\sigma_M\)</span> low.</p> <p>The estimated mosaicity feeds the rotation prediction (how many frames each reflection spans, §8.3) and the rotation partiality (§10.2). It is <strong>held fixed during scaling</strong>: in the per-image scale fit the mosaicity is degenerate with the scale <span class="math notranslate nohighlight">\(G\)</span> (both rescale the predicted intensity), so refining it there is unstable. A correct mosaicity matters because it controls both how much of each rocking curve is captured and the partiality used to form fulls (§10.6); too small a value truncates the captured curve and over-peaks the partiality, degrading the combined fulls.</p> </section> </section> <hr class=docutils /> <section id=auxiliary-statistics-i-i-and-wilson-plot > <h2 id=auxiliary-statistics-i-i-and-wilson-plot >12. Auxiliary statistics: ⟨I/σ(I)⟩ and Wilson plot<a class=headerlink href="#auxiliary-statistics-i-i-and-wilson-plot" title="Link to this heading">¶</a></h2> <section id=per-shell-i-i > <h3 id=per-shell-i-i >12.1 Per-shell ⟨I/σ(I)⟩<a class=headerlink href="#per-shell-i-i" title="Link to this heading">¶</a></h3> <p>For monitoring integration quality, Jungfraujoch reports mean <span class="math notranslate nohighlight">\(\langle I/\sigma(I)\rangle\)</span> in a fixed number of resolution shells. Shelling is performed in <span class="math notranslate nohighlight">\(1/d^2\)</span> space (typical of crystallographic practice).</p> </section> <section id=wilson-plot-b-factor-proxy > <h3 id=wilson-plot-b-factor-proxy >12.2 Wilson plot (B-factor proxy)<a class=headerlink href="#wilson-plot-b-factor-proxy" title="Link to this heading">¶</a></h3> <p>A Wilson-type analysis is computed by binning intensities by resolution and fitting: <span class="math notranslate nohighlight">\( \langle I\rangle \propto \exp\!\left(-\frac{B}{2}\frac{1}{d^2}\right), \)</span> i.e. <span class="math notranslate nohighlight">\( \log \langle I\rangle = \mathrm{const} - \frac{B}{2}\left(\frac{1}{d^2}\right). \)</span> A linear regression of <span class="math notranslate nohighlight">\(\log\langle I\rangle\)</span> vs <span class="math notranslate nohighlight">\(1/d^2\)</span> provides an estimate of <span class="math notranslate nohighlight">\(B\)</span>, subject to basic quality checks (e.g. <span class="math notranslate nohighlight">\(R^2\)</span> threshold).</p> </section> </section> <hr class=docutils /> <section id=practical-notes-and-limitations > <h2 id=practical-notes-and-limitations >13. Practical notes and limitations<a class=headerlink href="#practical-notes-and-limitations" title="Link to this heading">¶</a></h2> <ul class=simple > <li><p><strong>Bragg integration is profile-fitted by default</strong> (per-shell Gaussian profile, Kabsch extraction; §9.3), with plain box summation available as a fallback (<code class="docutils literal notranslate"><span class=pre >--integrator</span> <span class=pre >boxsum</span></code>). The profiles are built per frame from that frame’s strong spots, which suits fast-feedback and serial/streaming use; a profile shared across many frames (as in full offline workflows) is not currently formed.</p> <li><p><strong>Space-group symmetry</strong> beyond centering absences is not necessarily enforced during prediction/integration unless the space group is supplied and used downstream.</p> <li><p><strong>Resolution masking and ice rings</strong> are controllable; including ice-ring spots in indexing can improve robustness for some samples but may bias refinement in others.</p> <li><p><strong>Rotation vs still modes</strong> differ substantially in prediction and scaling: partiality is angle-driven in rotation data, while stills are predicted (within an excitation-error window) and scaled with unit partiality.</p> <li><p><strong>Space-group determination.</strong> When no space group is supplied, a POINTLESS-like search scores Laue-group symmetry (CC of <span class="math notranslate nohighlight">\(I(h)\)</span> vs <span class="math notranslate nohighlight">\(I(Rh)\)</span> plus merge self-consistency) and detects screw/centering absences from the <span class="math notranslate nohighlight">\(P1\)</span>-merged intensities. The self-consistency test is calibrated so a merohedral twin — whose twin law forces non-equivalent reflections together and inflates the merged <span class="math notranslate nohighlight">\(\chi^2\)</span> — stays in its true lower symmetry rather than being over-promoted to the holohedral group.</p> <li><p><strong>Twinning check.</strong> A Padilla–Yeates <span class="math notranslate nohighlight">\(L\)</span>-test (<span class="math notranslate nohighlight">\(\langle|L|\rangle\)</span>, <span class="math notranslate nohighlight">\(\langle L^2\rangle\)</span>) and the second moment <span class="math notranslate nohighlight">\(\langle I^2\rangle/\langle I\rangle^2\)</span> (taken per resolution shell with noise-only shells skipped and Wilson outliers rejected, so a single strong reflection in a collapsed-mean shell cannot skew it) are written to the merged mmCIF as a twinning diagnostic. Twinning is only flagged in Laue classes where a merohedral twin law can exist; the holohedral high-symmetry classes (<span class="math notranslate nohighlight">\(4/mmm\)</span>, <span class="math notranslate nohighlight">\(6/mmm\)</span>, <span class="math notranslate nohighlight">\(m\bar{3}m\)</span>, and <span class="math notranslate nohighlight">\(\bar{3}m\)</span> on a rhombohedral lattice) are exempt, so a low <span class="math notranslate nohighlight">\(\langle|L|\rangle\)</span> there is reported as a statistical artefact rather than twinning.</p> <li><p><strong>Outlier rejection.</strong> Merging applies an optional per-observation median-based <span class="math notranslate nohighlight">\(N\sigma\)</span> cut (default 6σ for <code class="docutils literal notranslate"><span class=pre >rot3d</span></code>) and an optional per-crystal <span class="math notranslate nohighlight">\(\Delta\mathrm{CC}_{1/2}\)</span> image rejection (<code class="docutils literal notranslate"><span class=pre >--reject-delta-cchalf</span></code>, CrystFEL-style, off by default). The same <span class="math notranslate nohighlight">\(N\sigma\)</span> cut is fed back into the error model: after an initial <span class="math notranslate nohighlight">\(a,b\)</span> fit the parameters are re-fit once on the reflections that survive rejection (dropping any whose squared deviation exceeds <span class="math notranslate nohighlight">\(N\sigma^2\,[a\,\sigma^2 + (b\,\langle I\rangle)^2]\)</span>), so the calibrated errors describe the reflections that actually enter the merge rather than the pre-rejection pool.</p> <li><p><strong>Automatic resolution cutoff.</strong> By default the reported/written high-resolution limit is trimmed where <span class="math notranslate nohighlight">\(\mathrm{CC}_{1/2}\)</span> falls off (logistic, target 0.30); <code class="docutils literal notranslate"><span class=pre >--scaling-high-resolution</span></code> overrides it and <code class="docutils literal notranslate"><span class=pre >--resolution-cutoff</span> <span class=pre >off</span></code> disables it.</p> <li><p><strong>Intensities only.</strong> The merged output carries intensities (mmCIF <code class="docutils literal notranslate"><span class=pre >intensity_meas</span></code>, MTZ <code class="docutils literal notranslate"><span class=pre >IMEAN</span></code>/<code class="docutils literal notranslate"><span class=pre >SIGIMEAN</span></code>); it does not convert to amplitudes <span class="math notranslate nohighlight">\(|F|\)</span> (no French–Wilson / truncate step) — do that downstream.</p> </ul> </section> </section> </article> </div> </div> </main> </div> <footer class=md-footer > <div class=md-footer-nav > <nav class="md-footer-nav__inner md-grid"> <a href=DETECTOR_GEOMETRY.html title="Detector geometry" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel=prev > <div class="md-flex__cell md-flex__cell--shrink"> <i class="md-icon md-icon--arrow-back md-footer-nav__button"></i> </div> <div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"> <span class=md-flex__ellipsis > <span class=md-footer-nav__direction > "Previous" </span> Detector geometry </span> </div> </a> <a href=OPENAPI.html title=OpenAPI class="md-flex md-footer-nav__link md-footer-nav__link--next" rel=next > <div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title"><span class=md-flex__ellipsis > <span class=md-footer-nav__direction > "Next" </span> OpenAPI </span> </div> <div class="md-flex__cell md-flex__cell--shrink"><i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i> </div> </a> </nav> </div> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-footer-copyright > <div class=md-footer-copyright__highlight > © Copyright 2024, Paul Scherrer Institute. </div> Created using <a href="http://www.sphinx-doc.org/">Sphinx</a> 8.1.3. and <a href="https://github.com/bashtage/sphinx-material/">Material for Sphinx</a> </div> </div> </div> </footer> <script src="_static/javascripts/application.js"></script> <script>app.initialize({version: "1.0.4", url: {base: ".."}})</script> |