From 1b5d36a2c5e281041c5414dddf9e553912a800ce Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Wed, 19 Jul 2023 12:55:12 +0200 Subject: [PATCH 001/136] restore pages for FAIRmat proposal site # Conflicts: # manual/source/conf.py --- .github/nexus-fairmat-gen-docs.yml | 94 ++++++++++++ .github/workflows/nexus-fairmat-gen-docs.yml | 98 +++++++++++++ manual/source/_static/blockquote.css.bak | 23 +++ manual/source/_static/to_alabaster.css | 65 +++++++++ manual/source/_static/to_rtd.css | 10 ++ manual/source/fairmat-cover.rst | 146 +++++++++++++++++++ manual/source/img/FAIRmat.png | Bin 0 -> 114746 bytes manual/source/index.rst | 54 ++++--- manual/source/laboratory-structure.rst | 25 ++++ manual/source/nexus-index.rst | 20 +++ manual/source/sed/entry-page.html | 6 + manual/source/stm-structure.rst | 32 ++++ 12 files changed, 550 insertions(+), 23 deletions(-) create mode 100644 .github/nexus-fairmat-gen-docs.yml create mode 100644 .github/workflows/nexus-fairmat-gen-docs.yml create mode 100644 manual/source/_static/blockquote.css.bak create mode 100644 manual/source/_static/to_alabaster.css create mode 100644 manual/source/_static/to_rtd.css create mode 100644 manual/source/fairmat-cover.rst create mode 100644 manual/source/img/FAIRmat.png create mode 100644 manual/source/laboratory-structure.rst create mode 100644 manual/source/nexus-index.rst create mode 100644 manual/source/sed/entry-page.html create mode 100644 manual/source/stm-structure.rst diff --git a/.github/nexus-fairmat-gen-docs.yml b/.github/nexus-fairmat-gen-docs.yml new file mode 100644 index 000000000..4d7e3813a --- /dev/null +++ b/.github/nexus-fairmat-gen-docs.yml @@ -0,0 +1,94 @@ +name: Publish Sphinx Docs to GitHub Pages +on: [push] + +# see: https://sphinx-notes.github.io/pages/ +# see: https://github.com/marketplace/actions/sphinx-to-github-pages + +jobs: + + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@master + with: + fetch-depth: 0 # otherwise, you will fail to push refs to dest repo + + - name: Install build requirements + run: | + pip install -r requirements.txt + - name: Diagnostic + run: | + pip list + - name: Run the test suite + run: | + # stops publishing when known problems are found + python utils/test_suite.py + - name: Prepare for out-of-source Sphinx build + run: | + rm -rf ./build + mkdir ./build + python ./utils/build_preparation.py . ./build + - name: Diagnostic + run: | + ls -lAFGh + ls -lAFGh ./build + - name: Install LaTeX + run: | + sudo apt-get update -y && \ + sudo apt-get install -y \ + latexmk \ + texlive-latex-recommended \ + texlive-latex-extra \ + texlive-fonts-recommended + - name: Build impatient guide + run: | + make -C ./build/impatient-guide html latexpdf + ls -lAFGh ./build/impatient-guide/_build/latex/*.pdf + # Copy to documentation source directory + cp \ + ./build/impatient-guide/_build/latex/NXImpatient.pdf \ + ./build/manual/source/_static/ + - name: Build PDF of manual + run: | + # expect next make (PDF) to fail (thus exit 0) + # since nexus.ind not found first time + # extra option for "levels nested too deeply" error + ( \ + make latexpdf \ + LATEXOPTS="--interaction=nonstopmode" \ + -C build/manual \ + || exit 0 \ + ) + # make that missing file + makeindex build/manual/build/latex/nexus.idx + # build the PDF, still a failure will be noted + # but we can ignore it without problem + ( \ + make latexpdf \ + LATEXOPTS="--interaction=nonstopmode" \ + -C build/manual \ + || exit 0\ + ) + # Copy to documentation source directory + cp \ + ./build/manual/build/latex/nexus.pdf \ + ./build/manual/source/_static/NeXusManual.pdf + - name: Include other PDFs + run: | + wget https://github.com/nexusformat/code/raw/master/doc/api/NeXusIntern.pdf -O ./build/manual/source/_static/NeXusIntern.pdf + wget https://github.com/nexusformat/code/raw/master/applications/NXtranslate/docs/NXtranslate.pdf -O ./build/manual/source/_static/NXtranslate.pdf + - name: Build (html) and Commit + uses: sphinx-notes/pages@master + with: + # path to conf.py directory + documentation_path: build/manual/source + + - name: Publish if refs/tags + # remove/comment next line to push right away + if: startsWith(github.ref, 'refs/tags') + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: gh-pages diff --git a/.github/workflows/nexus-fairmat-gen-docs.yml b/.github/workflows/nexus-fairmat-gen-docs.yml new file mode 100644 index 000000000..53c001e24 --- /dev/null +++ b/.github/workflows/nexus-fairmat-gen-docs.yml @@ -0,0 +1,98 @@ +name: NeXus/FAIRmat-Experimental Sphinx Docs to GitHub Pages +on: + #push: + # branches: + # - fairmat + workflow_dispatch: + +# see: https://sphinx-notes.github.io/pages/ +# see: https://github.com/marketplace/actions/sphinx-to-github-pages + +jobs: + + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@fairmat + with: + fetch-depth: 0 # otherwise, you will fail to push refs to dest repo + + #- name: Install build requirements + # run: | + # pip install -r requirements.txt + #- name: Diagnostic + # run: | + # pip list + #- name: Run the test suite + # run: | + # # stops publishing when known problems are found + # python utils/test_suite.py + #- name: Prepare for out-of-source Sphinx build + # run: | + # rm -rf ./build + # mkdir ./build + # python ./utils/build_preparation.py . ./build + #- name: Diagnostic + # run: | + # ls -lAFGh + # ls -lAFGh ./build + #- name: Install LaTeX + # run: | + # sudo apt-get update -y && \ + # sudo apt-get install -y \ + # latexmk \ + # texlive-latex-recommended \ + # texlive-latex-extra \ + # texlive-fonts-recommended + #- name: Build impatient guide + # run: | + # make -C ./build/impatient-guide html latexpdf + # ls -lAFGh ./build/impatient-guide/_build/latex/*.pdf + # # Copy to documentation source directory + # cp \ + # ./build/impatient-guide/_build/latex/NXImpatient.pdf \ + # ./build/manual/source/_static/ + #- name: Build PDF of manual + # run: | + # # expect next make (PDF) to fail (thus exit 0) + # # since nexus.ind not found first time + # # extra option for "levels nested too deeply" error + # ( \ + # make latexpdf \ + # LATEXOPTS="--interaction=nonstopmode" \ + # -C build/manual \ + # || exit 0 \ + # ) + # # make that missing file + # makeindex build/manual/build/latex/nexus.idx + # # build the PDF, still a failure will be noted + # # but we can ignore it without problem + # ( \ + # make latexpdf \ + # LATEXOPTS="--interaction=nonstopmode" \ + # -C build/manual \ + # || exit 0\ + # ) + # # Copy to documentation source directory + # cp \ + # ./build/manual/build/latex/nexus.pdf \ + # ./build/manual/source/_static/NeXusManual.pdf + #- name: Include other PDFs + # run: | + # wget https://github.com/nexusformat/code/raw/master/doc/api/NeXusIntern.pdf -O ./build/manual/source/_static/NeXusIntern.pdf + # wget https://github.com/nexusformat/code/raw/master/applications/NXtranslate/docs/NXtranslate.pdf -O ./build/manual/source/_static/NXtranslate.pdf + #- name: Build (html) and Commit + # uses: sphinx-notes/pages@master + # with: + # # path to conf.py directory + # documentation_path: build/manual/source + + - name: Publish if refs/tags + # remove/comment next line to push right away + if: startsWith(github.ref, 'refs/tags') + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: gh-pages diff --git a/manual/source/_static/blockquote.css.bak b/manual/source/_static/blockquote.css.bak new file mode 100644 index 000000000..4ce6e9b98 --- /dev/null +++ b/manual/source/_static/blockquote.css.bak @@ -0,0 +1,23 @@ +/* + * blockquote.css + * ~~~~~~~~~~~~~~~ + * + * custom Sphinx stylesheet -- define margins in blockquotes with NXDL documentation + * + * :see: http://stackoverflow.com/questions/23462494/how-to-add-custom-css-file + * + */ + +/* do NOT import, causes sidebar to disappear, see issue 341 +@import url("basic.css"); +*/ + +/* -- page layout ----------------------------------------------------------- */ + +/* github issue 341: nicer to solve this just for NXDL documentation files + * but this works for now + */ + +blockquote { + margin-right: 100px; +} diff --git a/manual/source/_static/to_alabaster.css b/manual/source/_static/to_alabaster.css new file mode 100644 index 000000000..32ccc19a6 --- /dev/null +++ b/manual/source/_static/to_alabaster.css @@ -0,0 +1,65 @@ +/* Theme override commands to control the html aspect in alabaster sphinx theme */ + +/* Override sidebar background color default (#FFFFFF) */ +.sphinxsidebar { + background: #005F73 !important; + } + + /* Control logo positioning */ +.sphinxsidebarwrapper p.logo { + margin-top: -8px !important; + margin-bottom: -8px !important; + text-align: center !important; +} + +/* Control sidebar headers (non clickable)*/ +.sphinxsidebarwrapper h3 { + font-size: 18pt !important; +} + +/* Control logo name string */ +.sphinxsidebarwrapper h1.logo { + margin-top: 0px !important; + font-size: 21pt !important; + margin-bottom: 10px !important; +} + +/* Control TOC tree top level links */ +.sphinxsidebar ul li.toctree-l1 > a { + font-size: 11pt !important; + line-height: 1.8 !important; +} + +/* Control TOC tree second level links */ +.sphinxsidebar ul li.toctree-l2 > a { + font-size: 10pt !important; + line-height: 1.8 !important; +} + +/* Control quick search bar */ +.sphinxsidebar input { + margin-top: 5px !important; + margin-bottom: 12px !important; +} + +/* Control quick search bar wrapper, nasty alignment with the google search bar */ +.sphinxsidebar div.searchformwrapper { + width: 209px !important; + align-self: center !important; + margin-left: 3px !important; +} + +/* Control text blurb explaining the project under the logo name */ +.sphinxsidebarwrapper p.blurb { + margin-top: 10px !important; + margin-bottom: 20px !important; +} + +/* Slightly increase the padding in the body */ +.bodywrapper div.body { + padding: 0 45px 0 45px !important; +} + +.body h1 { + margin-bottom: 50px !important; +} \ No newline at end of file diff --git a/manual/source/_static/to_rtd.css b/manual/source/_static/to_rtd.css new file mode 100644 index 000000000..0b6947542 --- /dev/null +++ b/manual/source/_static/to_rtd.css @@ -0,0 +1,10 @@ +/* Theme override commands to control the html aspect in read the docs sphinx theme*/ + +/* Sidebar header (and topbar for mobile) */ +.wy-side-nav-search, .wy-nav-top { + background: #FF331C; + } +/* Sidebar */ +.wy-nav-side { + background: #005F73; + } \ No newline at end of file diff --git a/manual/source/fairmat-cover.rst b/manual/source/fairmat-cover.rst new file mode 100644 index 000000000..d86dd303e --- /dev/null +++ b/manual/source/fairmat-cover.rst @@ -0,0 +1,146 @@ +.. _FairmatCover: + +======================= +FAIRmat-NeXus Proposal +======================= + +.. index:: + IntroductionCover + OurScope + Outreach + WhichData + WhatIsNew + +Aim +######################### + +Experiments nowadays create a set of very often voluminous and diverse numerical data and metadata. +These pieces of information represent entities of what is effectively a graph of materials data. +This graph can have a very large number of nodes and edges representing the large variety of +relations which scientists ideally want to identify and master +when transforming experimental research into knowledge. + +Experimentalists face the challenge that these pieces of information come at different levels +of granularity and format, of which many need to be better documented. You have very likely experienced +yourself how file and data formats are routinely encountered tasks to master in your daily +research practice and you might have questioned how these formats are currently handled +when you want to produce FAIR research data and publications. + +The NeXus-FAIRmat proposal is an interdisciplinary data science activity initiated by scientists of the +condensed-matter physics community which strives to develop community-maintained open file and data formats +for describing specific experimental techniques, their numerical data and metadata, +and strategies how to exchange these pieces of information. + +.. _IntroductionCover: + +The FAIRmat proposal to NeXus is an effort by the community of scientists of the `FAIRmat consortium `_ +to refine and expand the structure of NeXus. As a project which aims at creating an infrastructure +for experimental data to be findable, accessible, interoperable, and reusable (FAIR) in the fields of +condensed-matter physics and the chemical physics of solids, FAIRmat has adopted NeXus as the common format. + +`NeXus `_ is a common data exchange format which has its origin in the community of +scientists performing neutron, x-ray, and muon experiments. The development of NeXus is coordinated by the +NeXus International Advisory Committee (NIAC). +NeXus defines a schema of data entries with a controlled vocabulary and defined relations between the entries. +NeXus offers not only tools to document these schema definitions in a version-controlled manner but +also tools to check and verify how and if specific instances of NeXus schemata comply with the intended +schema definition when the data are written to files. Although, the Hierarchical Data Format (HDF5) is the +most commonly used file format to write NeXus file to, NeXus can also be used with other file formats. + +NeXus defines domain-specific rules for organizing data in e.g. HDF5 files (:ref:`application.definitions`) +and defines a dictionary of well-defined domain-specific (a vocabulary) of terms (:ref:`base.class.definitions`). +The meta- and numerical data in a NeXus file represent a hierarchical graph which encodes a specifically +granularized representation of relevant pieces of information and results that should be stored with +an experiment. + +Base classes and application definitions are two key components of the NeXus data model. +A base class represents a set of numerical data and metadata which specify details about +scientists, projects, instruments, and other physical devices, including the numerical data +and metadata which are deemed relevant for their description and the associated +computational analyses. Application definitions are constructed from combining such experiment- +and research-question-specifically customized base classes. + +In this combination, an application definition is a data contract between +a producer and a consumer of these scientific data. + +This design has sufficient flexibility to cover any experimental technique and instrumentation, while +ensuring rigorous, application-specific structures that can be processed in an automated manner. + +In cases where base classes or application definitions have not yet been proposed advantage of NeXus can be taken +if the respective scientific community explicitly designs, implements, uses, and continuously evolves +these classes and definitions. Here the role of the NIAC is to support the community with +data modeling and data science technical expertise, thus taking an important role of +cross-disciplinary review. + +The NeXus-FAIRmat proposal represents the results of this development for experiments and use cases which have not yet used NeXus. +Specifically, the proposal includes cases in the materials-science-branch of electron microscopy (EM), photo-emission spectroscopy, +ellipsometry, and the field of atom probe tomography and related field-ion microscopy, here jointly referred to as atom probe microscopy. + + +The documentation available here includes parts of the contents of the NeXus User Manual (also available `here `_), +reported here for the convenience of the user, but is restricted to the parts most pertinent to the our proposal. + +For more extensive information, please visit the original manual. + +.. _OurScope: + +Our scope and perspective +######################### + +Thanks to a cooperative approach across a wide variety of experimental techniques, +the NeXus-FAIRmat proposal of the FAIRmat project has an opportunity +to expand the set of data/metadata accurately described via NeXus. + +With a closely-connected team of domain experts, we will develop such expansion while at the same time maintaining +a consistent structure across different techniques and methods, striving for the maximum simplicity of use. + +Achieving a standardized and FAIR data structure has a wide spectrum of advantages, ranging from radical +progress in scientific transparency to the development of new, far-reaching tools that can be shared across +the whole scientific community. The convenience of such tools can range from guaranteeing data reusability within +a single lab, to enabling open-source availability of ready-to-use advanced analysis software. + +Perhaps the greatest resource, however, is the inclusion of experimental datasets in the `NOMAD Laboratory `_: +a data infrastructure that already hosts the largest computational material science repository in the world, representing a +homogeneous and machine-readable archive, a human-accessible encyclopedia of materials data +with tools for automated artificial intelligence analyses and data access. + +.. _Outreach: + +Outreach to the community +########################## + +A data infrastructure is not effective if it does not integrate seamlessly in the day-to-day workflow of a laboratory. +For this reason, we approach our newly developed NeXus proposal as a community-driven development. +We have drafted an accurate and consistent expansion of NeXus capabilities for a number of lab-based techniques, +but need extensive testing and tweaking of its characteristics by the community. + +If your data is generated with these techniques and you are interested in producing FAIR data and accessing the FAIRmat tools, we +invite you to try out our proposed structure. If you find any conflicts or inconsistencies, please raise them to us using the +comment section. These comments are implemented with `Hypothesis `_, a modern web annotation +tool from the journalism community. The commenting function for each page of the proposal enable you to contribute to the +creation of a more consistent and practical NeXus structure which, in our firm belief, can serve your community and beyond. + +If you do not find your specific experimental technique but would be interested in participating in the development +of a standard using NeXus, feel also very much invited to contact us directly at the `FAIRmat-Team `_. + +.. _WhichData: + +Which data should I convert? +############################ + +You are free to choose at which point in the workflow you wish to convert the data to NeXus, as its flexibility allows to +describe raw data, pre-processed data and fully processed data. As an entry step, we suggest to use a test dataset +that is fully processed and already published (or, alternatively, of negligible scientific content). These datasets, indeed, require often the most +extensive metadata description, but are most easily converted to NeXus, with minimal to no impact on the data processing pipeline. + +In fact, a low barrier (but high yield!) way to participate to FAIRmat consists in converting only fully processed datasets that +are used for a publication, and publishing them via FAIRmat only when your manuscript is in press. This makes the task of +converting to NeXus much more sporadic than fairifying raw data, to the point that it may be even acceptable not to automate it. At the same time, +it guarantees full control on the data until publication. We are confident that if you take this approach, more appetite will come with eating, +and you will be naturally inclined to gradually integrate FAIRmat structures and tools further in your workflow. + + +.. _WhatIsNew: + +.. What is New? +.. ############## diff --git a/manual/source/img/FAIRmat.png b/manual/source/img/FAIRmat.png new file mode 100644 index 0000000000000000000000000000000000000000..034aa452deb2c7695940d513cf0efe94291a1d69 GIT binary patch literal 114746 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

SJ*?a9hBJNeIH;OFPd;(P~M}Ih{ zalSkB(|5fUKn)$DI(Rao&Yx)}${V{Y(cdrLpHK4~lDt&SgBTZ=*S<1mwkN^RDY zFz*-MbY8nFsHx`#RoF>{9RvA*9WVbDuWadR2@gdxJC<^tt=FbcU(Ob1yY9MR;B;KF z^JumE2_U&*)j${UdBlK0C^A0GZxNaitswH*%Z-2Y$8Im3c4w3hbT6d>F#Ro%zuSou zW0fAgDQ4u*viz0aTr7X{{wrJrqnBHQD&>we_4%XgwO+m88svwvmvj$5GTIV4+n$RU zTEV|m#lDjJZzgbNC+!XV_+2E!A6c5!c~rLJ^F5tZZM*MOOHCc>Kat5xnUFR=g&px{ z58m{fP}hHqE)%2n_SUUqJ-X4RmcD3^`#Ynj3F#;_Q4*g8vm|Hz^)G_E5J|Y4zz*GL zWtP=>>~NA5&t0g|6uE2?+@@}ox=;3Y!jnGrd-odGQgBkSL#SpN&pE2NhMWGH4C%U5 z=<>*jJmq4L$8bn5+= zDmS&B^xZZPA*oQRlP9?O@zKL^+PU60n${~SmUJFIT;*S3sJN{0?*(%J+e`q~(eSSF zQq=(`i8?!UXDA%46;?5L)9X_>sTgd2Lx+dntucw-vNF?eXFVt&3Mul69Wn~oK~~3V z(ALpK2mU_7QA+B+i6uZkAGv9z6^347qe$F6(AvQ1MSCca?p!{lEpl~(CbC|%eUJdU zJT87dW9UP4Uu|YB5}HrbHXt;I{~+M8 zAu-;=eP=2^i;TI=oBL=hZngi>-azOD3(8M+&MxN(I7+Ju#h!vg6UrSNX(SQ1tG1~` zc**y8uY5D0-Mr`4Xn`G^g`R(Jf~%wX+VW|2&NA)GfjXAd=-{_rKKu_D*io@ve%=}Onf zwHWq$zO7z5bfsJrLwQql|O|ZuqMR~oGtPnISIc9Hu!w)Zm2De z$9={J*8#!R>mmVjEaa!ET!E%1Ty*1p?_q-%_z-PpUISPS?{NY&x+>6lpDtNaZ)>{f zy>0NDq`!9S{FVWOVVJvD60lj~wZv;u!3zKoFT;v(%7YbKvkK?EV_mcAW#BFM$tLC? zA11GjMorNcy1S*RxQ|vYsOH{z3maZ&c7C&OB=nFnkT)?Ai`TjI)707yR=A#wIGe5^ z>RP_>)^r49a-@vs5TqBw;D-K9{taAxrOdIkC~*IRD%{Vl=?3Zawq^IP$GM$8G+eb? z&bh||ycrHGyAh5hFX<3&>B-J;lNoHN_f6;EM=RblE5?lTtJmMxLO%;QQA`j*Ch0Kw z9r=*(fvWpbjj5@bp9nfKl5&uMTPW943^ zi^Mx;h;E?41iW|IC*7a3r;(Y{^a~K35VzMJNWJ4JHoz=kFMDBnjwD+x#`j0iDVe z&)}u;Kl={_@PLw_)a+|Ia;V2ZHn`YX0;DDr1YGVvJ);0Zie3vkM|TW_t_ey&1{p_@ ziOGOtZj?uYg7?50zZPQ1nHNacFf6%BPvoo*XWlet49)3kGrbzDD zx>IOuaYX>SD-Mimf_-TMnaMCqiKhEcG||+t`PBtM2IL!`8zUX1Ld1iZ>W!WPO~q9MP0gZ=!dRiSSc91{ zRz46k-muC(K562q*dXeR(vYT%lnRdsXK|nloctl)fPUnx?bQjdH2HlejT0Q%;@sXq z`zZzRDbGYOw{T-OO3NA0?%9VRbWpGpzK3BJMo$4PZK?;M7Ii8J_c)j0a1UBJm~TlJ z`G!sUHbq8dnMZe_2P-1I#u28RAHbD72eQ@KAYhywYmtB>m>^TYpuGPWVxCER!EU(3 zd=O?*4F216y?2rF$Il8W(C(ep7;0(G4d2RifetCTn%F7``0zITZ6IMke=rzm!EB5> zlg@8#3W*Rsaa}=@P2n?lrsOtp+C63t?hFv0pswoHfGj$HcFzSY=xaoq9Mq}6Zt(q= zkWOJj`uN&uANUZ{S4mb-CcgK}qItsKAo@O!RP#ym-#K>3@7nExdNSdm zKrdSL5TxP=p8@u=ds4r64nJv zo|X&H4EHLn+Ntb{@_l>weW4?kO|&!YWW_Jym4l&LDn-tZ+7wyQ#nlKcMeT(i0|k>z zUJxmaV`WRl?2e)gd-xk%t;Y^;)1mZ_uyN^ z0_kwn!4|7g=2BYsCJQpI#8=`%kKfG~2Rm(wc;q4B3=-qx;D&8N>}j79@G$|1hEhxE zgm8=_O+)DX1r6tp!B_BE<}Z! zzZv3~KA9n207Lw>1DgEX@kvL|4{5*0!NT+`INT+kX8BSz5YLCOaX{Mq{}|%cZ-(H4 zXt*y+rZSy5N}tWDe3MxT(sL8bph08E-mCDsJr{%UvVmlaW(YKM2X_h>g7ENv46zHa zB~t%s=bCWHDs2|Vj&1cU2`3K(7smwbd~zn86YA13+ClCT6-2p4G^Hq+)#)Y+II_gF zcBAdd-_{epDK`!f=T5B?&u0EURg8n0qm-jI$H7?GDE_=lx!1-Ekxjpth7`33n|F`Bk3{1PP1*-CPoa*1}7;@wtzbL6* zskb`EZ(@oC`O205GV$R0KD1)5mii8SV_*N30DO8?V?Vfy&bzM=@7ykcnyfMCe;xqQ z`=O=WGsiH0d(+#AgP!pQ>+UyCME?$so=ZCcLLrKo;R<`nAN!#^3P4n$W#DIuRi9zi zc&)wcE{VIk{&vHRM1ETaBj=47KN?9iH9fk*?#>03j|);hvF?K-e`_hSlD(Xa^)5y_ zM52(2p;;cebsWh;i@TOludO3Y>XEXgoncz(fnfU__Zj1K<+0;6A(*W;PjY-8AQ0Cb zPaT}80kMiAvC{n|!hTDYzWN8WM1{axXGJd;EaeA|I=e;sSo-<4-+W~*H}fB#OAgSRQR^l%6=#wv^n)y#;OP2E571E@L?bQeq>q$@v@K(`PrTu}IP#{W zVN*6AcC!GBbb<23Qt5F}AfP7Nz=?7O#isQqW+yH0CFO(xsi~OLey57LMq@JH2CCdZ zL^Eel6Mp|y6RtfQ;Ovj$&*58Dbe#IXN}`X<6GStS*wMj1)5CrDl75t>*G)~qVWPjW z5+j;Gb#mw$@8jnJ=54Z71?xvz9KmFf0voXs$u98-;FunGRHpNgN&4(hqO%V?az}|6>XM!c6moX=o34=Ql(6PLUZR zY{F$fgoNGZRYf_VgUs`03Z(cATSQ4+c6?kGNj9*$wx#kIi!$IUH{S@3bHz{W&%A;F z2PB*NDFCaC)5Sy+AVz~_ZXH_CG@6nT0sT=SN6E1f(%E7zWm((r=s`%idVeBire9Mp zh*=Edft_vG%72Q3dp{g&;+ptfS||*3wa@5c8iyFF#`##D_v zv`qWlk|L$7Uzz`48rK5?aeqmvFbf2O=J`#QFLXHL<1yNe#jMdh6(5E_H0;SmTmwx} z*Nx$dSYedP!9MYqKgC`mr#r6*%!oKbroWmJF7xMiKP@X#3XEE)r-xrI@umV_e5hmh zS)=>^=cQZnK5M1%6SXe9MsKM$y)sJjUhGHwIo)FHo4O%38`N6=z>y0jbT`6y5OM^_ z$eWx*Oqdoqx>um51zH>)vfl8bKtZG654(%9ZxSNw;Ydp%bm&Bhgvo8`qr(=9O72g5 zrs6dMXBx7$y#+O3zo^Z8p8Q%#D^OHc`UsOv1)9V;0AMmyn`VQDm^SQRd(pS*L+$&HpSWVjY-#mv;&!So%>0fnn-D3b8;) zXn}|^cG#cW19FtHbL@(?kVlEVs3aJ#I7bEZg(aG(pFvqcHGvVE(N=KJ(0Z7t1VWZmY zNwy6r%0c6e;cSm-A!DK^_7w+Ue%*)!mr}WWq4aLtQV6z|j04`J;bQCk(qKI(x&tUM z{)Rmm`Xj$)eF6!+zGSnZMAu@+{l}%AN!~wXVfxXo<^l7B=d5)6v5-Jh#Ru*{k12QM z9^~i;k3dw_5%SVW<#xQQT8l&461yo;FU)1dfnByUFdD7=L!!Sgo|`dPgoVQ3vY!4q zS^H7*BlKd(5)2^saw@d-X`-Hs07R{ly zvbd+R?~WhmV3{2+h!0z!+`%aFYwO4)!^8=XZhUQN>Z|}W-rJ4>4Y)eH(&Y#-p{jT0 zcHq5|$5&L^J3OWri()n*%$3Red^8`5T8CkZ$PfreYGBf89IYI{8zm24Mk|J$)!DH$ zvY$}zwuKdtd98OUg`#_(x6{HbX0_rlAm1zTaj+C0@>0@!>N{DxiP7IQgY#JeaaWC6*>#Rg(p+@Qzj?G^vpHs&U zojE3+f&a{iS%&i7xJnqt88o?(S;tCLvMk^^-4{^sObZk&B*%`OrIaOYKuYQ&%V_QLx%KXWP2QCw!5lf|)1!eHlP zJ*%kQn7XRiW_7z599zi&F#*pE0&xfiy)f8)YMB)TDF%i)P`L?I-jMyOQ^ln#Yl@Vl zJL_P^Y&)Jlh-geV4MAiIl;Ojr4Wd9#$hhMhF0O3JodvH@5vFvNv8%}{Ta7i*s zza+jGJ@13w^!*Db7|MKeaf!+fFF+=BO@i~Q2K}6 zC&}kDImhWdxuBQ}d|~h_Y6wOLAwws}45};$$6XW|a0&tIA>JWE&T$C|p2GMWl*Fg` z`OLX99H&ViF<#^j=m#~hl&)a|CZ`d25ExIhn(;X4_-Wbw_!7VuF5&|hXw-uRYM5B! ziu(a*{vOLUf%O06J(1?sbWUh$4y%5hnd;L)nE?lA@+r)%zj2KdOgG#_hm`j_H~+Jg z_cB2f7nV*0!Sknkj0l>YO-CkOg%U4GX(9(CU&aCs(C7{T^@smn8lf#D(6jB{Xv(Musn3H(eVQED#-5!!vSvdw8oIZrm z9&Dx{R z=CB?XiqTQPcy^*g3y@&{_!1`iLiCwj0lZC-8hL>QNSAujNK_89n9UQj3I z0Wp`#;dM-Q@26JR0ZS#Q=ibmAaI$#t{mp5CENpv;aWQb^>gF=*c;wBK9-WiPZ3n4| zr`8M2-O|k=JII2sPgblg0eM+hFttj7;N21a~DwVAOy(wX=0#JN1Ef3nLuE}F3J{e3J%Aw#ljZ50C2AscTq8UtmrqW@KUO*u!Fq6b<+F{4XUgghN}M)0RNI%AA(d#pDHBb#*Vd< z#nK=%zPyzfT_rx`4MEI=OVGmPAoQP`Y|fyZJK$PfTIc5s@nLe%a~WsLA)}m{zXLqZ zY90|-ggy}cG_ZEn=mPh@$!Ov%IqvNGAEG=E1yBDgjEEc*#5#bEmCwMiYM8+VL2_Kx zK`J8Oa)lj)k!4{dq`w@zdrLSh$Bc972+|3_xND;=1LB-glNA%9*GXvj`pyjp+k8&zB1Iep$=vVj!RFV^z68!kS6<5ik zDA=v!5X4pJ(G1KD>~iUc+1!U^JWK8|p_$>uv~2NDy5j24cO9=9K)SGR$a|;q5Zt8V zDPfCT9ajzE7cAgeLtb<6{nNcDN$lUrQfN*EC*qce6h-2yoY@W%{X4BZbEptkU9g2; z33Ah#ERb!oZIE900{|YdAd(eqJ3-=(Xq>qe;=13=hu&u zt#D23r5K3=a~sT9IF4c2FIyfDW9gqs!4FI`Q=u_@od}oGlzgDn3>!BU(!_;1Mg_lb zAHt;`FwQ_WbV=vjm?F%ysDmyCx|W1N5j}(N&LMBH^Kt^;Y0l}a85*hPk7({gDZWlF z!xwCh{Ih6~p($1S%Dt~2njGOtT$!WpHGCCHP_^gjNgV%*B{XVU#+jRYj1D}4*b5z6 zh7j7tC@}TgAU}vhrSa!DT=UPHdN2^(rLjy`+#-;yAnAmql3aBiOgF<<8D#N))hBV) zvilQs)l-CqqJZaUSnYvgEEqse!rH)1+gCun-C*(Lp2Z?&**$_e9-MLDh#A!%FP#|OE)qVtvUcO z$eyoLnO_A^&IYD}2B^)JntAr;j-d4ZfED2&sVU3U<9YvD0w}m3-=Zt|1IQx-1xPRZ zNhL)Cyb2V7q;AmWf3N_9@0UR6zrs6=?1a>tB@Y(6#3AU%P+JUH;h^!CLR64}mi}h2 zF?-*3fRaS>FW~2kErB?KgTGqx!&fEV(XR2*-fzDK(1)iX`)aP)uPjkOl3DY*-L*G* z3!iIm8|?&P;n64i;zu56(p%)^54$|x`GmP8FNq@OHRxZp0hMx(;qNyXeqwnS+4wD- zMWAd+XLKWNmZ#(U28jkHo+NnoHmwOF(ta!#1o~~*=1ZAdt)h8%d^AgEC5J`7GUaBR z)~An#AVzoB!`spoB~KvzLA7jrE8>v4AXyj!>Io=o4=!@n%J`3xhGshCRE@>iuxAY` z)&L)ZpwFEjzxLh`h}D!~|MvZnA}-hjf7>(LAA)lNI00ZJLXM|1RM;_Hgn`FoL`}p+ zi3SX>XT zHYO`mQInopd1O>SJ*AW(Gg~PPnXjAnr+fwgokiSsk!0K~wcuw%(YPZ5$?G>OMLMsd zs$1&~B}a7?n8=!fXd?9^_-%Qg?U<(|gNM=N@zsFiiFvndteCYC&sb)X$FqM0BHzoA8WXL0q3<44Kury=oZj zM54r&p=`$gOa-onW`pGMhv@(sbhh#xR1oI%0 zFQ&WRma!}DY)d0JQz;7}=N zUsgCoeQ;}#xpgpr+`nK02xr_@A9dzUPem2jTq7XO^MJ!wSQUpJQ3|sVMk7JN;r{{g z{7%dcc7hMMYq`|o6#b}KMdX-=&9OmO9DBwIMeo^-iy7F0LYfW6Eggf2xObY0NloHr zzxxtzRpBEDwS@noQeA1SDUkxULRTumK6cpOYIW-^ zAv%nlnMe~l*x|mb$2Lsd$D$(Ary17R+MMt_z`l=`^BxQ9=^=v870&O=p6MsKgoVJF zsk!9<30smY`KbHb^^Knk0fG{6dB>!F^k|T(7qu3v;x6t)n)2I|L1)j6Rvl9I`@;=T z{TrbQ_Ywz|Fa#>!Zu84w=u)tZsdan8Zpo|VhkG<&fv@NsPY|UakngauiIk*U@@qN_ zk=!1;sCD+?p65KVk7GJ#ixLLxg(V@*2l%e+9+2y3I|>BG;oo+!?8?RkStElPwO=+p zT{Usgeazxe!@5>mKH=$3+-p3q1}c0kww#5EqDaXcTu*0x7Co9iF$Cw|D+>SQryLEj zisbeW)3SnCUN-m zCrT{LN=9tVJW%TDYK(Yp=HSZvtMAh%hD&pv^M|X}ZBzYfz8fM%tQ3f+{uL2FFE_s} z2h4WlgPZnZ-*aR?{?u|>K2H)ryMNe5G(| z^7(U~$OfI0RohnvEaZ@zmn*x6Yho8f!;a$Y^vChVwBGZdCr48$2ItAHz3kPATl5V- zdg`7n9klJ5x-0i6Pilbu&*B~v2QytE#;;^Zr?>THpKAwp>;n%3uXA;G8#Zm*`i1ht zB=$*yzuW+iu#l_xT+}+mITUx3cLLlHT9!I&)DIP8M@E_xwAA-5DQ_j{7r=L(DfkOC zyZszq{0S+`6Cc`=q6f5nBYIcdpO^!qme?(P6T|+ySxQFf2DU{{bGZkYIsOPS89V0}s&&-5 zAcH-w(lB#6B&X4iH>Rq>&D>fDW#D!*Ij`;b42yz$y96nm0IhMiwB(gh`Z2DI$g;X; zH|>K~wVb*Ztv}#`&g|Lw^%f>dt;*SqVWF^>RXyWt13rb~WqJG+6n25S+o_HpJ~5;N zOz!lbY3Z#8aFpF^rq~)nI~jN~WRBGgm%c9TbvxlJnZKeae%;r~`C9m_#xrB$u3TK6 z)R_J3z)zE4fX$M1OCDx!T21iFfXb2J+wQj{EuGFN=t9zRhWJM5EP6i4A#Qd0h5 zqxpg-(!z7Tjh+H=FTUi`Gy*^zh%pA0dl9`)E?woaKHfegyOQT&$5*oR$8)c;8j|_3 z=)_55J1ej8OgrDokRt-ZQ71?a)qS7B^+HcUBeY6~Usn(CH#R`kSa+N9=siTbhy{MS z5jjg3`%O0VomWQZ!WWDY1~hz9T+kdGQ(MNzp`WE;i?g2Y;bG#1ETrMJjbpLu09#cq zs&hz;_~siIh0{5K43+rX zwK~AoLiI3rrF_TFwT30F>-H;7ABP^Qgn9OVVWM>FRWPjU<2daxC0f&YHtmsi-1M(I zw96Ttd8>7w7`zJF8`sV<6rO%}{9XgAJT;NrM@C63c2xOMB(-{U`fqv4eK7f(k8M%Z zWNxa{VCP>o(lgCt3U%;uE#C+mv5NBO0iV%HQ%4I&y09&J&*ho6j>?lXZj5Q=F#O|- z<+W=irT-iLaUpEt!1X#BGew%dQ%b$9CCUFhFHG|H8D!#-H_ncyruX#tx+QOEDLHoD znszj9ORm;*ZJUlhIJD!(7Vlhx>n(*A9yS{9B;mBW5p z)c1$C^QSt)mZG~U7fok#IzF5QF&|o{FQSZ{zvjpU7qc!;Y-QvVB~yzsXsAd z*4^NbaK<3VMboAgW691iXv1*)%9JYTH~oQR034-OKUuMM))Bol?z|%Bm|2t6<(oTF$C3@VF74CbtEEv?-D^5+JDQN*C`c`+ z5tFbKGCvcjtfX?NivRS3K!MN5hVCg?-mk)7lc^ozn!V1U}2Bdp_aZFSM4wID7BqC64Q2p-WGad7|aV zIMvJhwcoqwTi7A~-MgVI%Qmg9`&CNXb!u`m=mq^6u_rZBg4S&84A}<3N84KEo>k0L zma+)XHn(v1x95uvWt6avy6#N<);_6s^RkmZ^}{-T=>k6KgEUS)QIjpMOWnsmK)abE zpfOTM?mP-~Nc?)dHi^ICgml)}qGX_`xHzw(62Xef{q!iB z0`{Q(rpMUsuVo2~^#@eu7a+)DW0v-ypwvwEHkBfjnZ~qjfsVKV*3^Ut!CAh*$(ZXP@`Wr zUay8GdbKPbFj`QKFBv!56UG^v# zm9y|@ZW-O)5AXf>W9_&Mt9MsZv)^K6n%Ku^%hhF_OR(0&o7syMcCK5!2luli#u{gt zElcp&Vejw&H(W69H<#!r(b~&ra-U@eWN!vIn<^Lyh6oy~M2Xw>eT#m4)oh!4v*?G3 zqIN=EwI&ni$YEu3@wRsNHLN-Dxt9g+*OFS;Mk(I}O0oD;KRNc`FXwf+Pwz2atO z^L&+4B8NR;7En8nhl27isp7v^i?&QvJ0H_gsn$=-Z@9j|Qii|UbGa}weh+g~lkoPs zFNQ}*>;s+V3ot04q<#JRB!6>9Xt*3wts6N!lq^I?-&vjb6&NpO z?Df?}y-nR&RaI!(x~7~^Ev9P%Z6U_TJc>R40UJa%0xv0a=Bms4@%X@KRz0p==Y9QhfNv;`Df;-$<+j|)evk{jKi;U`8Y8(n2c`DffsUI}Il#O)u>JTZA=NViD%1h{>{-&S|)~ zXyO4CC~IXgT?RwQdN{)y^#s>y?}bJPQU$NODu~Iuatl(M&?v5Ev^zbt%6|b9QAz}R zy;D9MLR@%@%dXw8lCL_&ASElCb8$a;o~_fJC-A4K>F(t{!|YqrD)({6hyEBX)sN2w z9nljFCxrvUZ0tZx(sIp9%M-a;&|38fo(a<2a>uu8IsnsBB##)~X@*P6w~_j_J|2Bv zzRS$MtIn<4B`pg@@foqt_gq0Aq5a2VV#~mS?5^l?(BGyN?ErSH;l&Li#7e!ai}XGz z0z@~U@T@vACqd_n31&zBAVI3dVURl8_qv{{>l_L6M^E}*O65UcCrysse;2cE>BSD{ z#8T$C;RR{g`Ac7`b>rpN%ztWnsw1Qx8ByK+`uI{%YVcdHjm^S=mG#Rfwv=Tlh4*ww za##LZjC*vw*cA@U2eFf2vQw#aTekKx~e^se1exC4o*!4>3ByR772 z`YV(R&(^5Bxgi>$1wsww&tBKfYsql$su|RC9S@uWRWDd=zPX8r+C@4Ii+tC2CrPCw zN1s&^L5&hX6^*GNUy5zM-0`JiOvw$W4sU|oAgq_};omW4lGRfNypGmh>lq+l2PZFx z#aUK}dYZvpo({DH6a5EEE7bevA zjsj5#xq3%(E|+qO#4!sB5u%};uuG84YQmTX>3hg&`l|M5h;{J5;dhIaen0h@CMdsr ze=D>u--7zp0yr$g=9aq$VsQ-3OW4)&T-`1hrpved??zq=qeyFC6y;=-67>5FJQMu6#^~oj&rA0i=02qXQAi+Y4Fs%wZE+GxDqb3O zkxTacr<;IY;Io>T zv1L4Sg-*942{B?$tbyiuAuYeyZ=6y8r&gKw9p(!ZoZjYwS_YO+GmugdiEs?(7yfZx2Bka!O)Jxk0vz$c^L z%HdS#0G5LF#hjyl=70f{B7MiElV<2WvXnV@Yh+a*r0O5Nj~z9GF46Im=C&CpMx3NS z#ZV$;=uVyRtJ3x(1!D=9?d?=V`i@0lIgDtdYd|DmkWVOHzG4g6|vC&JqonF8( z>F}vu1OTX4`gr<+ShLCg%G75~4QAh9@0t8k&iDf?*|EmbDio9?u^X@5n_U*8%uK7$18SyFN{UuHbF#q(L7p-fHPM=)2=0^H6G&n@&|Zn`n|WnLc%X+4!aj zUxd?IjXW3f9%-MHbzKL_`bMlTW8Lbd?E6Ydm^%f`<5sy|HW5bqKZ!H_+(qv%6Z=;!8GMMVQ{(QhqQ7*_s1DW(s%uzJZuG1<~D}(BvIJr z;A&R(9a9QM(@ZX~XT_E|NsyApjLytx3`*L5aYTQwTA1kD=EY0l9u|*<2!r;|)*1LV z1NFne}=DRLK9a>s++)8pg!VSh}%G@)auM5TEsP}m&TK7^JQdugF(OF?$F(+GS(o@ zHYaJfUeP`1yL8`}J)GYAydeMzpTefSy0Wee!}i_<9|Exs_=8SY-OnPoFR06VadJmf zYyQ`l7Y6^4E#>5-Aq*ZPTP-}#09=CjS%KeS5~5Dfi44K9m zWp!od&8ZzXU$KQ;EOC}$2nh)|Iy`^|FGOmB30p5dkX9}55MZZPcOiEZoeB!|_=e~s zK$8m@YaBOo_2FZs8@P_5UCBZqRRJN@7%(-6mXV21<>G8kUsbK0695}?LZ0k z)_g6Sg)X>2iUv$L#AvH=%;VG5V>D>kp=&=S(Q)lAKNU1Q#|m&VW-lDM7~Z#%wgHw{ zLyJWLH?wOfQSG;%T`U)gj%AfWQVIvC5sUwer?T`L8z)<+2`E|$|0Dv6iT-CX6CF#c zg2!Fn6O8uD7c9!`K@aP!PS(AY&`kvlu4*)1^M(H!$EC=qx0JJ<4MlKIupr))lEgsA z5ZYXXqOrM%BIbTLhn|rd|E>ik5#?Zm3LYfZgRMM!5(yiCz-CYIYH5b&9zMmdbp*}& zl`bC{4T0K0a}_&@-4e%NZ-QZ{ef1NqplT@gCq+!|KQ5kRTPAV^(V zf`l!tm%xXXHO$a}Z4ds9&#e55j$E>2!0j2C910@$-LED{{hzb?;2jS^8!bcG2^BHM zUKpnF7ykN~j=`$*XQTS_fVnug%s*t#PluFBSx1+dQFQrl#VL~oiW3d8;#bQ80t@0( z!&f;kLb3VGEVo)!0LX|q@A_F`==|HR!&_4zlX?v*u)^`%)4IOapDWJf1bLP0{PnR2 z#CEotKUkq?zoih_FdH^wIzS&`mfR$umB8w zp;9nRGA(|<0vVM;^o+v^+s40LC*eGu21iP2&ZkeI>t9+OgXCF9m?{@*?43v;PNZw( zU)QsLG!}~xzQq7gEG~Qz-#FM{#$_)ZOsI!zWQ~Wj6GQ5BVCYw_LX6NA@DswYaMIBK zXL1qqR=-F*rccUv_=bvjM<;!ZrQN)NaW6752APML+H~ZG{yEgz>ngkhB9_tt#p3`O zj9F@4@T5ggu8=)8n)?J|4M=XJC6H~f&B2*-3y>C1I>7M&s-r>%P#!2XelE@{Oe+&w z6XXcv`wo5%GrnXt2*el%nJ;e-8b$unDS{mmPq81|T_nTM5cC%qXngR_Xdhh}X)dEa zNa#iHzH~y+8q)smN2}Trt0pRGQNGDNo*`?6s(M*h=*?j?`}M5U{*MsNS@KdkZsK->Iy!!|k+610e^|F)h- zOYvP|u6E{#YXN!XOzoe2^E=IkKNHACJc>T~^hb-@&ex0tVnBJu>PC|pE$Nbg!b+sz zY9s{;4_tr^?YodHi-gbOP3EWMGB|#QA3!cuqBO&@P_F~YcD(EvRVcNkKvlT~5!QcW z7DVO`fG3kSG_4_sodjAG&AB#hmSosg>=0p*&g(OPR16LwE6(Fw!x5C2 z68)3j^v>0awG|~W=+*7W3Re27K7|4jHU^POthaio{Ae0#poC>KtxNnwhB*0CE{Y39 zT&cw0FmG5JFE2g{P=NR3*PCk0yCw}mWZYO+#$7wVfQL!3r1H`vM0vo`y(qrtr6+F? zXf`Z(S+ZdR8h8VB zc5CIR$_E%1bsxXn@>%ATMo!iN8bsRG$s94eTsE9XQa{~u#20MX4m!~sI zor+;|cP}X)rl=BT%k}zn^)Af1dAy`i7O}GrgaSU(6?xJIGPS5!9Nfb;zwV0SLHuDXI$HX`73i&DN$gW68&HB(}THw#awtd3$Snwf8@=)>u<;GCAPtQ)_7&!`k?umur9b_ z^{?A_p!faB%qA2uS%gQMfj~RMH}t)X8_bupK+i_~67#mPZirZt z|K@R&cw&|I*jurTjys9YpIUPnVDycwfS@5HbKcG@5l-y*;a=Hq(``*4ap2H!zTLlRfu5I?Fe!5>Br!^yv;v7E?|ai@ zBm98ge2!NccAH<8ny8Jb-@N@_T2{FYWrt3VkGCfh<@?RgcqlGgJ>zM;ubyzHGt-xDvOPL0fQU_bh3 z$e|R7QQ~6WZ9G4FHKFD}sm|MB@KozxQSJhhFAtOQp;ib^qQ+ftXTp1wqhhH!qrec` z=wl>$r8d!VkZ;<^~?b3vW4Wg6+$sbNF#>$miY}C2MOm z45q)^&9GwDpq;^!<}CAtOpe~T^!(u!Y?O1hvh!EM=t6vJW?ceBGURV~civ?1jAc0F za!i+2RgDmt(D-ccMxVUzI zz$03~2y~>~Ise;HQ~zh=(8)Fh@A_X8Z~%f)zN&vsx*YjMx(+#U&&4b*N5OFX zC9r%Ud%!o457Uy=@dc`XNnO4tlm6DmgMe7ldW=K8djZuYvc`}wZO+naH&S-%3lt#@ z|NODkVzO#hvjBb(=8ezFwyi~ELYW8mZskkp?Jq}WNmBZBr;g3!yy(FvUZ5Ga@-^&s zVcsJy6iud;WB-P&ySsoN)Y9stxt1WkYIM!RLZNowAzX($d>vfJWgZB{gwW0-;%6>qH8t|@642x?k$VyZT(2Jp@2-n@%Od*P3 zkvI(a;MheUs_tJL@b4ooEc3>aby5a~fz*uCwKBU9>935AQ^&IUL~N;0El%b?B%7#Y zwSX^bq`1~^Mnj#ZR18*pY%;~uFH#GpDPn07rIo1^=had;db|k1$t~t{wBZcRlcovB z%0wI*LZlTa0e2e^4FneeiwN1eg^Ptk+yCaKkdc=lwRB`|-{<=@AEzJ;Q&W*S;<*RT zAP++tf?;)Tyl_Etj8Cl!Pi%i}`89$swx~LwT9dc>Le~9mN72URU)6S%b@=Zo$HZrQ zQokV50kArVbvo%_8|CYlgg_6DVQ9$TigR)*KbzlEnzxgaFw5GmDsUv0)_i~#*%E@z z%y6xP_Mq_8q<1VwtGEie?T%K#tIW5@wu3+;W8-=yzF#}EL>fbNkU^H`lgWkz zk)WJM>kZQ$-qa6Opj7av^52?}iy*=enDMa{g^Z*X(g8Ed4vZW=@U4_HP&j9Ny#YGZ z>dOu3nSh(wlJtoNaVg=OslDCUPMq4i(LZvyEc{U6ln}JbD7gB(-CzH2O*FRyAC7cs zd`9glsH-IUtA#nmyLkvOk%oUZd*5A`f;cOBj9<%uU;CJL;&x*Q?J-0$VR!ae`_eJ7 z+pT}=j)t2vrf#BADy-H(6;@mRW#n+g5S?y!C9nf@-)w9Z2SL<%bBIvh*yL*;w0RU> zarO32WQu*#T5=MpMMP2}9cJ-PZwYqZqwR|$?k3Q~CLq+n zAIncGG|Y?lg=(P)Gd-|nH?F}$2k`rNzbPv*LtQasz1Fh&KIiV{Z{E~*3G&o!nB51e z6|!)9CJ*WmNarveULZ4TpwwMU8YG+#`Q?P3o+l3}R9l*atIi&BSu6vgKjp4<+u8Io zHN<@2^+BK5L)vi!ny4+pW|*(vvc#dts`t|=Lv#83w}YVQr-k6{ipE%khqL$F)kQBDD+L)j=ug3T$v$P#W%v0Kk@ljFi|FIsh% zWmjoC>-CU#CvZ{b_;xf$3OpY~7T5rlF}0H~u=OLLR9mr1Z#u|3Qtj4I6vn3N?9h~o!qATL9)qI~)J!QbII{x)T86=)PO z1j#IT)XArN`dm4%>ZPAM5&vKBToM04AO&^a6cNcoE+Hl01w3h8c~)_G*cy^Kq7QEu zE$F)5I|@V{;UN9t&*dw&KxXRPKxRn~1=qSY`|x4Ri&RoUlI7CZ>PSop#l3X-Ir{T3 z@aZw|5r4iNUrz=*uEjl7+lhj+Tz{FW{tSoe1li6_{j4;$0s$LpbP>k|8sAZQij6As zf!Uk}uN+iZj!JoVf*CC0D^A`_^H~X#$57IjEtOr!NLi1L`xg}sVVa*Xu~bq8!(z-O z`hvrLc_{H}3S%$?!S7PHwI4(U#3T=@y*-T@_i}<7>G;{qT{u}n=p5MrWoN90lyh!T zz8eNVl6RxI0mwu8rxwALV@aNWn@pQZLWuNXRXda*1}m~u3tL=w2Zln3LHl-rehY;& zG8)Bnr%k?YR!4kRB$HB(?;bDvK7ZRaSOO@P>%G6&In{x4AZf0B+stP-61{}C>)UX~ zK!>Ar2Nb~s%!{L8*LzO~+Ua2o2y{h!BmOBwd>?8&4YwnF#lxbu7kFuQt9gZuc%f`u zMa*io;)WZTM2lP3qV!O-4BUv3f#jUMwZt6oPRY1Rc{;lxrTP;)zU8Q~{f`JlX(x{i z5(gT6g3Yd*lGQfzm1OD^UI)5}PFODsC}aTGMqDw+E$-g5LJ$(s*YQgkB$jDoJ>kSb z^Klfyv-}NPckD&08fdbC4V+{exzj5y15pT%Vbd>}rNBoLL=Oz&z0|U{GfBh4f}v+A zU?vEi<}ESaz*Kf$`wVrG@1YL8(dmjBKkMe*S8^0K(6I_?rZ8D4RD{SwkLf^8BLP3@XnzzpT@xb4-1aS)BZ z{kH|WF`d@@;8L>bbdm!v0|%%TOIgj=-JUu@d98B%UwGXL%dXmPOPXU>P!eL^JhXe2 z6JGnv@7G7OV&QOO- zk5^+j8E@w44%&g}SX|ZMtdtVjzK#S!8_sxdD-<}}5>Rb^)y9|Rtl`pD2n%8Bb)~}J z)J{(i5+2UKS%n5Mbxt_W2tneN0_7wi#H$SFIOi&<97{kg!fZADc0m1#pIdh#x0$Vl z%+P$WhH?CW3$i0oO#UbRp*U!^kItzgr|4KWfoND(`Eei+sIv@=>9Wm{ms+|YW9H7| z<)%%>TVA4vj-Jc>Ac!WRC^9zK`&>$7)geqI;p=63hs3N(3_z=4bw*lzSle5kIk7>3 zzVEE*(E)Y;oB;1|S#bTX_op}#C|}G^gcBrMU}Fq4jBro;tSuWzkl^ueA7qBDky{`p z*YF;clOsr7LU+4}QHOwpurOx{YdBMwz5T^S3j&^yY8uJ`8(H}?-E{O}xL5w9;Q!apt49#NK>C1o+NdkbFwO{Ku ze;+b%7o`rGM|(C@H1%3jp!|t%F}WZ(h5x{3Szk7eg=PNumSEXiajViw3U#_D-zjD9 zuDq%pMC~3!u4l(7ekVG?wT_Oh#`d9r6jq+t22@=A>Aj)m90sIp{?@;5W0MN;V@^xb zf*=cc#S%Zt+dAB-iI3S28dS8`Gop*xB|^|(6RS5=1Av%}4)~vsz#a$J|JCuNsbbdA z+0K6Rtptb)fI}OEj-KQh@nBMozucYIZx{y9z*5& zj?SB_Wy{8rKGYDvf34vh2(dSEC{Y`E^=+jx2`6 z*n!{w`%bK&5iU|~Q&JeRJ(=7S4!!pJ)WA@EU$VmyMIRpnir9fe_q=J(KhvYs(Qg68 z>^xwJ`9Lc9t8xG(Nh7mkVS@!3QQ%XKfK$Vjw@9fBMy%N=*;F~!(<7fdza_={%MFvq9A&rT>A%0kx#!2VsKLM%L(Kv!6w(qQo8=*yytrU3So zel%DECMXz6MN4ZJ;ptt?5d@+LzLAHWRwp56Lx+Sf0LY9s>uSS{10uOWf~Roc97o|@ z!=1zny6Iyjrw}O`-*@fg=6%TD9EndHkt%94{eM)wcOaGR|2Tegl1lM-9$8t@P-ZB5 zG*FpQ_DUpK$=;__JVq3uvPwu+va(OvyPWKq8M62Oy{@C@{rUd>I(3};y07bXz4pw4 zsN3XPF9rUBm^PR`Byy60@F=+W;SRsP*HqC@X2!UGyceF-kI^MFF$Ke50eKw}69BIx zv900w~v-S3?&KZ~#s?AzRpt=J1eR%p zlJsWpQ}R!enec)g^(4KwF3TERxV`-&Gt0}bH(4n$qb4_D7`2SZI1*w4vcT#f>4sYW z<-su_R_u23(v9t>J{^tyPT=Q^7RO-%C`a1$W!_z=8G1H-tpc(}EP9x+hT>iBIkVyd zOr?3GhY52fBQegi`m{o|M?(&>);ON}+><%W%Y1I>!Gh1eAvKUy&SU^_j>r=e>eRY_!ouM;tdlnNCAd?C4| z&&IyP;z%;N7OqeN=Lvzd(MzAzrhdZ$ym`RCZBMpSGI)XATz!x2&~A`%z_M+EHWjsc zkcFCrJ2@nj{0_rA3z!r@Jm!8S-FY1NQ4C<}?K4D7A*5_MK%q@!6!=>GK=C1zB=83- z!zl2wZv9OQmKa_UVUko|n=NFWiD87y=(v&9Y=oFtY?1{l4C&3uc|JyjosxD9u6_S> zR@jQq5hrKM$=?uVCA=s8){nVOHV_Gs!)Vxn0BHwAYs)J%7!4`CO5wMS0ut|-Ae(5p zf$?vfQFk1683M(cu*1i|hX-aL%s_%2ZD&d1|KVm-Q2qG~QJGw)Hx&415K+zCi>>0& zo%e&U6b&aOCEs%uqTo*eWaIw9PEO7~c7G7aiU{Xqt=@me;la%6_~gt}9R)twaWKA) zcH7-IB*y}OL&8Qrta=EoIs;MI^gJ=_<7Z?CBLtmi!lLp(4~g{b2>$%y9SwmTT6J&2 zAsNsi%kpz4)xo3QDqS~cCOuReFIdlGIxs^iRV6QrME;8nNk}D|gHVq5A?Q7ic4Mq> z^zWT%xS7DQw{id8>wQXfoBRG0gheaPEArm%Jb!ZM>EA=~j4Lh$MsC_6Vvz)R<=tt0 z4^U_jPOhF!&>+(hp-~L&Wjw$4F=Q!$uhxf@9u-AtwY2GRPQOs);x%M1bM=wws5fPS zj)HD@Gr#o})fJ31CpOu+V);m94WuMhg;bm}{C7;lL3XDU;`=22h#W`td|2SE^w_aZ zXzhe(X1jX>S`C<-fkY(NAAlTqsKS8!q58R368??(SI_P=#g!Gjd&CKOOF=%eU^UWT zEaKXW5qwCmPEL`%L{5ea(p47j^;Pa%9Um3=ieS>D4sy#t7I53kcQ9ejua6^+CY}*8`KCk* zhsXuTCY2vEU~-74-ZS%~webwlcOU23~H=fY4Vi}9YFyqxFF)nj&R#aN}7 zbd%F}q#q0Vqf%wnqgdm8}-F>d6R9J>`F> z9==iZn{GvG%m5qxhQN%WEkBD?=jSDhVgNrAO%ZZ%BEN!sXV<^07Jp@x9;KJ+U00Bi zE!4VbZ~LUcsH?kS=^s$eA%R=ZkOedOg5>U}BM_M_1fD|Tp^!QcQ#47Lc5|iaF{*FkVG=Nc%Ef1n~rx%Sh8zHkrF*5vyi9!s#6lnn$I zE%4ak3)fJ7f=|6q+DWG5M9Sv2PZm@Mh*QIitqa0gn8|W`SYrfm6mldcAtrM6`96Fn zAix>pDXphl-DOCg_E$*?%;9e~23kmdrUTiiFy-8#{(iwULz9FLNjJU}i!`BBsT zc-`HC05h@3T=i(krQ<&JA^x(yeBAC~U$us~|egJ3&=MyflVJ1gOk1kC(RTNSk z$8M{ya96u61uZ=M3aG1E3c+5w>w>H=AT|RbmJ^RSkyCd^)?;Oc*cP!Iyy5*WKNqG$ z1qdYaxH!JUJ6?LIiN=S;s<11wQq|!!ewhY*PH-4`Zg+k|?_0MIp|~<2?q_t^@N9Ws z_i`!!DdxsIB4G}0C!iH`?{33j9Q$U$#PXf&h|QVYOZ>`2cuVBP(K8r=sn2QaPC}h z5X=gcV(nZqF=H5p^oBcmoZG(>bGaIZVn>^e)}tr%_N}=xDwrv>;Xax`jigPO2K2;5 z4_iY_AVHZG)PCrAZb_fD(xjwaLtIv^Fc)yr_)EmJZ{=KL`J&s>^MB@rem5VP{R=CENpU$Am%aglUur+_JMz&{Oh)v$H%W})PTNBarf?!Mt4ol>KB@(+9tq#!;qTN}NzU#BgUXnW4ikmlJ z_nuU=W)iLayR+*`+~jQ~J`Mqza(^{SOFkE$WHziJSu1HTrv5iN0sYbw2FP%ao8u1d z?6Q3~eNRpXdQlW^{W$*R@&1TwiLYe(d%f3-acI!Za^Lte6=8GQ*RgUhUgIyo$xnCK zK7eU6GAa?=K9SQ(KL1HiiR-v*oMIXy!=?RcKU&7N>b1E(aj0oCSjM{d=eds54~kJGzAiJDrQv0!)+6H!KH=j5`(S93M)Kzs2{N3Z zVp|*0O&t691Fp`b6QopQgaoEuTz#`5+1EdWopXBT2X6jTQQSkhqK&&`r8J>semC`Y zyf#DId_hCj8hyS8;}w4Zo(1P3%Bq`W>S<6$?m(XfiO>Mo8YO5_x@M@zyIORmx+3H0 zzoDtn_PXd<+vCDLIQ2#MZ^!RrI(GqN9~(eQH(qptTm#W|S|4i#$1Wq!3$a#&<}q61 z(jE?t5S+^x7+t6RcecCYw)>5d8vUDG=`U7|FpfN_7d*FS`rAfh3B`XE}okAef? z>=mBJKZ|=FZCcN4?pypteK504O1VE_iWTs%r$5nY=nBu^_u~h!`+!QIakkI`)Xkk7 z)AnM+sSXiU#!kUy4|{$bu^b+<*SFw_f^r70IQ}vZ@dIuXMvA{}l9q;D-?3rCCyB?Y zv504K;A=^kit*2Na>6*+^GoO+P3Dvk9u=pxwFJHvFn;W8LJv2z!ef;@b41Vs_O7-K zGXjPlQefgRZ1(qbDufo95d6v8!&xoq; z{X@k3rr)$_YU-4CX})3d4sBg6L;!{$PTa|>?FV>mh( zr&{U<_dRnwG-TRI&&Rpx2YEzedtoFSj*wc&aSK~9G*n!^~0aj_tM?^`=Q6g z&8RAF@K@B|{H7*wT2+`;fyx)QtKRbI)X6R|bY zS0uu=HnUMr{AcNnm}2!^=$dwc1Fl5AAT50OkY>ku|#uk?;#SF#oTT*}-127kfM3d&v z#;Fz0v-#0#kL_&t3&WcAuHmJb-G{iWIMkqfU_QHj__!2BU_7u{wxpSKs;i-K=VjA1 zodlj#b{oqi*C))JlmEnk!;{!ky@`vgX<`yJT>{a2`{)S3ll+_@w45W;x@lF@c$aUm zzJ0N}kea@^E^KD@!;IiCv;a-l&*c9>KI-PPRy|t3969uC=4@rgq%+MA=)M+>P_Xc7 zt3O)+@Z%;sfu&iqJ>Yi{H0~cSaiM)lTOGQgH~o5A<0IWf@S<0n?w)yJwnSSEexom& zQv$NympAJDw4=8iyPATyo2E;ZsIiX&h#tSYeZTOmPh$H=)R8Ef5X36S%`3NJ+~th& zTr}<_xxJ_VXzjd0T=DQw1YQ~zs2xZB=uZ5vt&uA{UhMtM8jS|zNgVudaD=b_AW5B< z$CfohK}Ate5ZgDkQ5*I8wUyIjsbIxZ9fkidvymSBJY|aG%?7G#7ATv<_PZ5MB?fB8 z2s32Hzuz)H$nL)1%aJDw9j|fp7L%FWMBLB03B2mL;_CzcJtO(RcaH=d_q*cf#*rML;6XX@R2llx{A%H*R;*_hM8EK!o(R z3%xCGV+NyR={9y`k%O-J4AcIlaSn>B4>sE@``2mpt2oF7a&rFx#wM+Z_mnDeJ#L08 zTNaCs+cN(?rV*~s0~VkT2Lj&Zi9-T9r==Gw$CH^HRrJ9E#bG_ zYKAxi1I#E@L#6qdt*o>*-t*wP<(6kl%MB*)ys{qKhUV>0?`tUpJ6FcZsWGaHXoFWk zTjH)Vd)FYf9n&Yu^5nv$1L>u9?|dlcv-Fe_s7c~F4yRmul}}o`)H7H|AGoIyQdus; zO=qk`PBk?94Vu}2*rqs&ZpGB2`jAKf(Xx3)WzFvG!pvK zb1My9OK-;Oq7FJ`$z#FOVF+tJmPPMujg+h3doh^y1Kj~oG#()}40nK>QObZhF@vC| znqg-|FPsk_FB0GHD}&S-B+>5~J;Y)qKNiOt6}#uOB^}$S4`HXb@NsjRF1lj>iZAjo z`1U~-5I8%e1)l^Cno-eLiJW_GF3OhJJ=-L_S?$$TsG~D-p=eSEgy7ucdl*w+^H9D;u zNUr*MwwuN^bNvBTybdUOQtR_)rQ`6PpIsksjckq^NiMuW^4=6e9|-6AK;FlTouu;a zp8Hu_Lz5t)V;1&|psQqYpr(GfZ71IwIIugmkl1&*`6O2nhb+Gl?9E5Q!aJ63tixO$ zi?RUZ5NrnIFgc|<#!FEb@x`n`WlR~A#Cb90FF*dL{FE$k-Fd4dAUO8QZ`>`nBmu6Y zwlYkdty0ypZSDITble;&mm2@A? zn2hn7+6f0gAe+Bt_wLN2Y8%!_eC4&2q_MVfZynVOBTtH=)v8`y!m~*FNSE(=E z7&jntlqOm=GtY&ytqrIwCwoL%nI)t}C$z++sz)%+HiK)s!|^?h8zcssP0>C1=L8vj zYnQwGQ!g2{=Cd5^uv6}hdh;d0pwES~*-4B%xguX7WkV7z8Uo6(7D$t!?F<&ylhK0%L+c4@7vl4t%bTViu}-)*;*NONhTsSFrNken5b zG&VPf9xYq|^byR-zTZ9o3dFyjo1wPLRFmmeOShq7R^DgXKz+NCG%*ocPR zyD{Uow!{C-_uNwBH|kyf;oCVau+x!K7R25E12=X?~miIel`Z&%>Xj1jvmI@GSIL2e@LeiLM{u_cWS0R_kz85Eno+NclHT9@iH-X>a(N-6+#d#GVi|DY=qa9-ik zx;r6vCa85a7sTochy&M{+CPRD@bywp6`!H$X)npX0Gv!FgWIJy|~L0n@<(6C{{F_eE|&huq`HQhS^fH~NN6i9b? zo1U&{J@p>ukr$|v2^dXJd}UO|yFp`U1Md(q+aeQe7Up&qeso$hOjf~j1}lzp_Bodq zG+G^6zpH3}?p%5z7HgW_Y;d;pV2sKv=@epl`csFE>x63X2+0>Q%L z(c;B>qaK3^QEzlG{Q^T$K85`R>1eorz% zfr((cfch>=J1RnbuR(I4W8unJf(NU;Pco>nZg(2@U=+xBy>RXeUwX@_rtyE7hb_OU zz4;ub#q3K?SZG%wN&E$}hD31q$$Bj3V*=7#9UhVV-32_+MTb8Dm%|55TBKpCsd5&FHF&HxB}X-A6SG#aJQ_XX@Mi4-c7P^mSMH1{d7i zpJb+|QWA`t$RO3>NE6xUc}Y!NK$v(W1zrmIV`B4MdiErU#pE@aEew8XyocX`X?ZN> zmQo*_{wA10BS#SD45fvhM=-ipMaS2>?~ywnNSM^A+Wph0HqJKP;@O7-|-Y<}ZkyQ^tV(N%jg zhd53ptS-@Ff(}3gp?=`#TTo}^u8N=GaHdtJHtQGNEXI!*{o^GQvO0g()W%R6t20TA zh}{6X=*MA71#z;09o@`umw@dw`h7V`P~ z_mGFK78oYHBD<5)zMTL8$cvHvxpK*jL)VzgPATWEo?sQ(8Vm5f&un zmP;eu2XkGLSr;7q6j_*#lQU8k24mvI2WUvK`zor`T*o4+fP3A6jEk*MNaGQ(%V}vp2NiNM<_f4x2YR6fk3Jk{nKvXLeQtwISDemwV-ouxV(Y4%RL%`^^YT` z=pu8S*eOhwmG$Ed13jrP@vG(0trm;2(p#qB+AEs;N)UYxBd`M><;PZxK4xJ zP9Ulh8RGZxdDuW<8WKNAV5q-%C82)M&l%F3?(zkvZOpeyP~uHNM?he|Vl_EIMsNgP z?|CRd9U8zR$))@+z)#ts{O%(vd8S3K!uAP_u-JaCf4%ApPS6;{YyC`N1i7FWINlE6 zz+8#qPb9Q~vHT}Tw?w6*l0=cC z?LEm|f?yYLP0{ugXu(C#OF(XKmL^54T^wCTeBOfq6f)y z`3-ce2}U+Sz-o4KHy>7?t+>;sR@Uz*NimSi_JlSDI6I@&q{3Gm;Rph~{{JIsuvv+2 zNm}5Tqi+akB9L3uL;G&>eyq5qwIJ|4-RB6}X-a%P+GD=$RqY_tHyjFyTv`Iut32T`M~t|w0;pr;6XdIveZ?5rm6-&k4)DGM_*o0FfP6#&lw!m zoz1vep{AeQEy%$)a2RlQ;4CQm;a~+mew~6z`82jnDT>gPtWx6r*@vpBx%fS3yO)uH=t?r%M_3^d6PT`1g4=uWF-Zmd`h0jFp-d+|@%ugFQiU|eOmb}JqlOYI*mf#h zH^>HDx^yKXeL2mVe8~n9(d!a{>DRmkre7|KdBf-kvAP!5>ywAERTpp#fwKQrSM&xH zb>ECiIwwb~b=PuO5^8LK?q~mg@gewRrJLjIUV`24>12+c=~6w6pky=ku0LUU6Wgq7 zb(4tmeY?E*b>q(yZ&k(~WZj}WxnQ~%9~b4ACtk<$6i3hp$8Te~e}-x*wprmCo+K)F zZ89ABwczh58qp`86r<8-W*c36eB)Qxf|#5%P!)6C3%Kt3 z)V-X_B7i6!=*sv3htVQLk~Xv=<4`NwIK`M>lu3`hqqY}q2gx=O?062U3?hIErTp}@ z>0ng*X9;ae{HIjWmX5q3XJ)8_83rpoW)LK1e?9csw~T0-ir?25F`bLe3ZP^4ThCld zOHajB-m#!=$Li8Ff@``?9UL2x#OUm7q_>Q=J=wBOzoS;y1GnZMo?C&G8G;?MbY}o& z>B=D6Albitl>*;#H?PGtk1s(TGnuxwPUWU&t4IBg3>qS4+#9cIn8kd zqt`8YcEMh^d!H~~=*-B2UBS5d2!Ob$T=Mg=2)Hu+5$NTZ0G-ZQ6}FHQ<~tzTmu(Tm zB&Q1=?FA|BuU&=Tr(k#sLO|h{)A#6x?HTQzGN`e77+v~nS<~Y4)f;fhog|!E-0((M z9$}aqlO!WYtM?Mdd#xUUt6nVvu6sB^h1Kfj(6u%E@aY%3{y>cZu;n@i~P-%V{rQ!%enP*DJ|At`9b)=!Iv5q_4Bh!JQPnPSu zO!p_$OChNHm|HW+BWxoGb^XV5| zH1QWDVLr<7p?KT=y_oA;4Hbs@!mS)5Xsvy4y=j$Owd5uw{K+DGr~sQz9cHr)ifB^e z&B3uV^bP3!fd`~70*x$vjm%VtCgTnJ$8eBaJqc2&F2O@`pR&eB>5%^zI4-?D%A=9r z>?AtTLy?R7P_^q)M8+qqe&8nKcX9C6XK4t(V#Sc(`FR4MNY#+w+o3i#!q@JOpwGYM zfkV|mX~8bPeYk{C%}n%A=o~Q6+}DXiP972c@iscTFYmA8EA#SVtD?PR@*(lC4~7Sd z*(w@%x7V_npwTB&fYP?o-$e=;@b^I!$MQng5u>Vnv@ZbkyL-}D zcqn?PRq8s)B6sYXfYLH8D@(J^$V>urZ1EBC#q1~2Z?cCwR`tkyl@~jmPLduAwY-!I2*{@Qoc1FDS$lAN@(IqMC;K zDEDYKC1DeWv;q&ZHOzj=Q)boaEJl?SoAxqWb%DOckW+@j`j5 zQ^4dhah(#scJI}G-ZRo6<%=>yLw<|iP`tknF$ev;+-Lvg0u*!`K}y-g#K^se`FAa3 z6tM+}eULbHBJ@I_=gH04UIR`&Ap~>rsx?;o$vNZ0>VZ*k8}u8qtR{tlH?k_ai}+(RYDxn z07$2=$UiJXUt6l#M!?G!tLg7r_fhmsXFLQAHW+}n*-H-27hRjjhOsCEPH-xu^3!6&)9(`ZZW@j8 zmLSGRffXZ~FRp@?^_I!O?~mwiHncv@Tf*GBd)0@50lH*2-a5PH(&qO6!G)N^v z_#Ddc;AE`(=3LWH;sdI7Y<4d)P7VPCoVf-?99$n<e=9h^|tnsJtQpx zIox#h8I16{MTLS7-u;&KnE^-i2e>nnt`njK%Y6m4Hxy!o&%%RKF?5ft*gjBTa%_1g zCNm@Sum+7$aeWD2Z}$+B`Gc5p47{+R4%**U)6m9I_e}EyzP37g8L#`&kz2g&%^r-y z1^hmt-=>nCm@uN~FGWDFHwVG=E%{PSGYDlK*!>5=m-mVm4;3;nY^VeSl@ zBl(^v7@Ze9vYs7TM{ z^&H%!s9DVbj8(TGp(1!>{vkledulq_q$iK+Ag1ZyWZP0B1kSPzeA);kcMo5N*9Y|M ziOXTJ<@E(M1e`oJ(!u@fAev$JrQi-A-jFkBq(8)|@%c<4L8^v(AlYM_&*s_1m7C2C)qJq~3Pf6hxm>>*^V1vAOW3=xK>~NkV8@RD|%W=DAv#3mI zY(0*;MO+qB7Xvbj68#TJ1Fd7>J}mYS>LIGmoi1R^r4NlJ(ZddJSBD*D%OyLT($+h{!h>$sY`fB&rO@FxObW zHw!=AMmE{7(N_rLghd-hi3z^kcm|R&h&U^h<&ZpAkY1q&g*c$YhnUG6TtBtX;wyLy z&ce%d_CPWy_-#BT?ya7o5u#kdnt>=m|GD+)^bL>?9O+cA{b+l4qZ*sgtzRWIUI%VU z1_J#PJ(PbIIYz?OOJfaF*>4Z77cP-)z9uFAh|pUh?F(B?K5V6cx0p1N4CAc>O>8Lt z$hapPrn3(a{i8oP6C$?25jgMsR+5DvaN~pJW^0^uuM89t#9q<W2E($Ih#u-XhnF(okk`%^t9YNVYz)jC@vY#fAU! z7|C}P+0?Icmkj@S@juVY$2|}i){cGgO0VIoYq%{=0wY_6u~v@w8 z_Bx6`K4ymoE2S^=^envBn6oAZ*$F$aZ#t?Z|?X3Q|!g||N7)>WAxul@y0;!Nk$&?+tQo@*s_T7Q2w}e|;AK$@rm=P3%fK~ww zKc{R+F1e->|2d2K`*(B%{aPmaUl%w=hSex72!c1tum-;O2ZHRI*yfLk^O3kbHV#wa zkdxQ^+%Lu7B}$aXZ1YQ+Yy?_q;~TVmg3=JlYQuzWBrEAo5^Y(GB!H#Sw6*Pc=-z5IKNMe~s&{u*Bg|ob zIu}gL=SWrf#7N2vIwaa3o9d8cD5Gu!R@y$2l?Dk-By|rOvcU*x^>Z{A8RFxtzNw83 zo=CyuED@XP1flw$rto`734;Eq4o+Ad%$`CvgqQ$5l)G7gUuyweQ4Con32bs}j$PzN zWeclAyx{y}h$D+P14bX8W(($c@DGZ{H?^|j%H(yob0ex$z2MSJ7wKTijv2V6dQ`1C zk=|5yOX})a)Mhq+vaZC=IX()KN{H2E5LKrJ?J`YY>`=<%TRDUY>q zcyG8`n}+Xs*%&(uJ`1Rw0CJy&(r_eTPNvWIoh~k*Kd`4Rd1GifM-Hm01M6I+;v4pE z`F9(M?{u>JA;c(H-im1^$Nr)PWFa&I=UhIgDfm`7e;oA23-s|pCz=T>!SifyaoESG zplY1|9SaDjv4*s)E%hZi9K;6L(I(?w@8R0!{{G-=t9(WIw`Ml(d`eMB`qTNVYKUyp zN!B=`X$G=wdJ2ilo0OP0ia@NEeA>gs=2uuwCUw@W!1a~50gSNSUY-Rn;3lzk?f%Tq znVFVsS*wDMgS#g9tW=muMeXyxLYcxJeL!Q~aRj=|d!cf)aD#1nrg;qua+A9q}Z=lj_ zbdp2AIP^@a;`aaGv5HLeVaL%PngT$t69vOrW6> zs48)NL#aB|ymgL~IYJU#LQEqNs^PKrkx#jrO^VNQMi6&C-8>)r{H{Ld_c3a9JXqN>IOda*ayi;5u~| z*=RtfaqK*4~h5;rP^Xs{+i zLEKK%j8}<5lQduN17Dd!C`03jVS_u=fJL64iOUP{gep8y(=4@z3-U7iarjM0k~r9Q zrCv!5YHJ}^aseO0{=1%R-q}aHM}FkItn@~9#F#7=iaY}xKJpY?Ct@ZrZiN*IC){{+ z3Mg&5L5e9ydYo^0D=d?RU+aqzXZIW5Tp6Nl_5sBVh(pePo?0PCIObod?cIN}%S4j=?>h}7M~W$TeWB|}N*HZ){R1`X#u z&@-D|(X-_NtReHfkGn-8++%gG$Jpj!7_^0m-}4nblq5Ks6O(e1z!}BzuGu{Z9AHET z2Udu6Fo#eQOvPSah!kV!hW7rX*FfeE2OYN{9;{o2a0{2eZBRv z&G|NL@$x+`W#?+n{Q}>i$VpGsHV_?dXL`nnA;^^!KxQYrg{-J7{TN}t-(bI*N?nb4 zEaUyHmBHkhQ>U0{y+|_N;<;aLLmAZxi<|wn?-q0+tp$0lcq3}hH?qGjqd~~|i!5SlZKn<4Wif~~ zik}8jI30fQ>qt~*_89D}tkGZ};P5*7x*dcs*$B`Jn%Jtm+IvR)>hTGlr9l@I7MuP_PJmn1QGZ&+gexm~|?INAc|2A;8I@f(OC~ z>>J3@44s6ps;Iy?JbP&Q@6JhpV_>pxAm9RC=Bq0bC>7@@(FqFkyFi0_1s;-ro}l%O zcV7e2tA+6sBmwFOVR%jh!*_GFI%E@wc!;#Xn9et~mzNtZJHs=s zD0&ULZUkJlC|q>|j0^7tOP_fDKx;pw`@-Lp9{^8)kM7pTkzLTi(POoYWZc1yPW?^V zm?gL%--|+m=xPb1B6=vY!p}_tNN+Xif^*`fIm`nIOoN4(2Jm<-qP+m?7c@ zK{99u0)fo*lV~l`KWmXvvg`I~k%~k;FZG$Rj5#>`IU| zoi|+ot)soWPJV~9KWV>$tY4Sm`&pE%3?F(Br-h^jIFOZ#Y&s|}(2@`FLAWj<0Cm)h zp*&{zlE6bENrDxO1qD|L1Ym8`A>SC?UNQ1$!bcU#3c|8qjQ@>xD1anAY9dzhPgWjy z*9q1TjwAsE4vDf|-~*-Zpv;xwgwCsz2w?|w|DcjHO>y{MY@TF=!VdudcF)}mJ;?wd zI4m@iZ>S3)U%~DZ1rVkM=fu!29R$|@P*NNsHI!KV``j9op$w-e+eP=W8b_FsdB8b5 z1;K8UiiAU}qD33DJZAwE0l6B1ck%!qp!EaFfP{}^jio`TVq=G&q&{4SZ)TBLgAYkX z-2;`-{SJ523;w&xx4YDf-JmDvko9ej5Y`UtCq3hOHLWq@BurDoMyb0M&hvtM9%SetH!tOBe>08syf&8?DSO4G~@(M`9eqiYSfPpinOp z?wSNrlAjj1U(cU12rQy}+FK7oxEQIV2iUGHL{zc*QAl}*FG)^z@IlB)s|>l+56rps5VTduDgvZ~ib4bye^IvysEA zj-N!U5ayxvAc<1A^C8G|gJBOmq+|O>q$Th^2B`tjzE-HI!0?H?kKEVS59#Q-Mv3A5 zbND|XRtA3}Q6S;IB#KYslVAA(fj|w%-~Jmuzk8*XUt4yc7_jQIX`eoyVaaXimg@L! zpCiYYa1PDtcbx}_Hohs<%ymrf>>0R?BqX%k=!-lla?Ra6UiY5R@2M5_x$=a)JKt+V z?AY+L=T`p8`=#=Ax}!IG!-d^9M1*NFVVIaK?B?U!-Q83#+d|4L zyfpUKE#a61SS21ifap0Kb+XMJ0YdpZ-C05n9w9u}B&~mNLy>I|Ds{oXLOKWlIC=NF z^fTo}`s?9nXP0S+1qWc2h$txN2CZTy2kaJX>@@sa9W7!~3w25GX~6^EXvOaSDBUJt zKZaj83|}21?SVIQt9%zENtOT-UHHStN2Go0s3PP&4%e)EC$Gf~(RD=7?keN&rjGKh zMdyRvdmpK;f<+k#ocm3M@;H_*RU=LEq~nwsnB zN=tRC`RS_j)Ej=|J)mM>O1rQgakzgPH$R@^vom9R(lnXYo)|_o>mFu*y31B{+u)(3 za3a+hKm6SFH0jbJ>R+e(yI-Up{$AqGxMhB0!i?p+tvpNd*~?BsqI zR0;59ff)EUx~AiANN~I_Zds3)Ix*y*8dtV8NwZ>E^3yLNXZo*!Q+v0rzqiRREqhqd zo%NP!42d;Y^4-@dg5IhXhI4c5QsYVJ=~ZB{PPDvV$3w^m+xYa4p_1$Gw@!x5wI^49 zkxFZA5kClzM&NfLcC&;&%ZHnC-t}|H=V|G!6`xZXo1b5_agcA0uitwXklo%~EMs6O zlP*P>{n3Zi!`e*aFM)T85Z3)zudJ_$GVd|itp+c?Qnr;;KAK4t3qthY?k z7HcKmMV(AR-6bJyrMBIr;_eqXx1L2Kz_J?(g$J6B9IJYsTw z7d1X3=B-aXJSP_PdEL#~XZsH0+)wWGYo4DYMZ*WDmluxJG+ApOGv2bM5MF~wY&3cw z)#crD<@yZYw>hc!^54EidGn(EPGg{(bSJl6Rw-wbN;sDbym4L^FLT3HpJS zCG_7t1t{kk7stw)7AJ&MUKAFF%kqZRiXGMiM{U;`wf2&=otW9m?VA#rhzuW+$lT=#9-au=o$%TH*8=-+P&&l}0fo z?NyQ3hGOqit36FN@Rr$^yT>r!5rm`=>S24Qf~dsjwkOlgMJNu;M+Iq~aVny z>%SA_V#AYa19Pc8w1InJya!3BOHb-MQTsrO%`e3@?>*qXGf%oD%VLSKpnzz}^~;9C zlNT>lv^Hz;hN-2-G$G~$Jz)?p)nRFj@Jksc8a)>pE%(xEU;TM`jp8;Wk;+<4wcStS zGR%3=oCXuAO?NJn-nVD>edX?a=}M1T_HK>5E_8M|V*l|)n;8E^UCIbZC>~6EQFpK2 z)ll&KbAwkiL^t%D5Q*Ni( z&Oc9H(ce2fXZ}?W2;Sc}-*PbK?1$NAwrS00i{;Bz55%Hv<%Kv~AOz9rH7rp*lK9QQdwrYk2@{#{QMkbe{NWc*tA zcvAA}TIC&Ja8O0lheR(lf7KvKp;93CB+IjALQIMVTfBY(3US(3yv43s9lzNLfiFrs zt}edR2RrY(pHZ$w=a|EJ2nM7Z5;WdWq_sLL9;%p}PB(wnCEqgLY~_LsZ*uj`)6Q%& z@=`tZLzyRrT8$2?7+Ia&VMNUR&nvy#tY|m#@MM%o@~~$WIfIsa9-BSE>EA9tN(R# zQ`0f&`)>KKn|$G2g11O=x1qW=K>o28ORVm-LLUK9;pjwDb_P1JN3zaQe=?L_+NJZQy(C zH&9=IH-}q>HSOLx97PA*WrW#~Af3|%fI*p`&G(}s0JT!2`jmKX+-#e+)uhenKJ(_@ zs|@eF11~*6bCLm#2hX(23iFmjq!y3GE#&>($P0b|N;~5E)ioiikn-!roA=DV4)N+7 zS5dXf{r^4V4ENBuLb?Z)NK@wwkGNzP-Ljf+<*JmL!rsfWAnS@j&-G)FRo&uCimWNcHsQn~nb338$GJ9yb ziooDcBkBba=A@;FY7fia<5I2haRK+VSjK9%lTL!@%^pdEM!W=N61@l>u_6Af8LqFB z2dO|TR2n(4T|2~nHJs~so%Lqgb0XXhdV>V%4M}#udDBl&&i`@_m!yBN6zN%S7OmxE ztDjvYIO7+mdB3wGsH5)%x+~2@5}`PfD!y52hV0*WWL+**p6s@KS8IQdsMJqmsCkLu zYW}U(Giy0rC|_Ywcg~4yk2iF=r=gYsP{|*pYW3S4&%!6q zl@`1z+*J@;QhrQAcOppui3_vZS~^Nv+Kj5G(I>tN(wv(!;Ti1OC>CjI240-3bqbCp z$V$2z<~QTf$3_0o~} z&YU&wnrzKO4l36dw|P|jeOb1veL_}^cQmQ%r+><}n4O7$ZUl9_y!ksTKE!Gt4=$?F zObr!^m7S?lI4Gh1CFwFI)7m+`3(j77BE>dMtW&{~>W8)OpIHMX7_Yq^iEaRvS7Le! z!-&kFFLN6MfcaHZBz!-6fpqR-gA&>~TWyfMF0ZvjAXC}5)QWfQH@kwhHAzupAkoOc z$g3H1IhmL|n4LG?5Y8_oA^rjwAttbUz4g{JN&D?XFRpN!iiG0`yunY#-KhXfh=0JZ z2-#b+DMlN|kcJSOs1dxnbPiCCYIFuN20tD?!&Fah!nU#*vbA_Xe0r^Wn+*M~`4;IS zoAZ6%9aNO*eJaF4C|0i0x*pc7$M@FK3F)rQyL@T^K=5j2M2-z&_fBfidE2o!(Did9 z&h0n*D|JK_*(9o%l}gV$Sd;8=6o+R)*UttiH~%i2gmu(*bx~sLfBddQ1O_gxfv4Ds z@xE*Rk*us!2rFZEb(>^KIJ%p170fAN!R}8uw=6M6Uj$g_n2_Kp)wunpmSxxhq&9OM z8AtMWLBo)ve#jk0Qd%|>*kxL+;woT0f(sB5`^Na;(J6bztlm%@;cfJO?~-7h)Y^wq z77u;-!VbW)tNi~UF}-Th7$L+0+Mzk*xutzPk({envHc8jidB9R9hcgbM6@MdpavlH zrn6x5wN3(taYy|?BFcajg0~~tO#>UMDi4k(0JFzF%aqSRI#>z9z|vjK+75DNDTnV7 zNzfy30>^K+tohlSA&j)|{>AcS_o*=S^VJWN-W9K2TsISBQv5B_!h;1uPn^{bwM;=f zniXK5VD*7VHHw6v?PvAt?hO;CxXa0S3v0y&Cp4&sv$B}7N_Y@Rx2vGt5_~jOFx+=% zQLxtc-TP5QIs7=oKj!G@2X>EM6qW}^&(Rlx&H!UJNKXC7D7JU6L>Byxt`=K#z$nIX z_z`=T$u1R{#ueJh6LcUtXC+Ah+WtL!eebZtZ3!0qq^Oi;Dj#BL+hHUuD+BTKUKB(f zh@0=A-qha_fwD&sN5!4@p8)sg?KDLnlq-FR&(mitKS3Oz$F<nM{0&1b`OFxF($bKhdiY^yEIq{rwK(_mWVY z+yBV-<6H05>zQ7VUW*Y9K(BC_Wg<@lv^W?v;ZgY)N6^LHwr}gOt$`DpP>{IN#}6P; z<4?rdDl$>WJ8InuBLdBW4S}8~X-+!wlezw*9-z_1v)lKE;RvTcPbW^w41e_b#g2!q zrE#Du!{2c1dPcV9C}4&S6w+iv7qRFZgj*j?caN`9@=S)q??~7~OsgqAE@LOOyr>rn zv=DI9LjOl*A1@%*d{$i0C(OP=m8*pOqaMiavK~F-D~Myv#iIMtdITM}Ff7$A1-aat zkqy@`_w#?ZCijIToi2iOVgbV;6MB&W^Q-oDf9&S*8Dub`Mf?TQ)v13XNsB^Ob1|&c zR!DVaf6dMRSzM2WkX(+x4wq+at75bZ0VgwT6BlM(TX_tet$5QvtN3{UofaL3jSJ`) z_?9AkJ3vw&)IWR|9CQ^JEWh@ujbcIQmq*P(yvN?a@i`g`GvZJ9S%8^2@EgJhs3Tsc zNmn;tc4kfq-H)kd83nGsr>hQ90nV#h(VEDMmbBQtl3&i8-aP@I$7>%ldB+(7ubGuf zc=P=4Y$vCe2R2HPg|78*_gdcf`QIr8PQ@2y@7`g(#fUZENJ%tg_zPeUb(_}TBc3rX*YT2F8T<|l?6*&kR!NYqp8>X;z_3B$i2Nh-nz@HQ@o zv{Z<>roct`=HJH#oV>SOkbBJaWvy7c{FJj9+}_8p%E)%mae@up`AqcxT=arcz=3qd zYBgg?kxkjaEr52_NGg!oqF<{9&C2}1xUIY8ApxwoEj}~8d7;eW=?W(p7u~R+|2`f~ z_*jjY>h;%>Ouzov?qv{{chA+wSJB)ry$XT+CJxX3Awd=2qUl;-9(dU^q@^>9wu_x7 zCN$_hyIT{5STN#QW(l8JFW`W_eCS+QY27Y!?sVrH%=zbqyV~1pb16AJ2rMar%dSo$d*l$w50*d~>e+@kzu=KD`@&|qOBLl_5`Nxd8Yp5m zz`pzA1@OKD!*Zue1;d*riOeLzd%f{d*Nt;b$^YKdNec^=Q zHF|IKbLf{3g@wvvDx?j^ULhSU63*Y1jtpNt#?+ytNUca1cX4R_z-sDh?2HI!Q@2(& zynmKcD+v}CWVOrVRP6!=p&M>3q)L+_9lzJa2<*BLuhcH36*1+Vj<2#g0F8kcqfO-+<9r*sWR$&gP!~h;AHF|h`!>%iH0eYDJW=AenQ>H1AmSI_} z22z#>+kNV9c7pn%9Z9P#`+6UcKA}PPDYq8Z2PiQc~Wa!y@annk? zA+L=pLiER3-XBCiXCaY?92=C@75xKV!%EKAL7M-5$5~_a5H_33vOB!-7V#BXC98J8 zOp~XiVD+`SNcFWm&a zlseNsXJ)qluf1yxYU+r>*P=s3M;kDxm62&WQ)o>a3(g2KJjMa762-O@vDgq43WFM| z0SY8yMvIMT(5eUolqe8X5Qj_57;}o zv)MiOobP<+?76%9tx6}sUpP_~1K5SrioZhKr1lt^HU! zW3S_C{0Cg|ob1nI;GqKryfWog z;2HoXWz_Mgr030;L(nro)0CMa@H@Zf#V+|CnGt&-$+OTSRo!`zaTgSQNW3V?N_~8!yU%^FIaaI zbR`KuA28e(#lE0Cvq^yw(7iFOb8d`dpgefo=O+ggm4U~tB#ZMdbK$K$#^b3iSnD^E zdX@zvExZWHaQkkZ+bOrdww?vr+&zs1plI;Aun6#E#aXC7`p8;fYn;g5a^uKEfpZl0 zF)3vFE)GI-rxD?=RX2q~h+3ufgwF|B2uL3cBsEE-k^iC0tvg~&^IfIp3%E3754$UD!y zku#4tNNxY_l#hbK5kYBKF=WM69Z*{CYuHoX6t*)1x|SUWwJ-z?4Ue$$bs~5|;5|s_ z77D>W)`d_;<5hDTpi=4+cS3e{IC;u0EG7vnPM z6Cqil9mtGsD?!hEe92p%L6)rS1tmS&Jyavf1(s5pnmjF+-J5~8kUCB%w23h=)}E!9 zp!I}+Ash47eO)}?LnLf_G-Fd6{bPwApUzHw5$*ta&4c<|`l~S9F{;THO_5(0p7UAB z+jTT8Cu3&cZKM?Ja)>3970rOU;L`@|uuV;VfiqBIU7jJCHRA zoUm1sE9!`UET7Tw6#+}z<_WsNmhR_HCdFNQg7ORuOy7wTU?pxN`El1z4konvt|U

SJ*?a9hBJNeIH;OFPd;(P~M}Ih{ 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

yZj4a z+&Sp*Aa2!ph6crB)@h1>vb*{8)k7m%G`F~$i&PBD)HnyI}%JeO1C57J8z zf%F1G^LT$~hhee=afXy$sk0e_`V&n+rBL9L58F)-RKkI5ye^aL;O3lNaD*=`{MTa1 z1urur5Wm4nuY>57V5$;lhLnc!r3MaG;ouK3!!L~jjyckxN#)?Uy%`Q%({eOMJr8(h zZWm`(H;Nwh>n1FN;Bd5RNxgAoQXlG_unHUo9K$Y!0_#wdQ6E}Wd1^488HuL1AOg#R zev@GrwWMqA@CWK`NVk6O1q_NbMFD>AEkem1_GJu#gz65BERwn<5I0 OdyC(8-{OtzqyGX}z-~YQ diff --git a/manual/source/img/FAIRmat_new.png b/manual/source/img/FAIRmat_new.png deleted file mode 100644 index e5b7158a781f014b5c2a7feeacfc72e32fd507f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10334 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 JDcT|Oe*jcWnZN)5 diff --git a/manual/source/img/FAIRmat_new_with_text.png b/manual/source/img/FAIRmat_new_with_text.png deleted file mode 100644 index ef14aa0da6e1d41dab3eb03455e322097cc58f86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29306 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 diff --git a/manual/source/index.rst b/manual/source/index.rst index 962b7f691..bb4717055 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -1,51 +1,35 @@ +.. image:: img/NeXus.png + :width: 40% + ======================================= User Manual and Reference Documentation ======================================= -Welcome to the user manual of the NeXus for FAIRmat project. - https://www.nexusformat.org/ .. toctree:: :maxdepth: 2 - :numbered: 5 + :numbered: 4 - fairmat-cover - nexus-index - em-structure - mpes-structure - optical-spectroscopy-structure - apm-structure - transport-structure - sts-structure - cgms-structure - north-structure - laboratory-structure - icme-structure + user_manual + examples/index + ref_doc napi + community + installation + utilities history - - - + docs_about ----------- .. rubric:: Publishing Information -| This commit time code <>. -| This commit identifier <>. -| This manual built |today|. - -.. rubric:: Acknowledgements - -| The FAIRmat project is funded by the Deutsche Forschungsgemeinschaft -| (`DFG `_, German Research Foundation) - project 460197019. -| FAIRmat is a consortium within the `German NFDI `_. - +This manual built |today|. .. seealso:: - The extended NeXus documentation: + This document is available in these formats online: :HTML: https://manual.nexusformat.org/ @@ -62,14 +46,11 @@ https://www.nexusformat.org/ :PDF: https://manual.nexusformat.org/_static/NXImpatient.pdf - FAIRmat website: - - ``_ - - NOMAD website: - - ``_ - - - +.. Suggestions for adding to this manual: + Look for some other "section" such as "introduction.rst" and act similarly. + Any examples go as text files in the examples/ subdirectory and are pulled into + Sphinx inside a :directive:`literalcode` directive. Look for the pattern + or wing it. If you are ambitious, add index entries. Many examples of the + constructs you might use are already in the manual. + diff --git a/manual/source/laboratory-structure.rst b/manual/source/laboratory-structure.rst deleted file mode 100644 index 568e6d482..000000000 --- a/manual/source/laboratory-structure.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _Lab-Structure-Fairmat: - -================== -Sample preparation -================== - -Prototype application definitions for documenting steps during sample preparation are a part of ongoing work. - -A status quo of this work is reported here: :ref:`Synthesis-Structure` via the :ref:`NXlab_electro_chemo_mechanical_preparation` and the :ref:`NXlab_sample_mounting` application definitions. These are drafts. diff --git a/manual/source/nexus-index.rst b/manual/source/nexus-index.rst deleted file mode 100644 index 1e9bf529a..000000000 --- a/manual/source/nexus-index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _NexusIndex: - -======================================= -NeXus Documentation -======================================= - -Welcome to the user manual of the NeXus. - -https://www.nexusformat.org/ - -.. toctree:: - :maxdepth: 2 - - user_manual - examples/index - ref_doc - community - installation - utilities - docs_about \ No newline at end of file diff --git a/manual/source/north-structure.rst b/manual/source/north-structure.rst deleted file mode 100644 index 26526638d..000000000 --- a/manual/source/north-structure.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _North-Structure-Fairmat: - -============================ -NOMAD OASIS Remote Tools Hub -============================ - -.. index:: - IntroductionNorth - IntroductionApmTools - -.. _IntroductionNorth: - -Introduction to NORTH -##################### -The NOMAD OASIS Remote Tools Hub (NORTH), is a `NOMAD OASIS `_ service which provides access to containerized applications. -These containers contain pre-configured scientific software of different academic communities and offer access to the data inside the NOMAD OASIS research data management system. -This page delivers status reports of ongoing work specific to NeXus and how NeXus is being used by tools within specific containers offered by NORTH. - -.. _IntroductionApmTools: - -apmtools container -################## - -One containerized application in NORTH and its apmtools container, is the paraprobe-toolbox. This software is developed by `M. Kühbach et al. `_. -The software provides an implementation which exemplifies how NeXus/HDF5 and community tools for atom probe can be used to document provenance and steps of post-processing -for many steps relevant within the field of atom probe tomography and related field-ion microscopy: Inspect :ref:`Apm-Structure` for a status report and details. diff --git a/manual/source/optical-spectroscopy-structure.rst b/manual/source/optical-spectroscopy-structure.rst deleted file mode 100644 index c5d881d99..000000000 --- a/manual/source/optical-spectroscopy-structure.rst +++ /dev/null @@ -1,184 +0,0 @@ -.. _Optical-Spectroscopy-Structure-Fairmat: - -==================== -Optical spectroscopy -==================== - -.. index:: - OpticalSpec1 - Ellipsometry1 - Raman1 - DispersiveMaterial1 - -.. _OpticalSpec1: - -Optical Spectroscopy -#################### - - - - -Application Definitions ------------------------ - -We created one application definition: - - :ref:`NXoptical_spectroscopy`: - A general application definition for optical spectroscopy measurements. This includes specifically: - photoluminescence - transmission spectroscopy - reflection spectroscopy - and general spectroscopy experiments - - General spectroscopy experiments refer to experiments of the type photon-in photon-out. A detector is required to measure the "photon-out"-signal. - For Ellipsomertry and Raman spectroscopy are specific application definitions listed below. - - - - -.. _Ellipsometry1: - -Ellipsometry -############ - -Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. The measurements are based on determining how the polarization state of light changes upon transmission and reflection. Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. - -This application definition is an extension of :ref:`NXoptical_spectroscopy`. It provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. - - -Application Definitions ------------------------ - -We created one application definition: - - :ref:`NXellipsometry`: - A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - - -.. _Raman1: - -Raman spectroscopy -################## - -Raman spectroscopy is an optical characterization method by measuring elastic light scattering. In this way phonon characteristics are measured for a extreme broad range of samples: gasses, liquids, solids, glasses, crystals. - -The application definition provides an extension of :ref:`NXoptical_spectroscopy` to cover required or relevant data from Raman scattering experiments. - - -Application Definitions ------------------------ - -We created one application definition: - - :ref:`NXraman`: - A general application definition for Raman measurements. - - - - -Dispersive Material -################### - -A dispersive material is a description for the optical dispersion of materials. -This description may be used to store optical model data from an ellipsometric analysis -(or any other technique) or to build a database of optical constants for optical properties of materials. - -Application Definition ----------------------- - - :ref:`NXdispersive_material`: - An application definition to describe the dispersive properties of a material. - The material may be isotropic, uniaxial or biaxial. Hence, it may contain up - to three dispersive functions or tables. - - - -Base Classes ------------- - -There is a set of base classes for describing a dispersion. - - :ref:`NXdispersion` - This is an umbrella base class for a group of dispersion functions to describe the material. - For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. - If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. - This allows for, e.g. splitting real and imaginary parts and describing them seperately or - adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). - - :ref:`NXdispersion_function` - This dispersion is described by a function and its single and repeated parameter values. - It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` - (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. - - :ref:`NXdispersion_single_parameter` - This denotes a parameter which is used outside the summed part of a dispersion function, - e.g. ``eps_inf`` in the formula example above. - - :ref:`NXdispersion_repeated_parameter` - This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. - ``A`` and ``B`` are repeated parameters in the formula above. - - :ref:`NXdispersion_table` - This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. - -Formula Grammar ---------------- - -Below you find a grammar to which the formula should adhere and which can be used to parse and -evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be -filled with the respective single and repeated params from the stored data. - -.. code-block:: - - ?assignment: "eps" "=" kkr_expression -> eps - | "n" "=" kkr_expression -> n - - ?kkr_expression: expression - | "" "+" "1j" "*" term -> kkr_term - - ?expression: term - | expression "+" term -> add - | expression "-" term -> sub - - ?term: factor - | term "*" factor -> mul - | term "/" factor -> div - - ?factor: power - | power "**" power -> power - - - ?power: "(" expression ")" - | FUNC "(" expression ")" -> func - | "sum" "[" repeated_expression "]" -> sum_expr - | NAME -> single_param_name - | SIGNED_NUMBER -> number - | BUILTIN -> builtin - - ?repeated_expression: repeated_term - | repeated_expression "+" repeated_term -> add - | repeated_expression "-" repeated_term -> sub - - - ?repeated_term: repeated_factor - | repeated_term "*" repeated_factor -> mul - | repeated_term "/" repeated_factor -> div - - ?repeated_factor: repeated_power - | repeated_power "**" repeated_power -> power - - ?repeated_power: "(" repeated_expression ")" - | FUNC "(" repeated_expression ")" -> func - | SIGNED_NUMBER -> number - | NAME -> param_name - | BUILTIN -> builtin - - FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" - BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" - - %import common.CNAME -> NAME - %import common.SIGNED_NUMBER - %import common.WS_INLINE - - %ignore WS_INLINE - diff --git a/manual/source/sed/entry-page.html b/manual/source/sed/entry-page.html deleted file mode 100644 index b7c84946c..000000000 --- a/manual/source/sed/entry-page.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/manual/source/sts-structure.rst b/manual/source/sts-structure.rst deleted file mode 100644 index 26d406c30..000000000 --- a/manual/source/sts-structure.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _Stm-Structure-Fairmat: - -=============================== -Scanning Tunneling Spectroscopy -=============================== - -Scientists of the scanning tunneling spectroscopy community and FAIRmat have worked together to create an application definition and related base classes for documenting scanning tunneling spectroscopy experiments. -This is one community under the large umbrella of scanning (probe) microscopy methods. A status report of these efforts will be reported here: :ref:`Stm-Structure`. diff --git a/manual/source/transport-structure.rst b/manual/source/transport-structure.rst deleted file mode 100644 index 80cbcc1c8..000000000 --- a/manual/source/transport-structure.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _Transport-Structure-Fairmat: - -=================== -Transport phenomena -=================== - -Work of scientists within FAIRmat how to handshake between instrument control software like EPICS and CAMELS using NeXus resulted in an application definition for exemplar temperature dependent IV curve measurements. -IV curve measurements are one example of a large group of so-called transport measurements. The key idea behind these is to monitor one or more observables under controlled environmental conditions and eventual stimuli applied on a sample. - -Many techniques especially used within materials engineering fall into this category and thus could make use of specializations or extensions of NXiv_temp. -Examples include hardness measurements, nanoindentation, resistance, electro-chemical probing, or diffusion. - - :ref:`NXiv_temp`: - Application definition for temperature dependent IV curve measurements. diff --git a/requirements.txt b/requirements.txt index 74c736824..ba1f751d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,6 @@ sphinx-toolbox pytest # Code style and auto-formatting -black>=24.1.1 +black>=22.3 flake8>=4 isort>=5.10 From 9efbfa2ba07d6b08657f2f5b65e58f448366d70d Mon Sep 17 00:00:00 2001 From: sanbrock Date: Thu, 3 Oct 2024 12:14:50 +0200 Subject: [PATCH 062/136] remove unnecessary references from example documentation of definitions groups # Conflicts: # manual/source/classes/contributed_definitions/cgms-structure.rst # manual/source/classes/contributed_definitions/em-structure.rst # manual/source/classes/contributed_definitions/mpes-structure.rst # manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst --- .../classes/applications/apm-structure.rst | 89 +------------- .../classes/applications/em-structure.rst | 99 +--------------- .../classes/applications/mpes-structure.rst | 15 +-- .../optical-spectroscopy-structure.rst | 22 +--- .../classes/base_classes/apm-structure.rst | 109 +----------------- .../classes/base_classes/em-structure.rst | 99 +--------------- .../classes/base_classes/mpes-structure.rst | 34 +----- .../optical-spectroscopy-structure.rst | 23 +--- .../contributed_definitions/apm-structure.rst | 105 +---------------- .../contributed_definitions/em-structure.rst | 2 + .../icme-structure.rst | 23 ---- .../sample-prep-structure.rst | 2 - .../contributed_definitions/sts-structure.rst | 25 ---- 13 files changed, 41 insertions(+), 606 deletions(-) diff --git a/manual/source/classes/applications/apm-structure.rst b/manual/source/classes/applications/apm-structure.rst index dd6c45662..bc99b4a7c 100644 --- a/manual/source/classes/applications/apm-structure.rst +++ b/manual/source/classes/applications/apm-structure.rst @@ -12,6 +12,10 @@ Atom-probe tomography ApmParaprobeAppDef ApmGermanNfdi + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS + + .. _IntroductionApm-APP: Introduction @@ -43,11 +47,11 @@ The following base classes are proposed to support modularizing the storage of p A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. - :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`: + :ref:`NXcoordinate_system_set`: Base classes to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. - :ref:`NXion`: (about to become replaced by :ref:`NXatom_set`) + :ref:`NXion`: A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. For the usage in atom probe research the maximum number of atoms supported building a molecular ion is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with @@ -84,25 +88,6 @@ Microscopy experiments, not only taking into account those performed on commerci data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. -Several base classes were defined to document processing of atom probe data with established algorithms: - - :ref:`NXapm_hit_finding`: - A base class to describe hit finding algorithm. - - :ref:`NXapm_volt_and_bowl`: - A base class to describe the voltage-and-bowl correction. - - :ref:`NXapm_charge_state_analysis`: - A base class to document the resolving of the charge_state. - - :ref:`NXapm_reconstruction`: - A base class to document the tomographic reconstruction algorithm. - - :ref:`NXapm_ranging`: - A base class to document the ranging process. - - :ref:`NXapm_msr`, :ref:`NXapm_sim`: - Respective base classes that serve as templates to compose the :ref:`NXapm` application definition from. These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented to enable reproducible research, if possible even numerical reproducibility of the results, @@ -112,19 +97,6 @@ open-source community software can be modified to use descriptions of these comp A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: - :ref:`NXspatial_filter`: - A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. - This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, - and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. - The primitives are used for defining the shape and extent of a region of interest (ROI). - - :ref:`NXsubsampling_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered via sub-sampling. - - :ref:`NXmatch_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered based on their type or other descriptors like hit multiplicity. The respective research software here is the `paraprobe-toolbox `_ The software is developed by `M. Kühbach et al. `_. @@ -209,8 +181,6 @@ Base classes have been defined to group common pieces of information for each to toolbox. For each tool we define a pair of base classes. One for the configuration (input) side and one for the results (output) side: - :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`, :ref:`NXapm_paraprobe_tool_common`: - Configuration, results, and common parts respectively useful for the application definitions for tools of the paraprobe-toolbox. .. _ApmParaprobeAppDef-APP: @@ -221,51 +191,6 @@ NXapm_paraprobe application definitions are in fact pairs of application definit One for the configuration (input) side and one for the results (output) side. For each tool one such pair is proposed: - :ref:`NXapm_paraprobe_transcoder_config`, :ref:`NXapm_paraprobe_transcoder_results`: - Configuration and the results respectively of the paraprobe-transcoder tool. - Load POS, ePOS, APSuite APT, RRNG, RNG, and NeXus NXapm files. - Store reconstructed positions, ions, and charge states. - - :ref:`NXapm_paraprobe_ranger_config`, :ref:`NXapm_paraprobe_ranger_results`: - Configuration and results respectively of the paraprobe-ranger tool. - Apply ranging definitions and explore possible molecular ions. - Store applied ranging definitions and combinatorial analyses of possible iontypes. - - :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: - Configuration and results respectively of the paraprobe-selector tool. - Defining complex spatial regions-of-interest to filter reconstructed datasets. - Store which points are inside or on the boundary of complex spatial regions-of-interest. - - :ref:`NXapm_paraprobe_surfacer_config`, :ref:`NXapm_paraprobe_surfacer_results`: - Configuration and results respectively of the paraprobe-surfacer tool. - Create a model for the edge of a point cloud via convex hulls, alpha shapes, or alpha-wrappings. - Store triangulated surface meshes of models for the edge of a dataset. - - :ref:`NXapm_paraprobe_distancer_config`, :ref:`NXapm_paraprobe_distancer_results`: - Configuration and results respectively of the paraprobe-distancer tool. - Compute and store analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: - Configuration and results respectively of the paraprobe-tessellator tool. - Compute and store Voronoi cells and properties of these for all ions in a dataset. - - :ref:`NXapm_paraprobe_spatstat_config`, :ref:`NXapm_paraprobe_spatstat_results`: - Configuration and results respectively of the paraprobe-spatstat tool. - Compute spatial statistics on the entire or selected regions of the reconstructed dataset. - - :ref:`NXapm_paraprobe_clusterer_config`, :ref:`NXapm_paraprobe_clusterer_results`: - Configuration and results resepctively of the paraprobe-clusterer tool. - Compute cluster analyses with established machine learning algorithms using CPU or GPUs. - - :ref:`NXapm_paraprobe_nanochem_config`, :ref:`NXapm_paraprobe_nanochem_results`: - Configuration and results resepctively of the paraprobe-nanochem tool. - Compute delocalization, iso-surfaces, analyze 3D objects, composition profiles, and mesh interfaces. - - :ref:`NXapm_paraprobe_intersector_config`, :ref:`NXapm_paraprobe_intersector_results`: - Configuration and results resepctively of the paraprobe-intersector tool. - Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes - in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, - spatial arrangement, and colocation of 3D objects via graph-based techniques. .. _ApmGermanNfdi-APP: @@ -280,5 +205,3 @@ GmbH in Düsseldorf `_ by A. Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: - :ref:`NXapm_compositionspace_config`, :ref:`NXapm_compositionspace_results`: - Configuration and the results respectively of the CompositionSpace tool. diff --git a/manual/source/classes/applications/em-structure.rst b/manual/source/classes/applications/em-structure.rst index 782e27489..045fcdbb3 100644 --- a/manual/source/classes/applications/em-structure.rst +++ b/manual/source/classes/applications/em-structure.rst @@ -10,6 +10,10 @@ Electron microscopy EmBC EmAnalysisClasses + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS + + .. _IntroductionEm-APP: Introduction @@ -47,93 +51,6 @@ Base Classes The following base classes are proposed to support modularizing the storage of pieces of information related to electron microscopy research: - :ref:`NXem_msr`, :ref:`NXem_sim`: - Base classes to distinguish descriptions relevant for an experiment that is performed with a real microscope or a computer simulation of - electron matter interaction. Through these base classes NeXus supports to serialize details of a measurement and a related computer simulation - into one data artifact. - - :ref:`NXidentifier`, :ref:`NXserialized`: - Base classes to support storage of metadata whereby the source of information stored in a NeXus data artifact or class instances can be - documented especially when one does not store all relevant information using NeXus but one would like to refer to a specific other resource - where these pieces of information are stored. - - :ref:`NXebeam_column`: - A base class serving the possibility to group the components relevant for generating - and shaping the electron beam. - - :ref:`NXibeam_column`: - A base class serving the possibility to group the components relevant for generating - and shaping an ion beam of an instrument to offer focused-ion beam (milling) capabilities. - - :ref:`NXcomponent`: - A base class to describe components aka devices to building an instrument like a microscope irrespective whether that is a real one or a simulated one. - - :ref:`NXlens_em`: - A base class to detail an electro-magnetic lens. In practice, an electron microscope has many such lenses. It is possible to specify as many lenses as necessary to represent eventually each single lens of the microscope and thus describe how the lenses are affecting the electron beam. This can offer opportunities for developers of software tools which strive to model the instrument e.g. to create digital twins of the instrument. We understand there is still a way to go with this to arrive there though. Consequently, we suggest to focus first on which details should be collected for a lens as a component so that developers of application definitions can take immediate advantage of this work. - - :ref:`NXdeflector`: - A base class to describe a component to deflect a beam of charged particles. - - :ref:`NXchamber`: - A base class to describe the chamber as a part of the microscope or storage unit - for transferring specimens in between or within an instrument. - - :ref:`NXpump`: - A base class to describe details about pump(s) as components of an electron microscope. - - :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - - :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`, :ref:`NXtransformations`: - Base classes to describe different coordinate systems used and/or to be harmonized - or transformed into one another and respective transformations. - - :ref:`NXcorrector_cs`, :ref:`NXaberration`: - Base classes to describe procedures and values for the calibration of aberrations based on - conventions of different companies active in the field of aberration correction including a base class - to describe details about corrective lens or compound lens devices which reduce - (spherical) aberrations of an electron beam. - - :ref:`NXscanbox_em`: - A base class to represent the component of an electron microscope which realizes a controlled deflection - (and eventually shift, blanking, and/or descanning) of the electron beam to illuminate the specimen in a controlled manner - This base class can be used to document the scan pattern. The base class focuses mostly on the concept idea that there - is a component in a microscope which controls eventually multiple other components such as beam deflectors to achieve deflection - and thus a controlled scanning of the beam over the sample/specimen surface. - - :ref:`NXstage_lab`: - A base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities - which modern stages of electron microscopes typically offer. - - :ref:`NXevent_data_em`: - A base class representing a container to hold time-stamped and microscope-state-annotated - data during a session at an electron microscope. - - :ref:`NXevent_data_em_set`: - A base class to group all :ref:`NXevent_data_em` instances. - - :ref:`NXimage_set`: - Base classes for storing acquisition details for individual images or stacks of images. - - :ref:`NXspectrum_set`: - A base class and specializations comparable to :ref:`NXimage_set` but for storing spectra. - - :ref:`NXinteraction_vol_em`: - A base class to describe details about e.g. the assumed or simulated volume of interaction of the electrons with the specimen. - - :ref:`NXion`: - A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with which all possible isotopes can be described. - - :ref:`NXoptical_system_em`: - A base class to store for now qualitative and quantitative values of frequent interest - which are affected by the interplay of the components and state of an electron microscope. - Examples are the semiconvergence angle or the depth of field and depth of focus, the magnification, or the camera length. - - :ref:`NXpeak`: - A base class to describe peaks mathematically. - - :ref:`NXcircuit`: - A base class to describe a logical unit of at least one integrated circuit. .. _EmAnalysisClasses-APP: @@ -154,11 +71,3 @@ storage (i.e. serialization) using NeXus. More consolidation through the use of NXsubentry classes should be considered in the future. For now we use an approach whereby base classes are combined to reuse vocabulary and a hierarchical organization of pieces of information with specific constraints which are relevant only for specific usage of such data by specific tools used by an eventually smaller circle of users. - :ref:`NXem_method`, :ref:`NXem_ebsd`, :ref:`NXem_eds`, :ref:`NXem_eels`, :ref:`NXem_img`, :ref:`NXem_correlation`: - Base classes with method-specific details especially when it comes to reporting post-processed data within electron microscopy. - - :ref:`NXcrystal_structure`: - A base class to store crystalline phase/structure used for a simulation of diffraction pattern and comparison of these pattern against patterns to support indexing. - - :ref:`NXroi`: - A base class to granularize information collected and relevant for the characterization of a region-of-interest. diff --git a/manual/source/classes/applications/mpes-structure.rst b/manual/source/classes/applications/mpes-structure.rst index 9bc056b1f..ee2c29b92 100644 --- a/manual/source/classes/applications/mpes-structure.rst +++ b/manual/source/classes/applications/mpes-structure.rst @@ -12,7 +12,11 @@ Photoemission & core-level spectroscopy MpesExtendedBC -.. _IntroductionMpes-APP: + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS + + +. _IntroductionMpes-APP: Introduction ############ @@ -30,13 +34,4 @@ Application Definitions :ref:`NXmpes`: A general application definition with minimalistic metadata requirements, apt to describe all photoemission experiments. -:ref:`NXmpes_arpes`: - An application definition for angle-resolved photoemission spectroscopy (ARPES) experiments. - -:ref:`NXxps`: - An application definition for X-ray/ultraviolet photoelectron spectroscopy (XPS/UPS) measurements. - -:ref:`NXarpes`: - An application definition for angle-resolved photoemission spectroscopy (ARPES) experiments. This definition is a legacy - support for older NXarpes experiments. For newer experiments, the user is advised to use :ref:`NXmpes_arpes`:.” diff --git a/manual/source/classes/applications/optical-spectroscopy-structure.rst b/manual/source/classes/applications/optical-spectroscopy-structure.rst index b9f5e11c1..8208bc35b 100644 --- a/manual/source/classes/applications/optical-spectroscopy-structure.rst +++ b/manual/source/classes/applications/optical-spectroscopy-structure.rst @@ -10,6 +10,10 @@ Optical Spectroscopy DispersiveMaterial + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS + + .. _Ellipsometry-APP: Ellipsometry @@ -36,14 +40,10 @@ The application definition contains a minimum of descriptive elements required t Application Definitions ----------------------- - :ref:`NXoptical_spectroscopy`: - A generic application definition for spectroscopy measurements. This includes in particular ellipsometry and Raman spectroscopy measurements, but also other techniques such as photoluminescence, transmission, and reflection measurements. The requirements are: (i) an incident photon beam, (ii) a detector to measure scattered/emitted photons, and (iii) a sample. :ref:`NXellipsometry`: An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - :ref:`NXraman`: - An application definition for Raman spectroscopy measurements. Base Classes @@ -51,14 +51,6 @@ Base Classes This is the set of base classes for describing an optical experiment. - :ref:`NXbeam_device` - Beam devices are used to relate a beam, which has always at least one origin - and at least one destination. - - By referencing the beam devices with each other, a beam path can be - constructed. This can be used for vizualization or beam propery modeling - along the beam path. - :ref:`NXbeam` Beam properties such as intensity, polarization, wavelength or direction. @@ -71,12 +63,6 @@ This is the set of base classes for describing an optical experiment. :ref:`NXmonochromator` A monochromator is often used to energetically disperse the scattered or emitted light. - :ref:`NXlens_opt` - Description of an optical lens. - - :ref:`NXwaveplate` - A waveplate or retarder. - :ref:`NXsensor` Specify external parameters that have influenced the sample such as varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. diff --git a/manual/source/classes/base_classes/apm-structure.rst b/manual/source/classes/base_classes/apm-structure.rst index 79f90e42b..c66f42420 100644 --- a/manual/source/classes/base_classes/apm-structure.rst +++ b/manual/source/classes/base_classes/apm-structure.rst @@ -12,6 +12,10 @@ Atom-probe tomography ApmParaprobeAppDef ApmGermanNfdi + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES + + .. _IntroductionApm-BC: Introduction @@ -43,11 +47,11 @@ The following base classes are proposed to support modularizing the storage of p A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. - :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`: + :ref:`NXcoordinate_system_set`: Base classes to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. - :ref:`NXion`: (about to become replaced by :ref:`NXatom_set`) + :ref:`NXion`: A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. For the usage in atom probe research the maximum number of atoms supported building a molecular ion is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with @@ -57,28 +61,6 @@ The following base classes are proposed to support modularizing the storage of p A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - :ref:`NXpeak`: (about to become complemented by NXpeak_fitting) - A base class to describe peaks mathematically to detail how peaks in - mass-to-charge-state ratio histograms (aka mass spectra) are defined and - labelled as iontypes. - - :ref:`NXpump`: - A base class to describe details about pump(s) used as components of an instrument. - - :ref:`NXpulser_apm`: - A base class to describe the high-voltage and/or laser pulsing capabilities. - - :ref:`NXreflectron`: - A base class to describe a kinetic-energy-sensitive filtering device - for time-of-flight (ToF) mass spectrometry. - - :ref:`NXstage_lab`: - A base class to describe the specimen fixture including the cryo-head. - Nowadays, stages of microscopes represent small-scale laboratory platforms. - Therefore, there is a need to define the characteristics of such stages in more detail, - especially in light of in-situ experiments. Many similarities exists between a stage - in an electron microscope and one in an atom probe instrument. Both offer fixture - functionalities and additional components for applying e.g. stimuli on the specimen. Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named @@ -86,23 +68,6 @@ instances of the :ref:`NXprocess` base class. Several base classes were defined to document processing of atom probe data with established algorithms: - :ref:`NXapm_hit_finding`: - A base class to describe hit finding algorithm. - - :ref:`NXapm_volt_and_bowl`: - A base class to describe the voltage-and-bowl correction. - - :ref:`NXapm_charge_state_analysis`: - A base class to document the resolving of the charge_state. - - :ref:`NXapm_reconstruction`: - A base class to document the tomographic reconstruction algorithm. - - :ref:`NXapm_ranging`: - A base class to document the ranging process. - - :ref:`NXapm_msr`, :ref:`NXapm_sim`: - Respective base classes that serve as templates to compose the :ref:`NXapm` application definition from. These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented to enable reproducible research, if possible even numerical reproducibility of the results, @@ -112,19 +77,6 @@ open-source community software can be modified to use descriptions of these comp A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: - :ref:`NXspatial_filter`: - A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. - This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, - and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. - The primitives are used for defining the shape and extent of a region of interest (ROI). - - :ref:`NXsubsampling_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered via sub-sampling. - - :ref:`NXmatch_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered based on their type or other descriptors like hit multiplicity. The respective research software here is the `paraprobe-toolbox `_ The software is developed by `M. Kühbach et al. `_. @@ -209,8 +161,6 @@ Base classes have been defined to group common pieces of information for each to toolbox. For each tool we define a pair of base classes. One for the configuration (input) side and one for the results (output) side: - :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`, :ref:`NXapm_paraprobe_tool_common`: - Configuration, results, and common parts respectively useful for the application definitions for tools of the paraprobe-toolbox. .. _ApmParaprobeAppDef-BC: @@ -221,51 +171,6 @@ NXapm_paraprobe application definitions are in fact pairs of application definit One for the configuration (input) side and one for the results (output) side. For each tool one such pair is proposed: - :ref:`NXapm_paraprobe_transcoder_config`, :ref:`NXapm_paraprobe_transcoder_results`: - Configuration and the results respectively of the paraprobe-transcoder tool. - Load POS, ePOS, APSuite APT, RRNG, RNG, and NeXus NXapm files. - Store reconstructed positions, ions, and charge states. - - :ref:`NXapm_paraprobe_ranger_config`, :ref:`NXapm_paraprobe_ranger_results`: - Configuration and results respectively of the paraprobe-ranger tool. - Apply ranging definitions and explore possible molecular ions. - Store applied ranging definitions and combinatorial analyses of possible iontypes. - - :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: - Configuration and results respectively of the paraprobe-selector tool. - Defining complex spatial regions-of-interest to filter reconstructed datasets. - Store which points are inside or on the boundary of complex spatial regions-of-interest. - - :ref:`NXapm_paraprobe_surfacer_config`, :ref:`NXapm_paraprobe_surfacer_results`: - Configuration and results respectively of the paraprobe-surfacer tool. - Create a model for the edge of a point cloud via convex hulls, alpha shapes, or alpha-wrappings. - Store triangulated surface meshes of models for the edge of a dataset. - - :ref:`NXapm_paraprobe_distancer_config`, :ref:`NXapm_paraprobe_distancer_results`: - Configuration and results respectively of the paraprobe-distancer tool. - Compute and store analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: - Configuration and results respectively of the paraprobe-tessellator tool. - Compute and store Voronoi cells and properties of these for all ions in a dataset. - - :ref:`NXapm_paraprobe_spatstat_config`, :ref:`NXapm_paraprobe_spatstat_results`: - Configuration and results respectively of the paraprobe-spatstat tool. - Compute spatial statistics on the entire or selected regions of the reconstructed dataset. - - :ref:`NXapm_paraprobe_clusterer_config`, :ref:`NXapm_paraprobe_clusterer_results`: - Configuration and results resepctively of the paraprobe-clusterer tool. - Compute cluster analyses with established machine learning algorithms using CPU or GPUs. - - :ref:`NXapm_paraprobe_nanochem_config`, :ref:`NXapm_paraprobe_nanochem_results`: - Configuration and results resepctively of the paraprobe-nanochem tool. - Compute delocalization, iso-surfaces, analyze 3D objects, composition profiles, and mesh interfaces. - - :ref:`NXapm_paraprobe_intersector_config`, :ref:`NXapm_paraprobe_intersector_results`: - Configuration and results resepctively of the paraprobe-intersector tool. - Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes - in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, - spatial arrangement, and colocation of 3D objects via graph-based techniques. .. _ApmGermanNfdi-BC: @@ -280,5 +185,3 @@ GmbH in Düsseldorf `_ by A. Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: - :ref:`NXapm_compositionspace_config`, :ref:`NXapm_compositionspace_results`: - Configuration and the results respectively of the CompositionSpace tool. diff --git a/manual/source/classes/base_classes/em-structure.rst b/manual/source/classes/base_classes/em-structure.rst index 0c4afec11..167c9c6ff 100644 --- a/manual/source/classes/base_classes/em-structure.rst +++ b/manual/source/classes/base_classes/em-structure.rst @@ -10,6 +10,10 @@ Electron microscopy EmBC EmAnalysisClasses + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES + + .. _IntroductionEm-BC: Introduction @@ -47,93 +51,6 @@ Base Classes The following base classes are proposed to support modularizing the storage of pieces of information related to electron microscopy research: - :ref:`NXem_msr`, :ref:`NXem_sim`: - Base classes to distinguish descriptions relevant for an experiment that is performed with a real microscope or a computer simulation of - electron matter interaction. Through these base classes NeXus supports to serialize details of a measurement and a related computer simulation - into one data artifact. - - :ref:`NXidentifier`, :ref:`NXserialized`: - Base classes to support storage of metadata whereby the source of information stored in a NeXus data artifact or class instances can be - documented especially when one does not store all relevant information using NeXus but one would like to refer to a specific other resource - where these pieces of information are stored. - - :ref:`NXebeam_column`: - A base class serving the possibility to group the components relevant for generating - and shaping the electron beam. - - :ref:`NXibeam_column`: - A base class serving the possibility to group the components relevant for generating - and shaping an ion beam of an instrument to offer focused-ion beam (milling) capabilities. - - :ref:`NXcomponent`: - A base class to describe components aka devices to building an instrument like a microscope irrespective whether that is a real one or a simulated one. - - :ref:`NXlens_em`: - A base class to detail an electro-magnetic lens. In practice, an electron microscope has many such lenses. It is possible to specify as many lenses as necessary to represent eventually each single lens of the microscope and thus describe how the lenses are affecting the electron beam. This can offer opportunities for developers of software tools which strive to model the instrument e.g. to create digital twins of the instrument. We understand there is still a way to go with this to arrive there though. Consequently, we suggest to focus first on which details should be collected for a lens as a component so that developers of application definitions can take immediate advantage of this work. - - :ref:`NXdeflector`: - A base class to describe a component to deflect a beam of charged particles. - - :ref:`NXchamber`: - A base class to describe the chamber as a part of the microscope or storage unit - for transferring specimens in between or within an instrument. - - :ref:`NXpump`: - A base class to describe details about pump(s) as components of an electron microscope. - - :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - - :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`, :ref:`NXtransformations`: - Base classes to describe different coordinate systems used and/or to be harmonized - or transformed into one another and respective transformations. - - :ref:`NXcorrector_cs`, :ref:`NXaberration`: - Base classes to describe procedures and values for the calibration of aberrations based on - conventions of different companies active in the field of aberration correction including a base class - to describe details about corrective lens or compound lens devices which reduce - (spherical) aberrations of an electron beam. - - :ref:`NXscanbox_em`: - A base class to represent the component of an electron microscope which realizes a controlled deflection - (and eventually shift, blanking, and/or descanning) of the electron beam to illuminate the specimen in a controlled manner - This base class can be used to document the scan pattern. The base class focuses mostly on the concept idea that there - is a component in a microscope which controls eventually multiple other components such as beam deflectors to achieve deflection - and thus a controlled scanning of the beam over the sample/specimen surface. - - :ref:`NXstage_lab`: - A base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities - which modern stages of electron microscopes typically offer. - - :ref:`NXevent_data_em`: - A base class representing a container to hold time-stamped and microscope-state-annotated - data during a session at an electron microscope. - - :ref:`NXevent_data_em_set`: - A base class to group all :ref:`NXevent_data_em` instances. - - :ref:`NXimage_set`: - Base classes for storing acquisition details for individual images or stacks of images. - - :ref:`NXspectrum_set`: - A base class and specializations comparable to :ref:`NXimage_set` but for storing spectra. - - :ref:`NXinteraction_vol_em`: - A base class to describe details about e.g. the assumed or simulated volume of interaction of the electrons with the specimen. - - :ref:`NXion`: - A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with which all possible isotopes can be described. - - :ref:`NXoptical_system_em`: - A base class to store for now qualitative and quantitative values of frequent interest - which are affected by the interplay of the components and state of an electron microscope. - Examples are the semiconvergence angle or the depth of field and depth of focus, the magnification, or the camera length. - - :ref:`NXpeak`: - A base class to describe peaks mathematically. - - :ref:`NXcircuit`: - A base class to describe a logical unit of at least one integrated circuit. .. _EmAnalysisClasses-BC: @@ -154,11 +71,3 @@ storage (i.e. serialization) using NeXus. More consolidation through the use of NXsubentry classes should be considered in the future. For now we use an approach whereby base classes are combined to reuse vocabulary and a hierarchical organization of pieces of information with specific constraints which are relevant only for specific usage of such data by specific tools used by an eventually smaller circle of users. - :ref:`NXem_method`, :ref:`NXem_ebsd`, :ref:`NXem_eds`, :ref:`NXem_eels`, :ref:`NXem_img`, :ref:`NXem_correlation`: - Base classes with method-specific details especially when it comes to reporting post-processed data within electron microscopy. - - :ref:`NXcrystal_structure`: - A base class to store crystalline phase/structure used for a simulation of diffraction pattern and comparison of these pattern against patterns to support indexing. - - :ref:`NXroi`: - A base class to granularize information collected and relevant for the characterization of a region-of-interest. diff --git a/manual/source/classes/base_classes/mpes-structure.rst b/manual/source/classes/base_classes/mpes-structure.rst index 4610b5f90..910d09331 100644 --- a/manual/source/classes/base_classes/mpes-structure.rst +++ b/manual/source/classes/base_classes/mpes-structure.rst @@ -12,6 +12,10 @@ Photoemission & core-level spectroscopy MpesExtendedBC + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES + + .. _IntroductionMpes-BC: Introduction @@ -33,29 +37,10 @@ Base Classes :ref:`NXcollectioncolumn`: Base class to describe the set of electronic lenses in the electron collection column (standard, PEEM, momentum-microscope, etc.). - :ref:`NXenergydispersion`: - Base class to describe the energy dispersion sytem (hemispherical, time-of-flight, etc.). - - :ref:`NXspindispersion`: - Base class to describe the set of electronic lenses in the electron collection column. -:ref:`NXmanipulator`: - A base class to describe the complex manipulators used in photoemission experiments, often with > 4 degrees of freedom, - cryogenic cooling and other advanced features. Four base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: - :ref:`NXcalibration`: - A base class to describe the 1D calibration of an axis, with a function mapping a raw data scale to a calibrated scale with the same number of points. - - :ref:`NXdistortion`: - A base class to describe the 2D distortion correction of an axis, with a matrix mapping a raw data image to a undistorted image. - - :ref:`NXregistration`: - A base class to describe the rigid transformations that are applied to an image. May be redundant as they can be described with :ref:`NXtransformations`. - - :ref:`NXprocess_mpes`: - A base class specializing :ref:`NXprocess`, describing events of data processing, reconstruction, or analysis for photoemission-related data. .. _MpesCommonBC-BC: @@ -64,14 +49,3 @@ Common Base Classes There are related base classes that are common to other techniques: - :ref:`NXlens_em`: - A class to describe all types of lenses. Includes electrostatic lenses for electron energy analysers. - - :ref:`NXdeflector` - A class to describe all kinds of deflectors, including electrostatic and magnetostatic deflectors for electron energy analysers. - - :ref:`NXresolution`: - Describes the resolution of a physical quantity, e.g. the resolution of the MPES spectrometer. - - :ref:`NXfit`, :ref:`NXpeak`, :ref:`NXfit_background`, :ref:`NXfit_function`, :ref:`NXfit_parameter`: - Base classes for describing a fit procedure, e.g. a peak fitting in energy space in XPS. \ No newline at end of file diff --git a/manual/source/classes/base_classes/optical-spectroscopy-structure.rst b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst index cf610fc21..2ff2ba1d4 100644 --- a/manual/source/classes/base_classes/optical-spectroscopy-structure.rst +++ b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst @@ -10,6 +10,10 @@ Optical Spectroscopy DispersiveMaterial + +EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES + + .. _Ellipsometry-BC: Ellipsometry @@ -36,14 +40,9 @@ The application definition contains a minimum of descriptive elements required t Application Definitions ----------------------- - :ref:`NXoptical_spectroscopy`: - A generic application definition for spectroscopy measurements. This includes in particular ellipsometry and Raman spectroscopy measurements, but also other techniques such as photoluminescence, transmission, and reflection measurements. The requirements are: (i) an incident photon beam, (ii) a detector to measure scattered/emitted photons, and (iii) a sample. - :ref:`NXellipsometry`: An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - :ref:`NXraman`: - An application definition for Raman spectroscopy measurements. Base Classes @@ -51,14 +50,6 @@ Base Classes This is the set of base classes for describing an optical experiment. - :ref:`NXbeam_device` - Beam devices are used to relate a beam, which has always at least one origin - and at least one destination. - - By referencing the beam devices with each other, a beam path can be - constructed. This can be used for vizualization or beam propery modeling - along the beam path. - :ref:`NXbeam` Beam properties such as intensity, polarization, wavelength or direction. @@ -71,12 +62,6 @@ This is the set of base classes for describing an optical experiment. :ref:`NXmonochromator` A monochromator is often used to energetically disperse the scattered or emitted light. - :ref:`NXlens_opt` - Description of an optical lens. - - :ref:`NXwaveplate` - A waveplate or retarder. - :ref:`NXsensor` Specify external parameters that have influenced the sample such as varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index 2cbeaae4a..4ce8dc1d3 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -43,11 +43,11 @@ The following base classes are proposed to support modularizing the storage of p A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. - :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`: + :ref:`NXcoordinate_system_set`: Base classes to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. - :ref:`NXion`: (about to become replaced by :ref:`NXatom_set`) + :ref:`NXion`: A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. For the usage in atom probe research the maximum number of atoms supported building a molecular ion is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with @@ -57,28 +57,6 @@ The following base classes are proposed to support modularizing the storage of p A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - :ref:`NXpeak`: (about to become complemented by NXpeak_fitting) - A base class to describe peaks mathematically to detail how peaks in - mass-to-charge-state ratio histograms (aka mass spectra) are defined and - labelled as iontypes. - - :ref:`NXpump`: - A base class to describe details about pump(s) used as components of an instrument. - - :ref:`NXpulser_apm`: - A base class to describe the high-voltage and/or laser pulsing capabilities. - - :ref:`NXreflectron`: - A base class to describe a kinetic-energy-sensitive filtering device - for time-of-flight (ToF) mass spectrometry. - - :ref:`NXstage_lab`: - A base class to describe the specimen fixture including the cryo-head. - Nowadays, stages of microscopes represent small-scale laboratory platforms. - Therefore, there is a need to define the characteristics of such stages in more detail, - especially in light of in-situ experiments. Many similarities exists between a stage - in an electron microscope and one in an atom probe instrument. Both offer fixture - functionalities and additional components for applying e.g. stimuli on the specimen. Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named @@ -86,23 +64,6 @@ instances of the :ref:`NXprocess` base class. Several base classes were defined to document processing of atom probe data with established algorithms: - :ref:`NXapm_hit_finding`: - A base class to describe hit finding algorithm. - - :ref:`NXapm_volt_and_bowl`: - A base class to describe the voltage-and-bowl correction. - - :ref:`NXapm_charge_state_analysis`: - A base class to document the resolving of the charge_state. - - :ref:`NXapm_reconstruction`: - A base class to document the tomographic reconstruction algorithm. - - :ref:`NXapm_ranging`: - A base class to document the ranging process. - - :ref:`NXapm_msr`, :ref:`NXapm_sim`: - Respective base classes that serve as templates to compose the :ref:`NXapm` application definition from. These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented to enable reproducible research, if possible even numerical reproducibility of the results, @@ -112,19 +73,6 @@ open-source community software can be modified to use descriptions of these comp A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: - :ref:`NXspatial_filter`: - A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. - This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, - and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. - The primitives are used for defining the shape and extent of a region of interest (ROI). - - :ref:`NXsubsampling_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered via sub-sampling. - - :ref:`NXmatch_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered based on their type or other descriptors like hit multiplicity. The respective research software here is the `paraprobe-toolbox `_ The software is developed by `M. Kühbach et al. `_. @@ -209,8 +157,6 @@ Base classes have been defined to group common pieces of information for each to toolbox. For each tool we define a pair of base classes. One for the configuration (input) side and one for the results (output) side: - :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`, :ref:`NXapm_paraprobe_tool_common`: - Configuration, results, and common parts respectively useful for the application definitions for tools of the paraprobe-toolbox. .. _ApmParaprobeAppDef: @@ -221,51 +167,6 @@ NXapm_paraprobe application definitions are in fact pairs of application definit One for the configuration (input) side and one for the results (output) side. For each tool one such pair is proposed: - :ref:`NXapm_paraprobe_transcoder_config`, :ref:`NXapm_paraprobe_transcoder_results`: - Configuration and the results respectively of the paraprobe-transcoder tool. - Load POS, ePOS, APSuite APT, RRNG, RNG, and NeXus NXapm files. - Store reconstructed positions, ions, and charge states. - - :ref:`NXapm_paraprobe_ranger_config`, :ref:`NXapm_paraprobe_ranger_results`: - Configuration and results respectively of the paraprobe-ranger tool. - Apply ranging definitions and explore possible molecular ions. - Store applied ranging definitions and combinatorial analyses of possible iontypes. - - :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: - Configuration and results respectively of the paraprobe-selector tool. - Defining complex spatial regions-of-interest to filter reconstructed datasets. - Store which points are inside or on the boundary of complex spatial regions-of-interest. - - :ref:`NXapm_paraprobe_surfacer_config`, :ref:`NXapm_paraprobe_surfacer_results`: - Configuration and results respectively of the paraprobe-surfacer tool. - Create a model for the edge of a point cloud via convex hulls, alpha shapes, or alpha-wrappings. - Store triangulated surface meshes of models for the edge of a dataset. - - :ref:`NXapm_paraprobe_distancer_config`, :ref:`NXapm_paraprobe_distancer_results`: - Configuration and results respectively of the paraprobe-distancer tool. - Compute and store analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: - Configuration and results respectively of the paraprobe-tessellator tool. - Compute and store Voronoi cells and properties of these for all ions in a dataset. - - :ref:`NXapm_paraprobe_spatstat_config`, :ref:`NXapm_paraprobe_spatstat_results`: - Configuration and results respectively of the paraprobe-spatstat tool. - Compute spatial statistics on the entire or selected regions of the reconstructed dataset. - - :ref:`NXapm_paraprobe_clusterer_config`, :ref:`NXapm_paraprobe_clusterer_results`: - Configuration and results resepctively of the paraprobe-clusterer tool. - Compute cluster analyses with established machine learning algorithms using CPU or GPUs. - - :ref:`NXapm_paraprobe_nanochem_config`, :ref:`NXapm_paraprobe_nanochem_results`: - Configuration and results resepctively of the paraprobe-nanochem tool. - Compute delocalization, iso-surfaces, analyze 3D objects, composition profiles, and mesh interfaces. - - :ref:`NXapm_paraprobe_intersector_config`, :ref:`NXapm_paraprobe_intersector_results`: - Configuration and results resepctively of the paraprobe-intersector tool. - Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes - in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, - spatial arrangement, and colocation of 3D objects via graph-based techniques. .. _ApmGermanNfdi: @@ -280,5 +181,3 @@ GmbH in Düsseldorf `_ by A. Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: - :ref:`NXapm_compositionspace_config`, :ref:`NXapm_compositionspace_results`: - Configuration and the results respectively of the CompositionSpace tool. diff --git a/manual/source/classes/contributed_definitions/em-structure.rst b/manual/source/classes/contributed_definitions/em-structure.rst index 6b9008ae8..6f011c62f 100644 --- a/manual/source/classes/contributed_definitions/em-structure.rst +++ b/manual/source/classes/contributed_definitions/em-structure.rst @@ -112,6 +112,8 @@ The following base classes are proposed to support modularizing the storage of p :ref:`NXstage_lab`: As it was mentioned for atom probe microscopy, this is a base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities which modern stages of electron microscopes frequently offer. +Method-specific concepts and their usage in application definitions +################################################################### It became clear during the design of the electron-microscopy-specific additions to NeXus that there are sets of pieces of information (data and metadata) which are relevant for a given experiment but have usually only few connections to the detailed description of the workflow of processing these data into knowledge, motivating the granularization of these pieces of information in their own application definition. In fact, one limitation of application definitions in NeXus is that they define a set of constraints on their graph of controlled concepts and terms. If we take for example diffraction experiments with an electron microscope it is usually the case that (diffraction) patterns are collected in the session at the microscope but all scientifically relevant conclusions are drawn later, i.e. through post-processing these data. These numerical and algorithmic steps define computational workflows where data from the application definitions such as NXem are used as input but many additional concepts and constraints may apply without any need for changing constraints on fields or groups of NXem. If we were to modify NXem for these cases, NXem would likely combinatorially diverge as every different combination of required constraints would demand having their own but almost similar application definition. For this reason, we propose to define the following base classes: diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index 68c6f9859..87c2d5766 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -23,26 +23,3 @@ The following application definitions are proposed to support the discussion on materials-engineering-specific data schemas can connect to or be mapped on concepts which are equally modellable with NeXus: - :ref:`NXmicrostructure`: - A base class for documenting a snapshot of a reconstructed microstructure. - - :ref:`NXmicrostructure_imm_config`, :ref:`NXmicrostructure_imm_results`: - A specific example of an application definition for documenting the - configuration and results respectively of a computer simulation with - the legacy microstructure synthesizer developed at the Institut für - Metallkunde und Metallphysik in Aachen. - - :ref:`NXmicrostructure_kanapy_results`: - A specific example of an application definition for documenting the results - of a computer simulation with the kanapy microstructure synthesizer - developed at the ICAMS in Bochum. - - :ref:`NXmicrostructure_score_config`, :ref:`NXmicrostructure_score_results`: - A specific example of an application definition for documenting the - configuration and results respectively of a computer simulation with - the static recrystallization cellular automata model SCORE. - - :ref:`NXmicrostructure_gragles_config`, :ref:`NXmicrostructure_gragles_results`: - A specific example of an application definition for documenting the - configuration and results respectively of a computer simulation with - the grain growth level-set-based model GraGLeS. diff --git a/manual/source/classes/contributed_definitions/sample-prep-structure.rst b/manual/source/classes/contributed_definitions/sample-prep-structure.rst index 39f8249e9..5a2820f22 100644 --- a/manual/source/classes/contributed_definitions/sample-prep-structure.rst +++ b/manual/source/classes/contributed_definitions/sample-prep-structure.rst @@ -16,5 +16,3 @@ Virtually all experiments require a preparation of the sample. As most technique techniques is the key to successful experiments. Unfortunately, the quality of such processes is often difficult to reproduce. Nevertheless, documenting how samples are prepared is relevant. This part of the proposal provides prototypes how descriptions of steps performed by human or robots in a lab could be described using NeXus. - :ref:`NXlab_electro_chemo_mechanical_preparation`, :ref:`NXlab_sample_mounting`: - Prototype application definitions for documenting steps during sample preparation. diff --git a/manual/source/classes/contributed_definitions/sts-structure.rst b/manual/source/classes/contributed_definitions/sts-structure.rst index 42aef5e6e..5c3b18708 100644 --- a/manual/source/classes/contributed_definitions/sts-structure.rst +++ b/manual/source/classes/contributed_definitions/sts-structure.rst @@ -13,35 +13,10 @@ Scanning Tunneling Spectroscopy Application Definition ###################### - :ref:`NXsts`: - An application definition for scanning tunneling spectroscopy experiments. .. _StsNewBC: Base Classes ############ - :ref:`NXamplifier`: - A base class - - :ref:`NXbias_spectroscopy`: - A base class - - :ref:`NXcircuit`: - A base class - - :ref:`NXiv_bias`: - A base class - - :ref:`NXlockin`: - A base class - - :ref:`NXpid`: - A base class - - :ref:`NXpositioner_sts`: - A base class - - :ref:`NXsensor_scan`: - A base class From 49cb14490bd49473213b5fa1e17cad70f63652c2 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Thu, 15 Jun 2023 23:56:12 +0200 Subject: [PATCH 063/136] short tooltip and link # Conflicts: # dev_tools/docs/nxdl.py --- build/manual/source/conf.py | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 build/manual/source/conf.py diff --git a/build/manual/source/conf.py b/build/manual/source/conf.py new file mode 100644 index 000000000..f6d05e297 --- /dev/null +++ b/build/manual/source/conf.py @@ -0,0 +1,100 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +import sys, os, datetime + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'nexus' +author = 'NIAC, https://www.nexusformat.org' +copyright = u'1996-{}, {}'.format(datetime.datetime.now().year, author) +description = u'NeXus: A Common Data Format for Neutron, X-ray, and Muon Science' + +# The full version, including alpha/beta/rc tags +version = u'unknown NXDL version' +release = u'unknown NXDL release' +nxdl_version = open('../../NXDL_VERSION').read().strip() +if nxdl_version is not None: + version = nxdl_version.split('.')[0] + release = nxdl_version + + +# -- General configuration --------------------------------------------------- + +# https://github.com/nexusformat/definitions/issues/659#issuecomment-577438319 +needs_sphinx = '2.3' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinx.ext.githubpages', + 'sphinx.ext.todo', + 'sphinx_tabs.tabs' +] + +# Show `.. todo` directives in the output +# todo_include_todos = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +# html_theme = 'alabaster' +html_theme = 'sphinxdoc' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add extra files +html_extra_path = ['CNAME'] + +html_sidebars = { + '**': [ + 'localtoc.html', + 'relations.html', + 'sourcelink.html', + 'searchbox.html', + 'google_search.html' + ], +} + +# Output file base name for HTML help builder. +htmlhelp_basename = 'NeXusManualdoc' + +# -- Options for Latex output ------------------------------------------------- +latex_elements = { + 'maxlistdepth':25, # some application definitions are deeply nested + 'preamble': r''' + \usepackage{amsbsy} + \usepackage[utf8]{inputenc}''' +} From 5921e9e1b31a01b82e69ff90017edce2d402a910 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Fri, 16 Jun 2023 00:42:05 +0200 Subject: [PATCH 064/136] removing pynxtools as dependecy # Conflicts: # dev_tools/docs/nxdl.py # requirements.txt --- dev_tools/utils/nexus.py | 1394 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1394 insertions(+) create mode 100644 dev_tools/utils/nexus.py diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py new file mode 100644 index 000000000..ac1d8b36c --- /dev/null +++ b/dev_tools/utils/nexus.py @@ -0,0 +1,1394 @@ +# pylint: disable=too-many-lines +"""Read files from different format and print it in a standard NeXus format +""" + +import os +import xml.etree.ElementTree as ET +from functools import lru_cache +from glob import glob +import sys +import logging +import textwrap +import h5py +import click + + +class NxdlAttributeError(Exception): + """An exception for throwing an error when an Nxdl attribute is not found.""" + + +def get_app_defs_names(): + """Returns all the AppDef names without their extension: .nxdl.xml""" + app_def_path_glob = f"{get_nexus_definitions_path()}{os.sep}applications{os.sep}*.nxdl*" + contrib_def_path_glob = (f"{get_nexus_definitions_path()}{os.sep}" + f"contributed_definitions{os.sep}*.nxdl*") + files = sorted(glob(app_def_path_glob)) + sorted(glob(contrib_def_path_glob)) + return [os.path.basename(file).split(".")[0] for file in files] + ["NXroot"] + + +@lru_cache(maxsize=None) +def get_xml_root(file_path): + """Reducing I/O time by caching technique""" + + return ET.parse(file_path).getroot() + + +def get_nexus_definitions_path(): + """Check NEXUS_DEF_PATH variable. +If it is empty, this function is filling it""" + try: # either given by sys env + return os.environ['NEXUS_DEF_PATH'] + except KeyError: # or it should be available locally under the dir 'definitions' + local_dir = os.path.abspath(os.path.dirname(__file__)) + return os.path.join(local_dir, f"..{os.sep}definitions") + + +def get_hdf_root(hdf_node): + """Get the root HDF5 node""" + node = hdf_node + while node.name != '/': + node = node.parent + return node + + +def get_hdf_parent(hdf_info): + """Get the parent of an hdf_node in an hdf_info""" + if 'hdf_path' not in hdf_info: + return hdf_info['hdf_node'].parent + node = get_hdf_root(hdf_info['hdf_node']) if 'hdf_root' not in hdf_info \ + else hdf_info['hdf_root'] + for child_name in hdf_info['hdf_path'].split('/'): + node = node[child_name] + return node + + +def get_parent_path(hdf_name): + """Get parent path""" + return '/'.join(hdf_name.split('/')[:-1]) + + +def get_hdf_info_parent(hdf_info): + """Get the hdf_info for the parent of an hdf_node in an hdf_info""" + if 'hdf_path' not in hdf_info: + return {'hdf_node': hdf_info['hdf_node'].parent} + node = get_hdf_root(hdf_info['hdf_node']) if 'hdf_root' not in hdf_info \ + else hdf_info['hdf_root'] + for child_name in hdf_info['hdf_path'].split('/')[1:-1]: + node = node[child_name] + return {'hdf_node': node, 'hdf_path': get_parent_path(hdf_info['hdf_path'])} + + +def get_nx_class_path(hdf_info): + """Get the full path of an HDF5 node using nexus classes +in case of a field, end with the field name""" + hdf_node = hdf_info['hdf_node'] + if hdf_node.name == '/': + return '' + if isinstance(hdf_node, h5py.Group): + return get_nx_class_path(get_hdf_info_parent(hdf_info)) + '/' + \ + (hdf_node.attrs['NX_class'] if 'NX_class' in hdf_node.attrs.keys() else + hdf_node.name.split('/')[-1]) + if isinstance(hdf_node, h5py.Dataset): + return get_nx_class_path( + get_hdf_info_parent(hdf_info)) + '/' + hdf_node.name.split('/')[-1] + return '' + + +def get_nxdl_entry(hdf_info): + """Get the nxdl application definition for an HDF5 node""" + entry = hdf_info + while isinstance(entry['hdf_node'], h5py.Dataset) or \ + 'NX_class' not in entry['hdf_node'].attrs.keys() or \ + entry['hdf_node'].attrs['NX_class'] != 'NXentry': + entry = get_hdf_info_parent(entry) + if entry['hdf_node'].name == '/': + return 'NO NXentry found' + try: + nxdef = entry['hdf_node']['definition'][()] + return nxdef.decode() + except KeyError: # 'NO Definition referenced' + return "NXentry" + + +def get_nx_class(nxdl_elem): + """Get the nexus class for a NXDL node""" + if 'category' in nxdl_elem.attrib.keys(): + return None + try: + return nxdl_elem.attrib['type'] + except KeyError: + return 'NX_CHAR' + + +def get_nx_namefit(hdf_name, name, name_any=False): + """Checks if an HDF5 node name corresponds to a child of the NXDL element +uppercase letters in front can be replaced by arbitraty name, but +uppercase to lowercase match is preferred, +so such match is counted as a measure of the fit""" + if name == hdf_name: + return len(name) * 2 + # count leading capitals + counting = 0 + while counting < len(name) and name[counting].upper() == name[counting]: + counting += 1 + if name_any or counting == len(name) or \ + (counting > 0 and hdf_name.endswith(name[counting:])): # if potential fit + # count the matching chars + fit = 0 + for i in range(min(counting, len(hdf_name))): + if hdf_name[i].upper() == name[i]: + fit += 1 + else: + break + if fit == min(counting, len(hdf_name)): # accept only full fits as better fits + return fit + return 0 + return -1 # no fit + + +def get_nx_classes(): + """Read base classes from the NeXus definition folder. +Check each file in base_classes, applications, contributed_definitions. +If its category attribute is 'base', then it is added to the list. """ + base_classes = sorted(glob(os.path.join(get_nexus_definitions_path(), + 'base_classes', '*.nxdl.xml'))) + applications = sorted(glob(os.path.join(get_nexus_definitions_path(), + 'applications', '*.nxdl.xml'))) + contributed = sorted(glob(os.path.join(get_nexus_definitions_path(), + 'contributed_definitions', '*.nxdl.xml'))) + nx_clss = [] + for nexus_file in base_classes + applications + contributed: + root = get_xml_root(nexus_file) + if root.attrib['category'] == 'base': + nx_clss.append(str(nexus_file[nexus_file.rindex(os.sep) + 1:])[:-9]) + nx_clss = sorted(nx_clss) + return nx_clss + + +def get_nx_units(): + """Read unit kinds from the NeXus definition/nxdlTypes.xsd file""" + filepath = f"{get_nexus_definitions_path()}{os.sep}nxdlTypes.xsd" + root = get_xml_root(filepath) + units_and_type_list = [] + for child in root: + for i in child.attrib.values(): + units_and_type_list.append(i) + flag = False + for line in units_and_type_list: + if line == 'anyUnitsAttr': + flag = True + nx_units = [] + elif 'NX' in line and flag is True: + nx_units.append(line) + elif line == 'primitiveType': + flag = False + else: + pass + return nx_units + + +def get_nx_attribute_type(): + """Read attribute types from the NeXus definition/nxdlTypes.xsd file""" + filepath = get_nexus_definitions_path() + '/nxdlTypes.xsd' + root = get_xml_root(filepath) + units_and_type_list = [] + for child in root: + for i in child.attrib.values(): + units_and_type_list.append(i) + flag = False + for line in units_and_type_list: + if line == 'primitiveType': + flag = True + nx_types = [] + elif 'NX' in line and flag is True: + nx_types.append(line) + elif line == 'anyUnitsAttr': + flag = False + else: + pass + return nx_types + + +def get_node_name(node): + '''Node - xml node. Returns html documentation name. + Either as specified by the 'name' or taken from the type (nx_class). + Note that if only class name is available, the NX prefix is removed and + the string is converted to UPPER case.''' + if 'name' in node.attrib.keys(): + name = node.attrib['name'] + else: + name = node.attrib['type'] + if name.startswith('NX'): + name = name[2:].upper() + return name + + +def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): + """Checks if an HDF5 node name corresponds to a child of the NXDL element +uppercase letters in front can be replaced by arbitraty name, but +uppercase to lowercase match is preferred""" + if class_type and get_nx_class(child) != class_type: + return False + act_htmlname = get_node_name(child) + chk_name = hdf_name or name + if act_htmlname == chk_name: + return True + if not hdf_name: # search for name fits is only allowed for hdf_nodes + return False + try: # check if nameType allows different name + name_any = bool(child.attrib['nameType'] == "any") + except KeyError: + name_any = False + params = [act_htmlname, chk_name, name_any, nxdl_elem, child, name] + return belongs_to_capital(params) + + +def belongs_to_capital(params): + """Checking continues for Upper case""" + (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params + # or starts with capital and no reserved words used + if (name_any or 'A' <= act_htmlname[0] <= 'Z') and \ + name != 'doc' and name != 'enumeration': + fit = get_nx_namefit(chk_name, act_htmlname, name_any) # check if name fits + if fit < 0: + return False + for child2 in nxdl_elem: + if get_local_name_from_xml(child) != \ + get_local_name_from_xml(child2) or get_node_name(child2) == act_htmlname: + continue + # check if the name of another sibling fits better + name_any2 = "nameType" in child2.attrib.keys() and child2.attrib["nameType"] == "any" + fit2 = get_nx_namefit(chk_name, get_node_name(child2), name_any2) + if fit2 > fit: + return False + # accept this fit + return True + return False + + +def get_local_name_from_xml(element): + """Helper function to extract the element tag without the namespace.""" + return element.tag[element.tag.rindex("}") + 1:] + + +def get_own_nxdl_child_reserved_elements(child, name, nxdl_elem): + """checking reserved elements, like doc, enumeration""" + if get_local_name_from_xml(child) == 'doc' and name == 'doc': + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/doc') + return child + if get_local_name_from_xml(child) == 'enumeration' and name == 'enumeration': + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/enumeration') + return child + return False + + +def get_own_nxdl_child_base_types(child, class_type, nxdl_elem, name, hdf_name): + """checking base types of group, field,m attribute""" + if get_local_name_from_xml(child) == 'group': + if (class_type is None or (class_type and get_nx_class(child) == class_type)) and \ + belongs_to(nxdl_elem, child, name, class_type, hdf_name): + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + return child + if get_local_name_from_xml(child) == 'field' and \ + belongs_to(nxdl_elem, child, name, None, hdf_name): + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + return child + if get_local_name_from_xml(child) == 'attribute' and \ + belongs_to(nxdl_elem, child, name, None, hdf_name): + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + return child + return False + + +def get_own_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None): + """Checks if an NXDL child node fits to the specific name (either nxdl or hdf) + name - nxdl name + class_type - nxdl type or hdf classname (for groups, it is obligatory) + hdf_name - hdf name""" + for child in nxdl_elem: + if 'name' in child.attrib and child.attrib['name'] == name: + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + return child + for child in nxdl_elem: + if "name" in child.attrib and child.attrib["name"] == name: + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + return child + + for child in nxdl_elem: + result = get_own_nxdl_child_reserved_elements(child, name, nxdl_elem) + if result is not False: + return result + if nexus_type and get_local_name_from_xml(child) != nexus_type: + continue + result = get_own_nxdl_child_base_types(child, class_type, nxdl_elem, name, hdf_name) + if result is not False: + return result + return None + + +def find_definition_file(bc_name): + """find the nxdl file corresponding to the name. + Note that it first checks in contributed and goes beyond only if no contributed found""" + bc_filename = None + for nxdl_folder in ['contributed_definitions', 'base_classes', 'applications']: + if os.path.exists(f"{get_nexus_definitions_path()}{os.sep}" + f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml"): + bc_filename = f"{get_nexus_definitions_path()}{os.sep}" \ + f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml" + break + return bc_filename + + +def get_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None, go_base=True): # pylint: disable=too-many-arguments + """Get the NXDL child node corresponding to a specific name +(e.g. of an HDF5 node,or of a documentation) note that if child is not found in application +definition, it also checks for the base classes""" + # search for possible fits for hdf_nodes : skipped + # only exact hits are returned when searching an nxdl child + own_child = get_own_nxdl_child(nxdl_elem, name, class_type, hdf_name, nexus_type) + if own_child is not None: + return own_child + if not go_base: + return None + bc_name = get_nx_class(nxdl_elem) # check in the base class, app def or contributed + if bc_name[2] == '_': # filter primitive types + return None + if bc_name == "group": # Check if it is the root element. Then send to NXroot.nxdl.xml + bc_name = "NXroot" + bc_filename = find_definition_file(bc_name) + if not bc_filename: + raise ValueError('nxdl file not found in definitions folder!') + bc_obj = ET.parse(bc_filename).getroot() + bc_obj.set('nxdlbase', bc_filename) + if 'category' in bc_obj.attrib: + bc_obj.set('nxdlbase_class', bc_obj.attrib['category']) + bc_obj.set('nxdlpath', '') + return get_own_nxdl_child(bc_obj, name, class_type, hdf_name, nexus_type) + + +def get_required_string(nxdl_elem): + """Check for being REQUIRED, RECOMMENDED, OPTIONAL, NOT IN SCHEMA""" + if nxdl_elem is None: + return "<>" + is_optional = 'optional' in nxdl_elem.attrib.keys() \ + and nxdl_elem.attrib['optional'] == "true" + is_minoccurs = 'minOccurs' in nxdl_elem.attrib.keys() \ + and nxdl_elem.attrib['minOccurs'] == "0" + is_recommended = 'recommended' in nxdl_elem.attrib.keys() \ + and nxdl_elem.attrib['recommended'] == "true" + + if is_recommended: + return "<>" + if is_optional or is_minoccurs: + return "<>" + # default optionality: in BASE CLASSES is true; in APPLICATIONS is false + try: + if nxdl_elem.get('nxdlbase_class') == 'base': + return "<>" + except TypeError: + return "<>" + return "<>" + + +def chk_nxdataaxis_v2(hdf_node, name, logger): + """Check if dataset is an axis""" + own_signal = hdf_node.attrs.get('signal') # check for being a Signal + if own_signal is str and own_signal == "1": + logger.debug("Dataset referenced (v2) as NXdata SIGNAL") + own_axes = hdf_node.attrs.get('axes') # check for being an axis + if own_axes is str: + axes = own_axes.split(':') + for i in len(axes): + if axes[i] and name == axes[i]: + logger.debug("Dataset referenced (v2) as NXdata AXIS #%d", i) + return None + ownpaxis = hdf_node.attrs.get('primary') + own_axis = hdf_node.attrs.get('axis') + if own_axis is int: + # also convention v1 + if ownpaxis is int and ownpaxis == 1: + logger.debug("Dataset referenced (v2) as NXdata AXIS #%d", own_axis - 1) + else: + logger.debug( + "Dataset referenced (v2) as NXdata (primary/alternative) AXIS #%d", own_axis - 1) + return None + + +def chk_nxdataaxis(hdf_node, name, logger): + """NEXUS Data Plotting Standard v3: new version from 2014""" + if not isinstance(hdf_node, h5py.Dataset): # check if it is a field in an NXdata node + return None + parent = hdf_node.parent + if not parent or (parent and not parent.attrs.get('NX_class') == "NXdata"): + return None + signal = parent.attrs.get('signal') # chk for Signal + if signal and name == signal: + logger.debug("Dataset referenced as NXdata SIGNAL") + return None + axes = parent.attrs.get('axes') # check for default Axes + if axes is str: + if name == axes: + logger.debug("Dataset referenced as NXdata AXIS") + return None + elif axes is not None: + for i, j in enumerate(axes): + if name == j: + indices = parent.attrs.get(j + '_indices') + if indices is int: + logger.debug(f"Dataset referenced as NXdata AXIS #{indices}") + else: + logger.debug(f"Dataset referenced as NXdata AXIS #{i}") + return None + indices = parent.attrs.get(name + '_indices') # check for alternative Axes + if indices is int: + logger.debug(f"Dataset referenced as NXdata alternative AXIS #{indices}") + return chk_nxdataaxis_v2(hdf_node, name, logger) # check for older conventions + + +# below there are some functions used in get_nxdl_doc function: +def write_doc_string(logger, doc, attr): + """Simple function that prints a line in the logger if doc exists""" + if doc: + logger.debug("@" + attr + ' [NX_CHAR]') + return logger, doc, attr + + +def try_find_units(logger, elem, nxdl_path, doc, attr): + """Try to find if units is defined inside the field in the NXDL element, + otherwise try to find if units is defined as a child of the NXDL element.""" + try: # try to find if units is defined inside the field in the NXDL element + unit = elem.attrib[attr] + if doc: + logger.debug(get_node_concept_path(elem) + "@" + attr + ' [' + unit + ']') + elem = None + nxdl_path.append(attr) + except KeyError: # otherwise try to find if units is defined as a child of the NXDL element + orig_elem = elem + elem = get_nxdl_child(elem, attr, nexus_type='attribute') + if elem is not None: + if doc: + logger.debug(get_node_concept_path(orig_elem) + + "@" + attr + ' - [' + get_nx_class(elem) + ']') + nxdl_path.append(elem) + else: # if no units category were defined in NXDL: + if doc: + logger.debug(get_node_concept_path(orig_elem) + + "@" + attr + " - REQUIRED, but undefined unit category") + nxdl_path.append(attr) + return logger, elem, nxdl_path, doc, attr + + +def check_attr_name_nxdl(param): + """Check for ATTRIBUTENAME_units in NXDL (normal). +If not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE +is in the SCHEMA, but no units category were defined. """ + (logger, elem, nxdl_path, doc, attr, req_str) = param + orig_elem = elem + elem2 = get_nxdl_child(elem, attr, nexus_type='attribute') + if elem2 is not None: # check for ATTRIBUTENAME_units in NXDL (normal) + elem = elem2 + if doc: + logger.debug(get_node_concept_path(orig_elem) + + "@" + attr + ' - [' + get_nx_class(elem) + ']') + nxdl_path.append(elem) + else: + # if not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE + # is in the SCHEMA, but no units category were defined + elem2 = get_nxdl_child(elem, attr[:-6], nexus_type='attribute') + if elem2 is not None: + req_str = '<>' + if doc: + logger.debug(get_node_concept_path(orig_elem) + + "@" + attr + " - RECOMMENDED, but undefined unit category") + nxdl_path.append(attr) + else: # otherwise: NOT IN SCHEMA + elem = elem2 + if doc: + logger.debug(get_node_concept_path(orig_elem) + "@" + attr + " - IS NOT IN SCHEMA") + return logger, elem, nxdl_path, doc, attr, req_str + + +def try_find_default(logger, orig_elem, elem, nxdl_path, doc, attr): # pylint: disable=too-many-arguments + """Try to find if default is defined as a child of the NXDL element """ + if elem is not None: + if doc: + logger.debug(get_node_concept_path(orig_elem) + + "@" + attr + ' - [' + get_nx_class(elem) + ']') + nxdl_path.append(elem) + else: # if no default category were defined in NXDL: + if doc: + logger.debug(get_node_concept_path(orig_elem) + "@" + attr + " - [NX_CHAR]") + nxdl_path.append(attr) + return logger, elem, nxdl_path, doc, attr + + +def other_attrs(logger, orig_elem, elem, nxdl_path, doc, attr): # pylint: disable=too-many-arguments + """Handle remaining attributes """ + if elem is not None: + if doc: + logger.debug(get_node_concept_path(orig_elem) + + "@" + attr + ' - [' + get_nx_class(elem) + ']') + nxdl_path.append(elem) + else: + if doc: + logger.debug(get_node_concept_path(orig_elem) + "@" + attr + " - IS NOT IN SCHEMA") + return logger, elem, nxdl_path, doc, attr + + +def check_deprecation_enum_axis(variables, doc, elist, attr, hdf_node): + """Check for several attributes. - deprecation - enums - nxdataaxis """ + logger, elem, path = variables + dep_str = elem.attrib.get('deprecated') # check for deprecation + if dep_str: + if doc: + logger.debug("DEPRECATED - " + dep_str) + for base_elem in elist if not attr else [elem]: # check for enums + sdoc = get_nxdl_child(base_elem, 'enumeration', go_base=False) + if sdoc is not None: + if doc: + logger.debug("enumeration (" + get_node_concept_path(base_elem) + "):") + for item in sdoc: + if get_local_name_from_xml(item) == 'item': + if doc: + logger.debug("-> " + item.attrib['value']) + chk_nxdataaxis(hdf_node, path.split('/')[-1], logger) # look for NXdata reference (axes/signal) + for base_elem in elist if not attr else [elem]: # check for doc + sdoc = get_nxdl_child(base_elem, 'doc', go_base=False) + if doc: + logger.debug("documentation (" + get_node_concept_path(base_elem) + "):") + logger.debug(sdoc.text if sdoc is not None else "") + return logger, elem, path, doc, elist, attr, hdf_node + + +def get_node_concept_path(elem): + """get the short version of nxdlbase:nxdlpath""" + return str(elem.get('nxdlbase').split('/')[-1] + ":" + elem.get('nxdlpath')) + + +def get_nxdl_attr_doc( # pylint: disable=too-many-arguments,too-many-locals + elem, elist, attr, hdf_node, logger, doc, nxdl_path, req_str, path, hdf_info): + """Get nxdl documentation for an attribute""" + new_elem = [] + old_elem = elem + for elem_index, act_elem1 in enumerate(elist): + act_elem = act_elem1 + # NX_class is a compulsory attribute for groups in a nexus file + # which should match the type of the corresponding NXDL element + if attr == 'NX_class' and not isinstance(hdf_node, h5py.Dataset) and elem_index == 0: + elem = None + logger, doc, attr = write_doc_string(logger, doc, attr) + new_elem = elem + break + # units category is a compulsory attribute for any fields + if attr == 'units' and isinstance(hdf_node, h5py.Dataset): + req_str = "<>" + logger, act_elem, nxdl_path, doc, attr = try_find_units(logger, + act_elem, + nxdl_path, + doc, + attr) + # units for attributes can be given as ATTRIBUTENAME_units + elif attr.endswith('_units'): + logger, act_elem, nxdl_path, doc, attr, req_str = check_attr_name_nxdl((logger, + act_elem, + nxdl_path, + doc, + attr, + req_str)) + # default is allowed for groups + elif attr == 'default' and not isinstance(hdf_node, h5py.Dataset): + req_str = "<>" + # try to find if default is defined as a child of the NXDL element + act_elem = get_nxdl_child(act_elem, attr, nexus_type='attribute', go_base=False) + logger, act_elem, nxdl_path, doc, attr = try_find_default(logger, + act_elem1, + act_elem, + nxdl_path, + doc, + attr) + else: # other attributes + act_elem = get_nxdl_child(act_elem, attr, nexus_type='attribute', go_base=False) + if act_elem is not None: + logger, act_elem, nxdl_path, doc, attr = \ + other_attrs(logger, act_elem1, act_elem, nxdl_path, doc, attr) + if act_elem is not None: + new_elem.append(act_elem) + if req_str is None: + req_str = get_required_string(act_elem) # check for being required + if doc: + logger.debug(req_str) + variables = [logger, act_elem, path] + logger, elem, path, doc, elist, attr, hdf_node = check_deprecation_enum_axis(variables, + doc, + elist, + attr, + hdf_node) + elem = old_elem + if req_str is None and doc: + if attr != 'NX_class': + logger.debug("@" + attr + " - IS NOT IN SCHEMA") + logger.debug("") + return (req_str, get_nxdl_entry(hdf_info), nxdl_path) + + +def get_nxdl_doc(hdf_info, logger, doc, attr=False): + """Get nxdl documentation for an HDF5 node (or its attribute)""" + hdf_node = hdf_info['hdf_node'] + # new way: retrieve multiple inherited base classes + (class_path, nxdl_path, elist) = \ + get_inherited_nodes(None, nx_name=get_nxdl_entry(hdf_info), hdf_node=hdf_node, + hdf_path=hdf_info['hdf_path'] if 'hdf_path' in hdf_info else None, + hdf_root=hdf_info['hdf_root'] if 'hdf_root' in hdf_info else None) + elem = elist[0] if class_path and elist else None + if doc: + logger.debug("classpath: " + str(class_path)) + logger.debug("NOT IN SCHEMA" if elem is None else + "classes:\n" + "\n".join + (get_node_concept_path(e) for e in elist)) + # old solution with a single elem instead of using elist + path = get_nx_class_path(hdf_info) + req_str = None + if elem is None: + if doc: + logger.debug("") + return ('None', None, None) + if attr: + return get_nxdl_attr_doc(elem, elist, attr, hdf_node, logger, doc, nxdl_path, + req_str, path, hdf_info) + req_str = get_required_string(elem) # check for being required + if doc: + logger.debug(req_str) + variables = [logger, elem, path] + logger, elem, path, doc, elist, attr, hdf_node = check_deprecation_enum_axis(variables, + doc, + elist, + attr, + hdf_node) + return (req_str, get_nxdl_entry(hdf_info), nxdl_path) + + +def get_doc(node, ntype, nxhtml, nxpath): + """Get documentation""" + # URL for html documentation + anchor = '' + for n_item in nxpath: + anchor += n_item.lower() + "-" + anchor = ('https://manual.nexusformat.org/classes/', + nxhtml + "#" + anchor.replace('_', '-') + ntype) + if not ntype: + anchor = anchor[:-1] + doc = "" # RST documentation from the field 'doc' + doc_field = node.find("doc") + if doc_field is not None: + doc = doc_field.text + (index, enums) = get_enums(node) # enums + if index: + enum_str = "\n " + ("Possible values:" + if len(enums.split(',')) > 1 + else "Obligatory value:") + "\n " + enums + "\n" + else: + enum_str = "" + return anchor, doc + enum_str + + +def print_doc(node, ntype, level, nxhtml, nxpath): + """Print documentation""" + anchor, doc = get_doc(node, ntype, nxhtml, nxpath) + print(" " * (level + 1) + anchor) + preferred_width = 80 + level * 2 + wrapper = textwrap.TextWrapper(initial_indent=' ' * (level + 1), width=preferred_width, + subsequent_indent=' ' * (level + 1), expand_tabs=False, + tabsize=0) + if doc is not None: + for par in doc.split('\n'): + print(wrapper.fill(par)) + + +def get_namespace(element): + """Extracts the namespace for elements in the NXDL""" + return element.tag[element.tag.index("{"):element.tag.rindex("}") + 1] + + +def get_enums(node): + """Makes list of enumerations, if node contains any. + Returns comma separated STRING of enumeration values, if there are enum tag, + otherwise empty string.""" + # collect item values from enumeration tag, if any + namespace = get_namespace(node) + enums = [] + for enumeration in node.findall(f"{namespace}enumeration"): + for item in enumeration.findall(f"{namespace}item"): + enums.append(item.attrib["value"]) + enums = ','.join(enums) + if enums != "": + return (True, '[' + enums + ']') + return (False, "") # if there is no enumeration tag, returns empty string + + +def add_base_classes(elist, nx_name=None, elem: ET.Element = None): + """Add the base classes corresponding to the last eleme in elist to the list. Note that if +elist is empty, a nxdl file with the name of nx_name or a rather room elem is used if provided""" + if elist and nx_name is None: + nx_name = get_nx_class(elist[-1]) + # to support recursive defintions, like NXsample in NXsample, the following test is removed + # if elist and nx_name and f"{nx_name}.nxdl.xml" in (e.get('nxdlbase') for e in elist): + # return + if elem is None: + if not nx_name: + return + nxdl_file_path = find_definition_file(nx_name) + if nxdl_file_path is None: + nxdl_file_path = f"{nx_name}.nxdl.xml" + elem = ET.parse(nxdl_file_path).getroot() + elem.set('nxdlbase', nxdl_file_path) + else: + elem.set('nxdlbase', '') + if 'category' in elem.attrib: + elem.set('nxdlbase_class', elem.attrib['category']) + elem.set('nxdlpath', '') + elist.append(elem) + # add inherited base class + if 'extends' in elem.attrib and elem.attrib['extends'] != 'NXobject': + add_base_classes(elist, elem.attrib['extends']) + else: + add_base_classes(elist) + + +def set_nxdlpath(child, nxdl_elem): + """ + Setting up child nxdlbase, nxdlpath and nxdlbase_class from nxdl_element. + """ + if nxdl_elem.get('nxdlbase'): + child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) + child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + return child + + +def get_direct_child(nxdl_elem, html_name): + """ returns the child of nxdl_elem which has a name + corresponding to the the html documentation name html_name""" + for child in nxdl_elem: + if get_local_name_from_xml(child) in ('group', 'field', 'attribute') and \ + html_name == get_node_name(child): + decorated_child = set_nxdlpath(child, nxdl_elem) + return decorated_child + return None + + +def get_field_child(nxdl_elem, html_name): + """ returns the child of nxdl_elem which has a name + corresponding to the html documentation name html_name""" + data_child = None + for child in nxdl_elem: + if get_local_name_from_xml(child) != 'field': + continue + if get_node_name(child) == html_name: + data_child = set_nxdlpath(child, nxdl_elem) + break + return data_child + + +def get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name): + """ returns the child of an NXdata nxdl_elem which has a name + corresponding to the hdf_name""" + nxdata = hdf_node.parent + signals = [] + if 'signal' in nxdata.attrs.keys(): + signals.append(nxdata.attrs.get("signal")) + if "auxiliary_signals" in nxdata.attrs.keys(): + for aux_signal in nxdata.attrs.get("auxiliary_signals"): + signals.append(aux_signal) + data_child = get_field_child(nxdl_elem, 'DATA') + data_error_child = get_field_child(nxdl_elem, 'FIELDNAME_errors') + for signal in signals: + if signal == hdf_name: + return (data_child, 100) + if hdf_name.endswith('_errors') and signal == hdf_name[:-7]: + return (data_error_child, 100) + axes = [] + if "axes" in nxdata.attrs.keys(): + for axis in nxdata.attrs.get("axes"): + axes.append(axis) + axis_child = get_field_child(nxdl_elem, 'AXISNAME') + for axis in axes: + if axis == hdf_name: + return (axis_child, 100) + return (None, 0) + + +def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): + """ returns the child of nxdl_elem which has a name + corresponding to the the html documentation name html_name""" + bestfit = -1 + bestchild = None + if 'name' in nxdl_elem.attrib.keys() and nxdl_elem.attrib['name'] == 'NXdata' and \ + hdf_node is not None and hdf_node.parent is not None and \ + hdf_node.parent.attrs.get('NX_class') == 'NXdata': + (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) + if fnd_child is not None: + return (fnd_child, fit) + for child in nxdl_elem: + fit = -2 + if get_local_name_from_xml(child) == nexus_type and \ + (nexus_type != 'group' or get_nx_class(child) == hdf_class_name): + name_any = "nameType" in nxdl_elem.attrib.keys() and \ + nxdl_elem.attrib["nameType"] == "any" + fit = get_nx_namefit(hdf_name, get_node_name(child), name_any) + if fit > bestfit: + bestfit = fit + bestchild = set_nxdlpath(child, nxdl_elem) + return (bestchild, bestfit) + + +def walk_elist(elist, html_name): + """Handle elist from low priority inheritance classes to higher""" + for ind in range(len(elist) - 1, -1, -1): + child = get_direct_child(elist[ind], html_name) + if child is None: + # check for names fitting to a superclas definition + main_child = None + for potential_direct_parent in elist: + main_child = get_direct_child(potential_direct_parent, html_name) + if main_child is not None: + (fitting_child, _) = get_best_child(elist[ind], None, html_name, + get_nx_class(main_child), + get_local_name_from_xml(main_child)) + if fitting_child is not None: + child = fitting_child + break + elist[ind] = child + if elist[ind] is None: + del elist[ind] + continue + # override: remove low priority inheritance classes if class_type is overriden + if len(elist) > ind + 1 and get_nx_class(elist[ind]) != get_nx_class(elist[ind + 1]): + del elist[ind + 1:] + # add new base class(es) if new element brings such (and not a primitive type) + if len(elist) == ind + 1 and get_nx_class(elist[ind])[0:3] != 'NX_': + add_base_classes(elist) + return elist, html_name + + +def helper_get_inherited_nodes(hdf_info2, elist, pind, attr): + """find the best fitting name in all children""" + hdf_path, hdf_node, hdf_class_path = hdf_info2 + hdf_name = hdf_path[pind] + hdf_class_name = hdf_class_path[pind] + if pind < len(hdf_path) - (2 if attr else 1): + act_nexus_type = 'group' + elif pind == len(hdf_path) - 1 and attr: + act_nexus_type = 'attribute' + else: + act_nexus_type = 'field' if isinstance(hdf_node, h5py.Dataset) else 'group' + # find the best fitting name in all children + bestfit = -1 + html_name = None + for ind in range(len(elist) - 1, -1, -1): + newelem, fit = get_best_child(elist[ind], + hdf_node, + hdf_name, + hdf_class_name, + act_nexus_type) + if fit >= bestfit and newelem is not None: + html_name = get_node_name(newelem) + return hdf_path, hdf_node, hdf_class_path, elist, pind, attr, html_name + + +def get_hdf_path(hdf_info): + """Get the hdf_path from an hdf_info""" + if 'hdf_path' in hdf_info: + return hdf_info['hdf_path'].split('/')[1:] + return hdf_info['hdf_node'].name.split('/')[1:] + + +@lru_cache(maxsize=None) +def get_inherited_nodes(nxdl_path: str = None, # pylint: disable=too-many-arguments,too-many-locals + nx_name: str = None, elem: ET.Element = None, + hdf_node=None, hdf_path=None, hdf_root=None, attr=False): + """Returns a list of ET.Element for the given path.""" + # let us start with the given definition file + elist = [] # type: ignore[var-annotated] + add_base_classes(elist, nx_name, elem) + nxdl_elem_path = [elist[0]] + + class_path = [] # type: ignore[var-annotated] + if hdf_node is not None: + hdf_info = {'hdf_node': hdf_node} + if hdf_path: + hdf_info['hdf_path'] = hdf_path + if hdf_root: + hdf_root['hdf_root'] = hdf_root + hdf_node = hdf_info['hdf_node'] + hdf_path = get_hdf_path(hdf_info) + hdf_class_path = get_nx_class_path(hdf_info).split('/')[1:] + if attr: + hdf_path.append(attr) + hdf_class_path.append(attr) + path = hdf_path + else: + html_path = nxdl_path.split('/')[1:] + path = html_path + for pind in range(len(path)): + if hdf_node is not None: + hdf_info2 = [hdf_path, hdf_node, hdf_class_path] + [hdf_path, hdf_node, hdf_class_path, elist, + pind, attr, html_name] = helper_get_inherited_nodes(hdf_info2, elist, + pind, attr) + if html_name is None: # return if NOT IN SCHEMA + return (class_path, nxdl_elem_path, None) + else: + html_name = html_path[pind] + elist, html_name = walk_elist(elist, html_name) + if elist: + class_path.append(get_nx_class(elist[0])) + nxdl_elem_path.append(elist[0]) + return (class_path, nxdl_elem_path, elist) + + +def get_node_at_nxdl_path(nxdl_path: str = None, + nx_name: str = None, elem: ET.Element = None, + exc: bool = True): + """Returns an ET.Element for the given path. + This function either takes the name for the NeXus Application Definition + we are looking for or the root elem from a previously loaded NXDL file + and finds the corresponding XML element with the needed attributes.""" + try: + (class_path, nxdlpath, elist) = get_inherited_nodes(nxdl_path, nx_name, elem) + except ValueError as value_error: + if exc: + raise NxdlAttributeError(f"Attributes were not found for {nxdl_path}. " + "Please check this entry in the template dictionary.") \ + from value_error + return None + if class_path and nxdlpath and elist: + elem = elist[0] + else: + elem = None + if exc: + raise NxdlAttributeError(f"Attributes were not found for {nxdl_path}. " + "Please check this entry in the template dictionary.") + return elem + + +def process_node(hdf_node, hdf_path, parser, logger, doc=True): + """Processes an hdf5 node. +- it logs the node found and also checks for its attributes +- retrieves the corresponding nxdl documentation +TODO: +- follow variants +- NOMAD parser: store in NOMAD """ + hdf_info = {'hdf_path': hdf_path, 'hdf_node': hdf_node} + if isinstance(hdf_node, h5py.Dataset): + logger.debug(f'===== FIELD (/{hdf_path}): {hdf_node}') + val = str(hdf_node[()]).split('\n') if len(hdf_node.shape) <= 1 else str( + hdf_node[0]).split('\n') + logger.debug(f'value: {val[0]} {"..." if len(val) > 1 else ""}') + else: + logger.debug( + f"===== GROUP (/{hdf_path} " + f"[{get_nxdl_entry(hdf_info)}" + f"::{get_nx_class_path(hdf_info)}]): {hdf_node}" + ) + (req_str, nxdef, nxdl_path) = get_nxdl_doc(hdf_info, logger, doc) + if parser is not None and isinstance(hdf_node, h5py.Dataset): + parser({"hdf_info": hdf_info, + "nxdef": nxdef, + "nxdl_path": nxdl_path, + "val": val, + "logger": logger}) + for key, value in hdf_node.attrs.items(): + logger.debug(f'===== ATTRS (/{hdf_path}@{key})') + val = str(value).split('\n') + logger.debug(f'value: {val[0]} {"..." if len(val) > 1 else ""}') + (req_str, nxdef, nxdl_path) = \ + get_nxdl_doc(hdf_info, logger, doc, attr=key) + if ( + parser is not None + and req_str is not None + and 'NOT IN SCHEMA' not in req_str + and 'None' not in req_str + ): + parser({"hdf_info": hdf_info, + "nxdef": nxdef, + "nxdl_path": nxdl_path, + "val": val, + "logger": logger}, attr=key) + + +def logger_auxiliary_signal(logger, nxdata): + """Handle the presence of auxiliary signal""" + aux = nxdata.attrs.get('auxiliary_signals') + if aux is not None: + if isinstance(aux, str): + aux = [aux] + for asig in aux: + logger.debug(f'Further auxiliary signal has been identified: {asig}') + return logger + + +def print_default_plotable_header(logger): + """Print a three-lines header""" + logger.debug('========================') + logger.debug('=== Default Plotable ===') + logger.debug('========================') + + +def get_default_plotable(root, logger): + """Get default plotable""" + print_default_plotable_header(logger) + # v3 from 2014 + # nxentry + nxentry = None + default_nxentry_group_name = root.attrs.get("default") + if default_nxentry_group_name: + try: + nxentry = root[default_nxentry_group_name] + except KeyError: + nxentry = None + if not nxentry: + nxentry = entry_helper(root) + if not nxentry: + logger.debug('No NXentry has been found') + return + logger.debug('') + logger.debug('NXentry has been identified: ' + nxentry.name) + # nxdata + nxdata = None + nxgroup = nxentry + default_group_name = nxgroup.attrs.get("default") + while default_group_name: + try: + nxgroup = nxgroup[default_group_name] + default_group_name = nxgroup.attrs.get("default") + except KeyError: + pass + if nxgroup == nxentry: + nxdata = nxdata_helper(nxentry) + else: + nxdata = nxgroup + if not nxdata: + logger.debug('No NXdata group has been found') + return + logger.debug('') + logger.debug('NXdata group has been identified: ' + nxdata.name) + process_node(nxdata, nxdata.name, None, logger, False) + # signal + signal = None + signal_dataset_name = nxdata.attrs.get("signal") + try: + signal = nxdata[signal_dataset_name] + except (TypeError, KeyError): + signal = None + if not signal: + signal = signal_helper(nxdata) + if not signal: + logger.debug('No Signal has been found') + return + logger.debug('') + logger.debug('Signal has been identified: ' + signal.name) + process_node(signal, signal.name, None, logger, False) + logger = logger_auxiliary_signal(logger, nxdata) # check auxiliary_signals + dim = len(signal.shape) + axes = [] # axes + axis_helper(dim, nxdata, signal, axes, logger) + + +def entry_helper(root): + """Check entry related data""" + nxentries = [] + for key in root.keys(): + if isinstance(root[key], h5py.Group) and root[key].attrs.get('NX_class') and \ + root[key].attrs['NX_class'] == "NXentry": + nxentries.append(root[key]) + if len(nxentries) >= 1: + return nxentries[0] + return None + + +def nxdata_helper(nxentry): + """Check if nxentry hdf5 object has a NX_class and, if it contains NXdata, +return its value""" + lnxdata = [] + for key in nxentry.keys(): + if isinstance(nxentry[key], h5py.Group) and nxentry[key].attrs.get('NX_class') and \ + nxentry[key].attrs['NX_class'] == "NXdata": + lnxdata.append(nxentry[key]) + if len(lnxdata) >= 1: + return lnxdata[0] + return None + + +def signal_helper(nxdata): + """Check signal related data""" + signals = [] + for key in nxdata.keys(): + if isinstance(nxdata[key], h5py.Dataset): + signals.append(nxdata[key]) + if len(signals) == 1: # v3: as there was no selection given, only 1 data field shall exists + return signals[0] + if len(signals) > 1: # v2: select the one with an attribute signal="1" attribute + for sig in signals: + if sig.attrs.get("signal") and sig.attrs.get("signal") is str and \ + sig.attrs.get("signal") == "1": + return sig + return None + + +def find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list): + """Finds axis that have defined dimensions""" + # find those with attribute axis= actual dimension number + lax = [] + for key in nxdata.keys(): + if isinstance(nxdata[key], h5py.Dataset): + try: + if nxdata[key].attrs['axis'] == a_item + 1: + lax.append(nxdata[key]) + except KeyError: + pass + if len(lax) == 1: + ax_list.append(lax[0]) + # if there are more alternatives, prioritise the one with an attribute primary="1" + elif len(lax) > 1: + for sax in lax: + if sax.attrs.get('primary') and sax.attrs.get('primary') == 1: + ax_list.insert(0, sax) + else: + ax_list.append(sax) + + +def get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list): + """Gets either single or multiple axes from the NXDL""" + try: + if isinstance(ax_datasets, str): # single axis is defined + # explicite definition of dimension number + ind = nxdata.attrs.get(ax_datasets + '_indices') + if ind and ind is int: + if ind == a_item: + ax_list.append(nxdata[ax_datasets]) + elif a_item == 0: # positional determination of the dimension number + ax_list.append(nxdata[ax_datasets]) + else: # multiple axes are listed + # explicite definition of dimension number + for aax in ax_datasets: + ind = nxdata.attrs.get(aax + '_indices') + if ind and isinstance(ind, int): + if ind == a_item: + ax_list.append(nxdata[aax]) + if not ax_list: # positional determination of the dimension number + ax_list.append(nxdata[ax_datasets[a_item]]) + except KeyError: + pass + return ax_list + + +def axis_helper(dim, nxdata, signal, axes, logger): + """Check axis related data""" + for a_item in range(dim): + ax_list = [] + ax_datasets = nxdata.attrs.get("axes") # primary axes listed in attribute axes + ax_list = get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list) + for attr in nxdata.attrs.keys(): # check for corresponding AXISNAME_indices + if attr.endswith('_indices') and nxdata.attrs[attr] == a_item and \ + nxdata[attr.split('_indices')[0]] not in ax_list: + ax_list.append(nxdata[attr.split('_indices')[0]]) + # v2 # check for ':' separated axes defined in Signal + if not ax_list: + try: + ax_datasets = signal.attrs.get("axes").split(':') + ax_list.append(nxdata[ax_datasets[a_item]]) + except (KeyError, AttributeError): + pass + if not ax_list: # check for axis/primary specifications + find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list) + axes.append(ax_list) + logger.debug('') + logger.debug( + f'For Axis #{a_item}, {len(ax_list)} axes have been identified: {str(ax_list)}' + ) + + +def get_all_is_a_rel_from_hdf_node(hdf_node, hdf_path): + """Return list of nxdl concept paths for a nxdl element which corresponds to + hdf node. + """ + hdf_info = {'hdf_path': hdf_path, 'hdf_node': hdf_node} + (_, _, elist) = \ + get_inherited_nodes(None, nx_name=get_nxdl_entry(hdf_info), hdf_node=hdf_node, + hdf_path=hdf_info['hdf_path'] if 'hdf_path' in hdf_info else None, + hdf_root=hdf_info['hdf_root'] if 'hdf_root' in hdf_info else None) + return elist + + +def hdf_node_to_self_concept_path(hdf_info, logger): + """ Get concept or nxdl path from given hdf_node. + """ + # The bellow logger is for deactivatine unnecessary debug message above + if logger is None: + logger = logging.getLogger(__name__) + logger.setLevel(logging.INFO) + (_, _, nxdl_path) = get_nxdl_doc(hdf_info, logger, None) + con_path = '' + if nxdl_path: + for nd_ in nxdl_path: + con_path = con_path + '/' + get_node_name(nd_) + return con_path + + +class HandleNexus: + """documentation""" + def __init__(self, logger, nexus_file, + d_inq_nd=None, c_inq_nd=None): + self.logger = logger + local_dir = os.path.abspath(os.path.dirname(__file__)) + + self.input_file_name = nexus_file if nexus_file is not None else \ + os.path.join(local_dir, '../../tests/data/nexus/201805_WSe2_arpes.nxs') + self.parser = None + self.in_file = None + self.d_inq_nd = d_inq_nd + self.c_inq_nd = c_inq_nd + # Aggregating hdf path corresponds to concept query node + self.hdf_path_list_for_c_inq_nd = [] + + def visit_node(self, hdf_name, hdf_node): + """Function called by h5py that iterates on each node of hdf5file. + It allows h5py visititems function to visit nodes.""" + if self.d_inq_nd is None and self.c_inq_nd is None: + process_node(hdf_node, '/' + hdf_name, self.parser, self.logger) + elif (self.d_inq_nd is not None + and hdf_name in (self.d_inq_nd, self.d_inq_nd[1:])): + process_node(hdf_node, '/' + hdf_name, self.parser, self.logger) + elif self.c_inq_nd is not None: + attributed_concept = self.c_inq_nd.split('@') + attr = attributed_concept[1] if len(attributed_concept) > 1 else None + elist = get_all_is_a_rel_from_hdf_node(hdf_node, '/' + hdf_name) + if elist is None: + return + fnd_superclass = False + fnd_superclass_attr = False + for elem in reversed(elist): + tmp_path = elem.get('nxdlbase').split('.nxdl')[0] + con_path = '/NX' + tmp_path.split('NX')[-1] + elem.get('nxdlpath') + if fnd_superclass or con_path == attributed_concept[0]: + fnd_superclass = True + if attr is None: + self.hdf_path_list_for_c_inq_nd.append(hdf_name) + break + for attribute in hdf_node.attrs.keys(): + attr_concept = get_nxdl_child(elem, attribute, nexus_type='attribute', + go_base=False) + if attr_concept is not None and \ + attr_concept.get('nxdlpath').endswith(attr): + fnd_superclass_attr = True + con_path = '/NX' + tmp_path.split('NX')[-1] \ + + attr_concept.get('nxdlpath') + self.hdf_path_list_for_c_inq_nd.append(hdf_name + "@" + attribute) + break + if fnd_superclass_attr: + break + + def not_yet_visited(self, root, name): + """checking if a new node has already been visited in its path""" + path = name.split('/') + for i in range(1, len(path)): + act_path = '/'.join(path[:i]) + # print(act_path+' - '+name) + if root['/' + act_path] == root['/' + name]: + return False + return True + + def full_visit(self, root, hdf_node, name, func): + """visiting recursivly all children, but avoiding endless cycles""" + # print(name) + if len(name) > 0: + func(name, hdf_node) + if isinstance(hdf_node, h5py.Group): + for ch_name, child in hdf_node.items(): + full_name = ch_name if len(name) == 0 else name + '/' + ch_name + if self.not_yet_visited(root, full_name): + self.full_visit(root, child, full_name, func) + + def process_nexus_master_file(self, parser): + """Process a nexus master file by processing all its nodes and their attributes""" + self.parser = parser + self.in_file = h5py.File( + self.input_file_name[0] + if isinstance(self.input_file_name, list) + else self.input_file_name, 'r' + ) + self.full_visit(self.in_file, self.in_file, '', self.visit_node) + if self.d_inq_nd is None and self.c_inq_nd is None: + get_default_plotable(self.in_file, self.logger) + # To log the provided concept and concepts founded + if self.c_inq_nd is not None: + for hdf_path in self.hdf_path_list_for_c_inq_nd: + self.logger.info(hdf_path) + self.in_file.close() + + +@click.command() +@click.option( + '-f', + '--nexus-file', + required=False, + default=None, + help=('NeXus file with extension .nxs to learn NeXus different concept' + ' documentation and concept.') +) +@click.option( + '-d', + '--documentation', + required=False, + default=None, + help=("Definition path in nexus output (.nxs) file. Returns debug" + "log relavent with that definition path. Example: /entry/data/delays") +) +@click.option( + '-c', + '--concept', + required=False, + default=None, + help=("Concept path from application definition file (.nxdl,xml). Finds out" + "all the available concept definition (IS-A realation) for rendered" + "concept path. Example: /NXarpes/ENTRY/INSTRUMENT/analyser") +) +def main(nexus_file, documentation, concept): + """The main function to call when used as a script.""" + logging_format = "%(levelname)s: %(message)s" + stdout_handler = logging.StreamHandler(sys.stdout) + stdout_handler.setLevel(logging.DEBUG) + logging.basicConfig(level=logging.INFO, format=logging_format, handlers=[stdout_handler]) + logger = logging.getLogger(__name__) + logger.addHandler(stdout_handler) + logger.setLevel(logging.DEBUG) + logger.propagate = False + if documentation and concept: + raise ValueError("Only one option either documentation (-d) or is_a relation " + "with a concept (-c) can be requested.") + nexus_helper = HandleNexus(logger, nexus_file, + d_inq_nd=documentation, + c_inq_nd=concept) + nexus_helper.process_nexus_master_file(None) + + +if __name__ == '__main__': + main() # pylint: disable=no-value-for-parameter From 131b764c51a21b0e5658e65c6a122d3a263bd36f Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Fri, 16 Jun 2023 00:45:17 +0200 Subject: [PATCH 065/136] linting --- dev_tools/utils/nexus.py | 1069 +++++++++++++++++++++++--------------- 1 file changed, 645 insertions(+), 424 deletions(-) diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py index ac1d8b36c..7b09e30f3 100644 --- a/dev_tools/utils/nexus.py +++ b/dev_tools/utils/nexus.py @@ -19,9 +19,13 @@ class NxdlAttributeError(Exception): def get_app_defs_names(): """Returns all the AppDef names without their extension: .nxdl.xml""" - app_def_path_glob = f"{get_nexus_definitions_path()}{os.sep}applications{os.sep}*.nxdl*" - contrib_def_path_glob = (f"{get_nexus_definitions_path()}{os.sep}" - f"contributed_definitions{os.sep}*.nxdl*") + app_def_path_glob = ( + f"{get_nexus_definitions_path()}{os.sep}applications{os.sep}*.nxdl*" + ) + contrib_def_path_glob = ( + f"{get_nexus_definitions_path()}{os.sep}" + f"contributed_definitions{os.sep}*.nxdl*" + ) files = sorted(glob(app_def_path_glob)) + sorted(glob(contrib_def_path_glob)) return [os.path.basename(file).split(".")[0] for file in files] + ["NXroot"] @@ -35,9 +39,9 @@ def get_xml_root(file_path): def get_nexus_definitions_path(): """Check NEXUS_DEF_PATH variable. -If it is empty, this function is filling it""" + If it is empty, this function is filling it""" try: # either given by sys env - return os.environ['NEXUS_DEF_PATH'] + return os.environ["NEXUS_DEF_PATH"] except KeyError: # or it should be available locally under the dir 'definitions' local_dir = os.path.abspath(os.path.dirname(__file__)) return os.path.join(local_dir, f"..{os.sep}definitions") @@ -46,65 +50,82 @@ def get_nexus_definitions_path(): def get_hdf_root(hdf_node): """Get the root HDF5 node""" node = hdf_node - while node.name != '/': + while node.name != "/": node = node.parent return node def get_hdf_parent(hdf_info): """Get the parent of an hdf_node in an hdf_info""" - if 'hdf_path' not in hdf_info: - return hdf_info['hdf_node'].parent - node = get_hdf_root(hdf_info['hdf_node']) if 'hdf_root' not in hdf_info \ - else hdf_info['hdf_root'] - for child_name in hdf_info['hdf_path'].split('/'): + if "hdf_path" not in hdf_info: + return hdf_info["hdf_node"].parent + node = ( + get_hdf_root(hdf_info["hdf_node"]) + if "hdf_root" not in hdf_info + else hdf_info["hdf_root"] + ) + for child_name in hdf_info["hdf_path"].split("/"): node = node[child_name] return node def get_parent_path(hdf_name): """Get parent path""" - return '/'.join(hdf_name.split('/')[:-1]) + return "/".join(hdf_name.split("/")[:-1]) def get_hdf_info_parent(hdf_info): """Get the hdf_info for the parent of an hdf_node in an hdf_info""" - if 'hdf_path' not in hdf_info: - return {'hdf_node': hdf_info['hdf_node'].parent} - node = get_hdf_root(hdf_info['hdf_node']) if 'hdf_root' not in hdf_info \ - else hdf_info['hdf_root'] - for child_name in hdf_info['hdf_path'].split('/')[1:-1]: + if "hdf_path" not in hdf_info: + return {"hdf_node": hdf_info["hdf_node"].parent} + node = ( + get_hdf_root(hdf_info["hdf_node"]) + if "hdf_root" not in hdf_info + else hdf_info["hdf_root"] + ) + for child_name in hdf_info["hdf_path"].split("/")[1:-1]: node = node[child_name] - return {'hdf_node': node, 'hdf_path': get_parent_path(hdf_info['hdf_path'])} + return {"hdf_node": node, "hdf_path": get_parent_path(hdf_info["hdf_path"])} def get_nx_class_path(hdf_info): """Get the full path of an HDF5 node using nexus classes -in case of a field, end with the field name""" - hdf_node = hdf_info['hdf_node'] - if hdf_node.name == '/': - return '' + in case of a field, end with the field name""" + hdf_node = hdf_info["hdf_node"] + if hdf_node.name == "/": + return "" if isinstance(hdf_node, h5py.Group): - return get_nx_class_path(get_hdf_info_parent(hdf_info)) + '/' + \ - (hdf_node.attrs['NX_class'] if 'NX_class' in hdf_node.attrs.keys() else - hdf_node.name.split('/')[-1]) + return ( + get_nx_class_path(get_hdf_info_parent(hdf_info)) + + "/" + + ( + hdf_node.attrs["NX_class"] + if "NX_class" in hdf_node.attrs.keys() + else hdf_node.name.split("/")[-1] + ) + ) if isinstance(hdf_node, h5py.Dataset): - return get_nx_class_path( - get_hdf_info_parent(hdf_info)) + '/' + hdf_node.name.split('/')[-1] - return '' + return ( + get_nx_class_path(get_hdf_info_parent(hdf_info)) + + "/" + + hdf_node.name.split("/")[-1] + ) + return "" def get_nxdl_entry(hdf_info): """Get the nxdl application definition for an HDF5 node""" entry = hdf_info - while isinstance(entry['hdf_node'], h5py.Dataset) or \ - 'NX_class' not in entry['hdf_node'].attrs.keys() or \ - entry['hdf_node'].attrs['NX_class'] != 'NXentry': + while ( + isinstance(entry["hdf_node"], h5py.Dataset) + or "NX_class" not in entry["hdf_node"].attrs.keys() + or entry["hdf_node"].attrs["NX_class"] != "NXentry" + ): entry = get_hdf_info_parent(entry) - if entry['hdf_node'].name == '/': - return 'NO NXentry found' + if entry["hdf_node"].name == "/": + return "NO NXentry found" try: - nxdef = entry['hdf_node']['definition'][()] + nxdef = entry["hdf_node"]["definition"][()] return nxdef.decode() except KeyError: # 'NO Definition referenced' return "NXentry" @@ -112,27 +133,30 @@ def get_nxdl_entry(hdf_info): def get_nx_class(nxdl_elem): """Get the nexus class for a NXDL node""" - if 'category' in nxdl_elem.attrib.keys(): + if "category" in nxdl_elem.attrib.keys(): return None try: - return nxdl_elem.attrib['type'] + return nxdl_elem.attrib["type"] except KeyError: - return 'NX_CHAR' + return "NX_CHAR" def get_nx_namefit(hdf_name, name, name_any=False): """Checks if an HDF5 node name corresponds to a child of the NXDL element -uppercase letters in front can be replaced by arbitraty name, but -uppercase to lowercase match is preferred, -so such match is counted as a measure of the fit""" + uppercase letters in front can be replaced by arbitraty name, but + uppercase to lowercase match is preferred, + so such match is counted as a measure of the fit""" if name == hdf_name: return len(name) * 2 # count leading capitals counting = 0 while counting < len(name) and name[counting].upper() == name[counting]: counting += 1 - if name_any or counting == len(name) or \ - (counting > 0 and hdf_name.endswith(name[counting:])): # if potential fit + if ( + name_any + or counting == len(name) + or (counting > 0 and hdf_name.endswith(name[counting:])) + ): # if potential fit # count the matching chars fit = 0 for i in range(min(counting, len(hdf_name))): @@ -143,24 +167,31 @@ def get_nx_namefit(hdf_name, name, name_any=False): if fit == min(counting, len(hdf_name)): # accept only full fits as better fits return fit return 0 - return -1 # no fit + return -1 # no fit def get_nx_classes(): """Read base classes from the NeXus definition folder. -Check each file in base_classes, applications, contributed_definitions. -If its category attribute is 'base', then it is added to the list. """ - base_classes = sorted(glob(os.path.join(get_nexus_definitions_path(), - 'base_classes', '*.nxdl.xml'))) - applications = sorted(glob(os.path.join(get_nexus_definitions_path(), - 'applications', '*.nxdl.xml'))) - contributed = sorted(glob(os.path.join(get_nexus_definitions_path(), - 'contributed_definitions', '*.nxdl.xml'))) + Check each file in base_classes, applications, contributed_definitions. + If its category attribute is 'base', then it is added to the list.""" + base_classes = sorted( + glob(os.path.join(get_nexus_definitions_path(), "base_classes", "*.nxdl.xml")) + ) + applications = sorted( + glob(os.path.join(get_nexus_definitions_path(), "applications", "*.nxdl.xml")) + ) + contributed = sorted( + glob( + os.path.join( + get_nexus_definitions_path(), "contributed_definitions", "*.nxdl.xml" + ) + ) + ) nx_clss = [] for nexus_file in base_classes + applications + contributed: root = get_xml_root(nexus_file) - if root.attrib['category'] == 'base': - nx_clss.append(str(nexus_file[nexus_file.rindex(os.sep) + 1:])[:-9]) + if root.attrib["category"] == "base": + nx_clss.append(str(nexus_file[nexus_file.rindex(os.sep) + 1 :])[:-9]) nx_clss = sorted(nx_clss) return nx_clss @@ -175,12 +206,12 @@ def get_nx_units(): units_and_type_list.append(i) flag = False for line in units_and_type_list: - if line == 'anyUnitsAttr': + if line == "anyUnitsAttr": flag = True nx_units = [] - elif 'NX' in line and flag is True: + elif "NX" in line and flag is True: nx_units.append(line) - elif line == 'primitiveType': + elif line == "primitiveType": flag = False else: pass @@ -189,7 +220,7 @@ def get_nx_units(): def get_nx_attribute_type(): """Read attribute types from the NeXus definition/nxdlTypes.xsd file""" - filepath = get_nexus_definitions_path() + '/nxdlTypes.xsd' + filepath = get_nexus_definitions_path() + "/nxdlTypes.xsd" root = get_xml_root(filepath) units_and_type_list = [] for child in root: @@ -197,12 +228,12 @@ def get_nx_attribute_type(): units_and_type_list.append(i) flag = False for line in units_and_type_list: - if line == 'primitiveType': + if line == "primitiveType": flag = True nx_types = [] - elif 'NX' in line and flag is True: + elif "NX" in line and flag is True: nx_types.append(line) - elif line == 'anyUnitsAttr': + elif line == "anyUnitsAttr": flag = False else: pass @@ -210,23 +241,23 @@ def get_nx_attribute_type(): def get_node_name(node): - '''Node - xml node. Returns html documentation name. + """Node - xml node. Returns html documentation name. Either as specified by the 'name' or taken from the type (nx_class). Note that if only class name is available, the NX prefix is removed and - the string is converted to UPPER case.''' - if 'name' in node.attrib.keys(): - name = node.attrib['name'] + the string is converted to UPPER case.""" + if "name" in node.attrib.keys(): + name = node.attrib["name"] else: - name = node.attrib['type'] - if name.startswith('NX'): + name = node.attrib["type"] + if name.startswith("NX"): name = name[2:].upper() return name def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): """Checks if an HDF5 node name corresponds to a child of the NXDL element -uppercase letters in front can be replaced by arbitraty name, but -uppercase to lowercase match is preferred""" + uppercase letters in front can be replaced by arbitraty name, but + uppercase to lowercase match is preferred""" if class_type and get_nx_class(child) != class_type: return False act_htmlname = get_node_name(child) @@ -236,7 +267,7 @@ def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): if not hdf_name: # search for name fits is only allowed for hdf_nodes return False try: # check if nameType allows different name - name_any = bool(child.attrib['nameType'] == "any") + name_any = bool(child.attrib["nameType"] == "any") except KeyError: name_any = False params = [act_htmlname, chk_name, name_any, nxdl_elem, child, name] @@ -247,17 +278,25 @@ def belongs_to_capital(params): """Checking continues for Upper case""" (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params # or starts with capital and no reserved words used - if (name_any or 'A' <= act_htmlname[0] <= 'Z') and \ - name != 'doc' and name != 'enumeration': + if ( + (name_any or "A" <= act_htmlname[0] <= "Z") + and name != "doc" + and name != "enumeration" + ): fit = get_nx_namefit(chk_name, act_htmlname, name_any) # check if name fits if fit < 0: return False for child2 in nxdl_elem: - if get_local_name_from_xml(child) != \ - get_local_name_from_xml(child2) or get_node_name(child2) == act_htmlname: + if ( + get_local_name_from_xml(child) != get_local_name_from_xml(child2) + or get_node_name(child2) == act_htmlname + ): continue # check if the name of another sibling fits better - name_any2 = "nameType" in child2.attrib.keys() and child2.attrib["nameType"] == "any" + name_any2 = ( + "nameType" in child2.attrib.keys() + and child2.attrib["nameType"] == "any" + ) fit2 = get_nx_namefit(chk_name, get_node_name(child2), name_any2) if fit2 > fit: return False @@ -268,68 +307,81 @@ def belongs_to_capital(params): def get_local_name_from_xml(element): """Helper function to extract the element tag without the namespace.""" - return element.tag[element.tag.rindex("}") + 1:] + return element.tag[element.tag.rindex("}") + 1 :] def get_own_nxdl_child_reserved_elements(child, name, nxdl_elem): """checking reserved elements, like doc, enumeration""" - if get_local_name_from_xml(child) == 'doc' and name == 'doc': - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/doc') + if get_local_name_from_xml(child) == "doc" and name == "doc": + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set("nxdlpath", nxdl_elem.get("nxdlpath") + "/doc") return child - if get_local_name_from_xml(child) == 'enumeration' and name == 'enumeration': - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/enumeration') + if get_local_name_from_xml(child) == "enumeration" and name == "enumeration": + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set("nxdlpath", nxdl_elem.get("nxdlpath") + "/enumeration") return child return False def get_own_nxdl_child_base_types(child, class_type, nxdl_elem, name, hdf_name): """checking base types of group, field,m attribute""" - if get_local_name_from_xml(child) == 'group': - if (class_type is None or (class_type and get_nx_class(child) == class_type)) and \ - belongs_to(nxdl_elem, child, name, class_type, hdf_name): - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + if get_local_name_from_xml(child) == "group": + if ( + class_type is None or (class_type and get_nx_class(child) == class_type) + ) and belongs_to(nxdl_elem, child, name, class_type, hdf_name): + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set( + "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) + ) return child - if get_local_name_from_xml(child) == 'field' and \ - belongs_to(nxdl_elem, child, name, None, hdf_name): - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + if get_local_name_from_xml(child) == "field" and belongs_to( + nxdl_elem, child, name, None, hdf_name + ): + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set( + "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) + ) return child - if get_local_name_from_xml(child) == 'attribute' and \ - belongs_to(nxdl_elem, child, name, None, hdf_name): - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + if get_local_name_from_xml(child) == "attribute" and belongs_to( + nxdl_elem, child, name, None, hdf_name + ): + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set( + "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) + ) return child return False -def get_own_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None): +def get_own_nxdl_child( + nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None +): """Checks if an NXDL child node fits to the specific name (either nxdl or hdf) - name - nxdl name - class_type - nxdl type or hdf classname (for groups, it is obligatory) - hdf_name - hdf name""" + name - nxdl name + class_type - nxdl type or hdf classname (for groups, it is obligatory) + hdf_name - hdf name""" for child in nxdl_elem: - if 'name' in child.attrib and child.attrib['name'] == name: - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + if "name" in child.attrib and child.attrib["name"] == name: + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set( + "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) + ) return child for child in nxdl_elem: if "name" in child.attrib and child.attrib["name"] == name: - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) return child for child in nxdl_elem: @@ -338,7 +390,9 @@ def get_own_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_ty return result if nexus_type and get_local_name_from_xml(child) != nexus_type: continue - result = get_own_nxdl_child_base_types(child, class_type, nxdl_elem, name, hdf_name) + result = get_own_nxdl_child_base_types( + child, class_type, nxdl_elem, name, hdf_name + ) if result is not False: return result return None @@ -346,21 +400,28 @@ def get_own_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_ty def find_definition_file(bc_name): """find the nxdl file corresponding to the name. - Note that it first checks in contributed and goes beyond only if no contributed found""" + Note that it first checks in contributed and goes beyond only if no contributed found + """ bc_filename = None - for nxdl_folder in ['contributed_definitions', 'base_classes', 'applications']: - if os.path.exists(f"{get_nexus_definitions_path()}{os.sep}" - f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml"): - bc_filename = f"{get_nexus_definitions_path()}{os.sep}" \ - f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml" + for nxdl_folder in ["contributed_definitions", "base_classes", "applications"]: + if os.path.exists( + f"{get_nexus_definitions_path()}{os.sep}" + f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml" + ): + bc_filename = ( + f"{get_nexus_definitions_path()}{os.sep}" + f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml" + ) break return bc_filename -def get_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None, go_base=True): # pylint: disable=too-many-arguments +def get_nxdl_child( + nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None, go_base=True +): # pylint: disable=too-many-arguments """Get the NXDL child node corresponding to a specific name -(e.g. of an HDF5 node,or of a documentation) note that if child is not found in application -definition, it also checks for the base classes""" + (e.g. of an HDF5 node,or of a documentation) note that if child is not found in application + definition, it also checks for the base classes""" # search for possible fits for hdf_nodes : skipped # only exact hits are returned when searching an nxdl child own_child = get_own_nxdl_child(nxdl_elem, name, class_type, hdf_name, nexus_type) @@ -369,18 +430,20 @@ def get_nxdl_child(nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=N if not go_base: return None bc_name = get_nx_class(nxdl_elem) # check in the base class, app def or contributed - if bc_name[2] == '_': # filter primitive types + if bc_name[2] == "_": # filter primitive types return None - if bc_name == "group": # Check if it is the root element. Then send to NXroot.nxdl.xml + if ( + bc_name == "group" + ): # Check if it is the root element. Then send to NXroot.nxdl.xml bc_name = "NXroot" bc_filename = find_definition_file(bc_name) if not bc_filename: - raise ValueError('nxdl file not found in definitions folder!') + raise ValueError("nxdl file not found in definitions folder!") bc_obj = ET.parse(bc_filename).getroot() - bc_obj.set('nxdlbase', bc_filename) - if 'category' in bc_obj.attrib: - bc_obj.set('nxdlbase_class', bc_obj.attrib['category']) - bc_obj.set('nxdlpath', '') + bc_obj.set("nxdlbase", bc_filename) + if "category" in bc_obj.attrib: + bc_obj.set("nxdlbase_class", bc_obj.attrib["category"]) + bc_obj.set("nxdlpath", "") return get_own_nxdl_child(bc_obj, name, class_type, hdf_name, nexus_type) @@ -388,12 +451,16 @@ def get_required_string(nxdl_elem): """Check for being REQUIRED, RECOMMENDED, OPTIONAL, NOT IN SCHEMA""" if nxdl_elem is None: return "<>" - is_optional = 'optional' in nxdl_elem.attrib.keys() \ - and nxdl_elem.attrib['optional'] == "true" - is_minoccurs = 'minOccurs' in nxdl_elem.attrib.keys() \ - and nxdl_elem.attrib['minOccurs'] == "0" - is_recommended = 'recommended' in nxdl_elem.attrib.keys() \ - and nxdl_elem.attrib['recommended'] == "true" + is_optional = ( + "optional" in nxdl_elem.attrib.keys() and nxdl_elem.attrib["optional"] == "true" + ) + is_minoccurs = ( + "minOccurs" in nxdl_elem.attrib.keys() and nxdl_elem.attrib["minOccurs"] == "0" + ) + is_recommended = ( + "recommended" in nxdl_elem.attrib.keys() + and nxdl_elem.attrib["recommended"] == "true" + ) if is_recommended: return "<>" @@ -401,7 +468,7 @@ def get_required_string(nxdl_elem): return "<>" # default optionality: in BASE CLASSES is true; in APPLICATIONS is false try: - if nxdl_elem.get('nxdlbase_class') == 'base': + if nxdl_elem.get("nxdlbase_class") == "base": return "<>" except TypeError: return "<>" @@ -410,40 +477,44 @@ def get_required_string(nxdl_elem): def chk_nxdataaxis_v2(hdf_node, name, logger): """Check if dataset is an axis""" - own_signal = hdf_node.attrs.get('signal') # check for being a Signal + own_signal = hdf_node.attrs.get("signal") # check for being a Signal if own_signal is str and own_signal == "1": logger.debug("Dataset referenced (v2) as NXdata SIGNAL") - own_axes = hdf_node.attrs.get('axes') # check for being an axis + own_axes = hdf_node.attrs.get("axes") # check for being an axis if own_axes is str: - axes = own_axes.split(':') + axes = own_axes.split(":") for i in len(axes): if axes[i] and name == axes[i]: logger.debug("Dataset referenced (v2) as NXdata AXIS #%d", i) return None - ownpaxis = hdf_node.attrs.get('primary') - own_axis = hdf_node.attrs.get('axis') + ownpaxis = hdf_node.attrs.get("primary") + own_axis = hdf_node.attrs.get("axis") if own_axis is int: # also convention v1 if ownpaxis is int and ownpaxis == 1: logger.debug("Dataset referenced (v2) as NXdata AXIS #%d", own_axis - 1) else: logger.debug( - "Dataset referenced (v2) as NXdata (primary/alternative) AXIS #%d", own_axis - 1) + "Dataset referenced (v2) as NXdata (primary/alternative) AXIS #%d", + own_axis - 1, + ) return None def chk_nxdataaxis(hdf_node, name, logger): """NEXUS Data Plotting Standard v3: new version from 2014""" - if not isinstance(hdf_node, h5py.Dataset): # check if it is a field in an NXdata node + if not isinstance( + hdf_node, h5py.Dataset + ): # check if it is a field in an NXdata node return None parent = hdf_node.parent - if not parent or (parent and not parent.attrs.get('NX_class') == "NXdata"): + if not parent or (parent and not parent.attrs.get("NX_class") == "NXdata"): return None - signal = parent.attrs.get('signal') # chk for Signal + signal = parent.attrs.get("signal") # chk for Signal if signal and name == signal: logger.debug("Dataset referenced as NXdata SIGNAL") return None - axes = parent.attrs.get('axes') # check for default Axes + axes = parent.attrs.get("axes") # check for default Axes if axes is str: if name == axes: logger.debug("Dataset referenced as NXdata AXIS") @@ -451,13 +522,13 @@ def chk_nxdataaxis(hdf_node, name, logger): elif axes is not None: for i, j in enumerate(axes): if name == j: - indices = parent.attrs.get(j + '_indices') + indices = parent.attrs.get(j + "_indices") if indices is int: logger.debug(f"Dataset referenced as NXdata AXIS #{indices}") else: logger.debug(f"Dataset referenced as NXdata AXIS #{i}") return None - indices = parent.attrs.get(name + '_indices') # check for alternative Axes + indices = parent.attrs.get(name + "_indices") # check for alternative Axes if indices is int: logger.debug(f"Dataset referenced as NXdata alternative AXIS #{indices}") return chk_nxdataaxis_v2(hdf_node, name, logger) # check for older conventions @@ -467,7 +538,7 @@ def chk_nxdataaxis(hdf_node, name, logger): def write_doc_string(logger, doc, attr): """Simple function that prints a line in the logger if doc exists""" if doc: - logger.debug("@" + attr + ' [NX_CHAR]') + logger.debug("@" + attr + " [NX_CHAR]") return logger, doc, attr @@ -477,61 +548,96 @@ def try_find_units(logger, elem, nxdl_path, doc, attr): try: # try to find if units is defined inside the field in the NXDL element unit = elem.attrib[attr] if doc: - logger.debug(get_node_concept_path(elem) + "@" + attr + ' [' + unit + ']') + logger.debug(get_node_concept_path(elem) + "@" + attr + " [" + unit + "]") elem = None nxdl_path.append(attr) - except KeyError: # otherwise try to find if units is defined as a child of the NXDL element + except ( + KeyError + ): # otherwise try to find if units is defined as a child of the NXDL element orig_elem = elem - elem = get_nxdl_child(elem, attr, nexus_type='attribute') + elem = get_nxdl_child(elem, attr, nexus_type="attribute") if elem is not None: if doc: - logger.debug(get_node_concept_path(orig_elem) - + "@" + attr + ' - [' + get_nx_class(elem) + ']') + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - [" + + get_nx_class(elem) + + "]" + ) nxdl_path.append(elem) else: # if no units category were defined in NXDL: if doc: - logger.debug(get_node_concept_path(orig_elem) - + "@" + attr + " - REQUIRED, but undefined unit category") + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - REQUIRED, but undefined unit category" + ) nxdl_path.append(attr) return logger, elem, nxdl_path, doc, attr def check_attr_name_nxdl(param): """Check for ATTRIBUTENAME_units in NXDL (normal). -If not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE -is in the SCHEMA, but no units category were defined. """ + If not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE + is in the SCHEMA, but no units category were defined.""" (logger, elem, nxdl_path, doc, attr, req_str) = param orig_elem = elem - elem2 = get_nxdl_child(elem, attr, nexus_type='attribute') + elem2 = get_nxdl_child(elem, attr, nexus_type="attribute") if elem2 is not None: # check for ATTRIBUTENAME_units in NXDL (normal) elem = elem2 if doc: - logger.debug(get_node_concept_path(orig_elem) - + "@" + attr + ' - [' + get_nx_class(elem) + ']') + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - [" + + get_nx_class(elem) + + "]" + ) nxdl_path.append(elem) else: # if not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE # is in the SCHEMA, but no units category were defined - elem2 = get_nxdl_child(elem, attr[:-6], nexus_type='attribute') + elem2 = get_nxdl_child(elem, attr[:-6], nexus_type="attribute") if elem2 is not None: - req_str = '<>' + req_str = "<>" if doc: - logger.debug(get_node_concept_path(orig_elem) - + "@" + attr + " - RECOMMENDED, but undefined unit category") + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - RECOMMENDED, but undefined unit category" + ) nxdl_path.append(attr) else: # otherwise: NOT IN SCHEMA elem = elem2 if doc: - logger.debug(get_node_concept_path(orig_elem) + "@" + attr + " - IS NOT IN SCHEMA") + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - IS NOT IN SCHEMA" + ) return logger, elem, nxdl_path, doc, attr, req_str -def try_find_default(logger, orig_elem, elem, nxdl_path, doc, attr): # pylint: disable=too-many-arguments - """Try to find if default is defined as a child of the NXDL element """ +def try_find_default( + logger, orig_elem, elem, nxdl_path, doc, attr +): # pylint: disable=too-many-arguments + """Try to find if default is defined as a child of the NXDL element""" if elem is not None: if doc: - logger.debug(get_node_concept_path(orig_elem) - + "@" + attr + ' - [' + get_nx_class(elem) + ']') + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - [" + + get_nx_class(elem) + + "]" + ) nxdl_path.append(elem) else: # if no default category were defined in NXDL: if doc: @@ -540,38 +646,50 @@ def try_find_default(logger, orig_elem, elem, nxdl_path, doc, attr): # pylint: return logger, elem, nxdl_path, doc, attr -def other_attrs(logger, orig_elem, elem, nxdl_path, doc, attr): # pylint: disable=too-many-arguments - """Handle remaining attributes """ +def other_attrs( + logger, orig_elem, elem, nxdl_path, doc, attr +): # pylint: disable=too-many-arguments + """Handle remaining attributes""" if elem is not None: if doc: - logger.debug(get_node_concept_path(orig_elem) - + "@" + attr + ' - [' + get_nx_class(elem) + ']') + logger.debug( + get_node_concept_path(orig_elem) + + "@" + + attr + + " - [" + + get_nx_class(elem) + + "]" + ) nxdl_path.append(elem) else: if doc: - logger.debug(get_node_concept_path(orig_elem) + "@" + attr + " - IS NOT IN SCHEMA") + logger.debug( + get_node_concept_path(orig_elem) + "@" + attr + " - IS NOT IN SCHEMA" + ) return logger, elem, nxdl_path, doc, attr def check_deprecation_enum_axis(variables, doc, elist, attr, hdf_node): - """Check for several attributes. - deprecation - enums - nxdataaxis """ + """Check for several attributes. - deprecation - enums - nxdataaxis""" logger, elem, path = variables - dep_str = elem.attrib.get('deprecated') # check for deprecation + dep_str = elem.attrib.get("deprecated") # check for deprecation if dep_str: if doc: logger.debug("DEPRECATED - " + dep_str) for base_elem in elist if not attr else [elem]: # check for enums - sdoc = get_nxdl_child(base_elem, 'enumeration', go_base=False) + sdoc = get_nxdl_child(base_elem, "enumeration", go_base=False) if sdoc is not None: if doc: logger.debug("enumeration (" + get_node_concept_path(base_elem) + "):") for item in sdoc: - if get_local_name_from_xml(item) == 'item': + if get_local_name_from_xml(item) == "item": if doc: - logger.debug("-> " + item.attrib['value']) - chk_nxdataaxis(hdf_node, path.split('/')[-1], logger) # look for NXdata reference (axes/signal) + logger.debug("-> " + item.attrib["value"]) + chk_nxdataaxis( + hdf_node, path.split("/")[-1], logger + ) # look for NXdata reference (axes/signal) for base_elem in elist if not attr else [elem]: # check for doc - sdoc = get_nxdl_child(base_elem, 'doc', go_base=False) + sdoc = get_nxdl_child(base_elem, "doc", go_base=False) if doc: logger.debug("documentation (" + get_node_concept_path(base_elem) + "):") logger.debug(sdoc.text if sdoc is not None else "") @@ -580,11 +698,12 @@ def check_deprecation_enum_axis(variables, doc, elist, attr, hdf_node): def get_node_concept_path(elem): """get the short version of nxdlbase:nxdlpath""" - return str(elem.get('nxdlbase').split('/')[-1] + ":" + elem.get('nxdlpath')) + return str(elem.get("nxdlbase").split("/")[-1] + ":" + elem.get("nxdlpath")) def get_nxdl_attr_doc( # pylint: disable=too-many-arguments,too-many-locals - elem, elist, attr, hdf_node, logger, doc, nxdl_path, req_str, path, hdf_info): + elem, elist, attr, hdf_node, logger, doc, nxdl_path, req_str, path, hdf_info +): """Get nxdl documentation for an attribute""" new_elem = [] old_elem = elem @@ -592,43 +711,44 @@ def get_nxdl_attr_doc( # pylint: disable=too-many-arguments,too-many-locals act_elem = act_elem1 # NX_class is a compulsory attribute for groups in a nexus file # which should match the type of the corresponding NXDL element - if attr == 'NX_class' and not isinstance(hdf_node, h5py.Dataset) and elem_index == 0: + if ( + attr == "NX_class" + and not isinstance(hdf_node, h5py.Dataset) + and elem_index == 0 + ): elem = None logger, doc, attr = write_doc_string(logger, doc, attr) new_elem = elem break # units category is a compulsory attribute for any fields - if attr == 'units' and isinstance(hdf_node, h5py.Dataset): + if attr == "units" and isinstance(hdf_node, h5py.Dataset): req_str = "<>" - logger, act_elem, nxdl_path, doc, attr = try_find_units(logger, - act_elem, - nxdl_path, - doc, - attr) + logger, act_elem, nxdl_path, doc, attr = try_find_units( + logger, act_elem, nxdl_path, doc, attr + ) # units for attributes can be given as ATTRIBUTENAME_units - elif attr.endswith('_units'): - logger, act_elem, nxdl_path, doc, attr, req_str = check_attr_name_nxdl((logger, - act_elem, - nxdl_path, - doc, - attr, - req_str)) + elif attr.endswith("_units"): + logger, act_elem, nxdl_path, doc, attr, req_str = check_attr_name_nxdl( + (logger, act_elem, nxdl_path, doc, attr, req_str) + ) # default is allowed for groups - elif attr == 'default' and not isinstance(hdf_node, h5py.Dataset): + elif attr == "default" and not isinstance(hdf_node, h5py.Dataset): req_str = "<>" # try to find if default is defined as a child of the NXDL element - act_elem = get_nxdl_child(act_elem, attr, nexus_type='attribute', go_base=False) - logger, act_elem, nxdl_path, doc, attr = try_find_default(logger, - act_elem1, - act_elem, - nxdl_path, - doc, - attr) + act_elem = get_nxdl_child( + act_elem, attr, nexus_type="attribute", go_base=False + ) + logger, act_elem, nxdl_path, doc, attr = try_find_default( + logger, act_elem1, act_elem, nxdl_path, doc, attr + ) else: # other attributes - act_elem = get_nxdl_child(act_elem, attr, nexus_type='attribute', go_base=False) + act_elem = get_nxdl_child( + act_elem, attr, nexus_type="attribute", go_base=False + ) if act_elem is not None: - logger, act_elem, nxdl_path, doc, attr = \ - other_attrs(logger, act_elem1, act_elem, nxdl_path, doc, attr) + logger, act_elem, nxdl_path, doc, attr = other_attrs( + logger, act_elem1, act_elem, nxdl_path, doc, attr + ) if act_elem is not None: new_elem.append(act_elem) if req_str is None: @@ -636,14 +756,18 @@ def get_nxdl_attr_doc( # pylint: disable=too-many-arguments,too-many-locals if doc: logger.debug(req_str) variables = [logger, act_elem, path] - logger, elem, path, doc, elist, attr, hdf_node = check_deprecation_enum_axis(variables, - doc, - elist, - attr, - hdf_node) + ( + logger, + elem, + path, + doc, + elist, + attr, + hdf_node, + ) = check_deprecation_enum_axis(variables, doc, elist, attr, hdf_node) elem = old_elem if req_str is None and doc: - if attr != 'NX_class': + if attr != "NX_class": logger.debug("@" + attr + " - IS NOT IN SCHEMA") logger.debug("") return (req_str, get_nxdl_entry(hdf_info), nxdl_path) @@ -651,48 +775,54 @@ def get_nxdl_attr_doc( # pylint: disable=too-many-arguments,too-many-locals def get_nxdl_doc(hdf_info, logger, doc, attr=False): """Get nxdl documentation for an HDF5 node (or its attribute)""" - hdf_node = hdf_info['hdf_node'] + hdf_node = hdf_info["hdf_node"] # new way: retrieve multiple inherited base classes - (class_path, nxdl_path, elist) = \ - get_inherited_nodes(None, nx_name=get_nxdl_entry(hdf_info), hdf_node=hdf_node, - hdf_path=hdf_info['hdf_path'] if 'hdf_path' in hdf_info else None, - hdf_root=hdf_info['hdf_root'] if 'hdf_root' in hdf_info else None) + (class_path, nxdl_path, elist) = get_inherited_nodes( + None, + nx_name=get_nxdl_entry(hdf_info), + hdf_node=hdf_node, + hdf_path=hdf_info["hdf_path"] if "hdf_path" in hdf_info else None, + hdf_root=hdf_info["hdf_root"] if "hdf_root" in hdf_info else None, + ) elem = elist[0] if class_path and elist else None if doc: logger.debug("classpath: " + str(class_path)) - logger.debug("NOT IN SCHEMA" if elem is None else - "classes:\n" + "\n".join - (get_node_concept_path(e) for e in elist)) + logger.debug( + "NOT IN SCHEMA" + if elem is None + else "classes:\n" + "\n".join(get_node_concept_path(e) for e in elist) + ) # old solution with a single elem instead of using elist path = get_nx_class_path(hdf_info) req_str = None if elem is None: if doc: logger.debug("") - return ('None', None, None) + return ("None", None, None) if attr: - return get_nxdl_attr_doc(elem, elist, attr, hdf_node, logger, doc, nxdl_path, - req_str, path, hdf_info) + return get_nxdl_attr_doc( + elem, elist, attr, hdf_node, logger, doc, nxdl_path, req_str, path, hdf_info + ) req_str = get_required_string(elem) # check for being required if doc: logger.debug(req_str) variables = [logger, elem, path] - logger, elem, path, doc, elist, attr, hdf_node = check_deprecation_enum_axis(variables, - doc, - elist, - attr, - hdf_node) + logger, elem, path, doc, elist, attr, hdf_node = check_deprecation_enum_axis( + variables, doc, elist, attr, hdf_node + ) return (req_str, get_nxdl_entry(hdf_info), nxdl_path) def get_doc(node, ntype, nxhtml, nxpath): """Get documentation""" # URL for html documentation - anchor = '' + anchor = "" for n_item in nxpath: anchor += n_item.lower() + "-" - anchor = ('https://manual.nexusformat.org/classes/', - nxhtml + "#" + anchor.replace('_', '-') + ntype) + anchor = ( + "https://manual.nexusformat.org/classes/", + nxhtml + "#" + anchor.replace("_", "-") + ntype, + ) if not ntype: anchor = anchor[:-1] doc = "" # RST documentation from the field 'doc' @@ -701,9 +831,13 @@ def get_doc(node, ntype, nxhtml, nxpath): doc = doc_field.text (index, enums) = get_enums(node) # enums if index: - enum_str = "\n " + ("Possible values:" - if len(enums.split(',')) > 1 - else "Obligatory value:") + "\n " + enums + "\n" + enum_str = ( + "\n " + + ("Possible values:" if len(enums.split(",")) > 1 else "Obligatory value:") + + "\n " + + enums + + "\n" + ) else: enum_str = "" return anchor, doc + enum_str @@ -714,17 +848,21 @@ def print_doc(node, ntype, level, nxhtml, nxpath): anchor, doc = get_doc(node, ntype, nxhtml, nxpath) print(" " * (level + 1) + anchor) preferred_width = 80 + level * 2 - wrapper = textwrap.TextWrapper(initial_indent=' ' * (level + 1), width=preferred_width, - subsequent_indent=' ' * (level + 1), expand_tabs=False, - tabsize=0) + wrapper = textwrap.TextWrapper( + initial_indent=" " * (level + 1), + width=preferred_width, + subsequent_indent=" " * (level + 1), + expand_tabs=False, + tabsize=0, + ) if doc is not None: - for par in doc.split('\n'): + for par in doc.split("\n"): print(wrapper.fill(par)) def get_namespace(element): """Extracts the namespace for elements in the NXDL""" - return element.tag[element.tag.index("{"):element.tag.rindex("}") + 1] + return element.tag[element.tag.index("{") : element.tag.rindex("}") + 1] def get_enums(node): @@ -737,15 +875,16 @@ def get_enums(node): for enumeration in node.findall(f"{namespace}enumeration"): for item in enumeration.findall(f"{namespace}item"): enums.append(item.attrib["value"]) - enums = ','.join(enums) + enums = ",".join(enums) if enums != "": - return (True, '[' + enums + ']') + return (True, "[" + enums + "]") return (False, "") # if there is no enumeration tag, returns empty string def add_base_classes(elist, nx_name=None, elem: ET.Element = None): """Add the base classes corresponding to the last eleme in elist to the list. Note that if -elist is empty, a nxdl file with the name of nx_name or a rather room elem is used if provided""" + elist is empty, a nxdl file with the name of nx_name or a rather room elem is used if provided + """ if elist and nx_name is None: nx_name = get_nx_class(elist[-1]) # to support recursive defintions, like NXsample in NXsample, the following test is removed @@ -758,48 +897,51 @@ def add_base_classes(elist, nx_name=None, elem: ET.Element = None): if nxdl_file_path is None: nxdl_file_path = f"{nx_name}.nxdl.xml" elem = ET.parse(nxdl_file_path).getroot() - elem.set('nxdlbase', nxdl_file_path) + elem.set("nxdlbase", nxdl_file_path) else: - elem.set('nxdlbase', '') - if 'category' in elem.attrib: - elem.set('nxdlbase_class', elem.attrib['category']) - elem.set('nxdlpath', '') + elem.set("nxdlbase", "") + if "category" in elem.attrib: + elem.set("nxdlbase_class", elem.attrib["category"]) + elem.set("nxdlpath", "") elist.append(elem) # add inherited base class - if 'extends' in elem.attrib and elem.attrib['extends'] != 'NXobject': - add_base_classes(elist, elem.attrib['extends']) + if "extends" in elem.attrib and elem.attrib["extends"] != "NXobject": + add_base_classes(elist, elem.attrib["extends"]) else: add_base_classes(elist) def set_nxdlpath(child, nxdl_elem): """ - Setting up child nxdlbase, nxdlpath and nxdlbase_class from nxdl_element. + Setting up child nxdlbase, nxdlpath and nxdlbase_class from nxdl_element. """ - if nxdl_elem.get('nxdlbase'): - child.set('nxdlbase', nxdl_elem.get('nxdlbase')) - child.set('nxdlbase_class', nxdl_elem.get('nxdlbase_class')) - child.set('nxdlpath', nxdl_elem.get('nxdlpath') + '/' + get_node_name(child)) + if nxdl_elem.get("nxdlbase"): + child.set("nxdlbase", nxdl_elem.get("nxdlbase")) + child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) + child.set("nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child)) return child def get_direct_child(nxdl_elem, html_name): - """ returns the child of nxdl_elem which has a name - corresponding to the the html documentation name html_name""" + """returns the child of nxdl_elem which has a name + corresponding to the the html documentation name html_name""" for child in nxdl_elem: - if get_local_name_from_xml(child) in ('group', 'field', 'attribute') and \ - html_name == get_node_name(child): + if get_local_name_from_xml(child) in ( + "group", + "field", + "attribute", + ) and html_name == get_node_name(child): decorated_child = set_nxdlpath(child, nxdl_elem) return decorated_child return None def get_field_child(nxdl_elem, html_name): - """ returns the child of nxdl_elem which has a name - corresponding to the html documentation name html_name""" + """returns the child of nxdl_elem which has a name + corresponding to the html documentation name html_name""" data_child = None for child in nxdl_elem: - if get_local_name_from_xml(child) != 'field': + if get_local_name_from_xml(child) != "field": continue if get_node_name(child) == html_name: data_child = set_nxdlpath(child, nxdl_elem) @@ -808,27 +950,27 @@ def get_field_child(nxdl_elem, html_name): def get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name): - """ returns the child of an NXdata nxdl_elem which has a name - corresponding to the hdf_name""" + """returns the child of an NXdata nxdl_elem which has a name + corresponding to the hdf_name""" nxdata = hdf_node.parent signals = [] - if 'signal' in nxdata.attrs.keys(): + if "signal" in nxdata.attrs.keys(): signals.append(nxdata.attrs.get("signal")) if "auxiliary_signals" in nxdata.attrs.keys(): for aux_signal in nxdata.attrs.get("auxiliary_signals"): signals.append(aux_signal) - data_child = get_field_child(nxdl_elem, 'DATA') - data_error_child = get_field_child(nxdl_elem, 'FIELDNAME_errors') + data_child = get_field_child(nxdl_elem, "DATA") + data_error_child = get_field_child(nxdl_elem, "FIELDNAME_errors") for signal in signals: if signal == hdf_name: return (data_child, 100) - if hdf_name.endswith('_errors') and signal == hdf_name[:-7]: + if hdf_name.endswith("_errors") and signal == hdf_name[:-7]: return (data_error_child, 100) axes = [] if "axes" in nxdata.attrs.keys(): for axis in nxdata.attrs.get("axes"): axes.append(axis) - axis_child = get_field_child(nxdl_elem, 'AXISNAME') + axis_child = get_field_child(nxdl_elem, "AXISNAME") for axis in axes: if axis == hdf_name: return (axis_child, 100) @@ -836,22 +978,29 @@ def get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name): def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): - """ returns the child of nxdl_elem which has a name - corresponding to the the html documentation name html_name""" + """returns the child of nxdl_elem which has a name + corresponding to the the html documentation name html_name""" bestfit = -1 bestchild = None - if 'name' in nxdl_elem.attrib.keys() and nxdl_elem.attrib['name'] == 'NXdata' and \ - hdf_node is not None and hdf_node.parent is not None and \ - hdf_node.parent.attrs.get('NX_class') == 'NXdata': + if ( + "name" in nxdl_elem.attrib.keys() + and nxdl_elem.attrib["name"] == "NXdata" + and hdf_node is not None + and hdf_node.parent is not None + and hdf_node.parent.attrs.get("NX_class") == "NXdata" + ): (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) if fnd_child is not None: return (fnd_child, fit) for child in nxdl_elem: fit = -2 - if get_local_name_from_xml(child) == nexus_type and \ - (nexus_type != 'group' or get_nx_class(child) == hdf_class_name): - name_any = "nameType" in nxdl_elem.attrib.keys() and \ - nxdl_elem.attrib["nameType"] == "any" + if get_local_name_from_xml(child) == nexus_type and ( + nexus_type != "group" or get_nx_class(child) == hdf_class_name + ): + name_any = ( + "nameType" in nxdl_elem.attrib.keys() + and nxdl_elem.attrib["nameType"] == "any" + ) fit = get_nx_namefit(hdf_name, get_node_name(child), name_any) if fit > bestfit: bestfit = fit @@ -869,9 +1018,13 @@ def walk_elist(elist, html_name): for potential_direct_parent in elist: main_child = get_direct_child(potential_direct_parent, html_name) if main_child is not None: - (fitting_child, _) = get_best_child(elist[ind], None, html_name, - get_nx_class(main_child), - get_local_name_from_xml(main_child)) + (fitting_child, _) = get_best_child( + elist[ind], + None, + html_name, + get_nx_class(main_child), + get_local_name_from_xml(main_child), + ) if fitting_child is not None: child = fitting_child break @@ -880,10 +1033,12 @@ def walk_elist(elist, html_name): del elist[ind] continue # override: remove low priority inheritance classes if class_type is overriden - if len(elist) > ind + 1 and get_nx_class(elist[ind]) != get_nx_class(elist[ind + 1]): - del elist[ind + 1:] + if len(elist) > ind + 1 and get_nx_class(elist[ind]) != get_nx_class( + elist[ind + 1] + ): + del elist[ind + 1 :] # add new base class(es) if new element brings such (and not a primitive type) - if len(elist) == ind + 1 and get_nx_class(elist[ind])[0:3] != 'NX_': + if len(elist) == ind + 1 and get_nx_class(elist[ind])[0:3] != "NX_": add_base_classes(elist) return elist, html_name @@ -894,20 +1049,18 @@ def helper_get_inherited_nodes(hdf_info2, elist, pind, attr): hdf_name = hdf_path[pind] hdf_class_name = hdf_class_path[pind] if pind < len(hdf_path) - (2 if attr else 1): - act_nexus_type = 'group' + act_nexus_type = "group" elif pind == len(hdf_path) - 1 and attr: - act_nexus_type = 'attribute' + act_nexus_type = "attribute" else: - act_nexus_type = 'field' if isinstance(hdf_node, h5py.Dataset) else 'group' + act_nexus_type = "field" if isinstance(hdf_node, h5py.Dataset) else "group" # find the best fitting name in all children bestfit = -1 html_name = None for ind in range(len(elist) - 1, -1, -1): - newelem, fit = get_best_child(elist[ind], - hdf_node, - hdf_name, - hdf_class_name, - act_nexus_type) + newelem, fit = get_best_child( + elist[ind], hdf_node, hdf_name, hdf_class_name, act_nexus_type + ) if fit >= bestfit and newelem is not None: html_name = get_node_name(newelem) return hdf_path, hdf_node, hdf_class_path, elist, pind, attr, html_name @@ -915,15 +1068,21 @@ def helper_get_inherited_nodes(hdf_info2, elist, pind, attr): def get_hdf_path(hdf_info): """Get the hdf_path from an hdf_info""" - if 'hdf_path' in hdf_info: - return hdf_info['hdf_path'].split('/')[1:] - return hdf_info['hdf_node'].name.split('/')[1:] + if "hdf_path" in hdf_info: + return hdf_info["hdf_path"].split("/")[1:] + return hdf_info["hdf_node"].name.split("/")[1:] @lru_cache(maxsize=None) -def get_inherited_nodes(nxdl_path: str = None, # pylint: disable=too-many-arguments,too-many-locals - nx_name: str = None, elem: ET.Element = None, - hdf_node=None, hdf_path=None, hdf_root=None, attr=False): +def get_inherited_nodes( + nxdl_path: str = None, # pylint: disable=too-many-arguments,too-many-locals + nx_name: str = None, + elem: ET.Element = None, + hdf_node=None, + hdf_path=None, + hdf_root=None, + attr=False, +): """Returns a list of ET.Element for the given path.""" # let us start with the given definition file elist = [] # type: ignore[var-annotated] @@ -932,27 +1091,33 @@ def get_inherited_nodes(nxdl_path: str = None, # pylint: disable=too-many-argum class_path = [] # type: ignore[var-annotated] if hdf_node is not None: - hdf_info = {'hdf_node': hdf_node} + hdf_info = {"hdf_node": hdf_node} if hdf_path: - hdf_info['hdf_path'] = hdf_path + hdf_info["hdf_path"] = hdf_path if hdf_root: - hdf_root['hdf_root'] = hdf_root - hdf_node = hdf_info['hdf_node'] + hdf_root["hdf_root"] = hdf_root + hdf_node = hdf_info["hdf_node"] hdf_path = get_hdf_path(hdf_info) - hdf_class_path = get_nx_class_path(hdf_info).split('/')[1:] + hdf_class_path = get_nx_class_path(hdf_info).split("/")[1:] if attr: hdf_path.append(attr) hdf_class_path.append(attr) path = hdf_path else: - html_path = nxdl_path.split('/')[1:] + html_path = nxdl_path.split("/")[1:] path = html_path for pind in range(len(path)): if hdf_node is not None: hdf_info2 = [hdf_path, hdf_node, hdf_class_path] - [hdf_path, hdf_node, hdf_class_path, elist, - pind, attr, html_name] = helper_get_inherited_nodes(hdf_info2, elist, - pind, attr) + [ + hdf_path, + hdf_node, + hdf_class_path, + elist, + pind, + attr, + html_name, + ] = helper_get_inherited_nodes(hdf_info2, elist, pind, attr) if html_name is None: # return if NOT IN SCHEMA return (class_path, nxdl_elem_path, None) else: @@ -964,9 +1129,12 @@ def get_inherited_nodes(nxdl_path: str = None, # pylint: disable=too-many-argum return (class_path, nxdl_elem_path, elist) -def get_node_at_nxdl_path(nxdl_path: str = None, - nx_name: str = None, elem: ET.Element = None, - exc: bool = True): +def get_node_at_nxdl_path( + nxdl_path: str = None, + nx_name: str = None, + elem: ET.Element = None, + exc: bool = True, +): """Returns an ET.Element for the given path. This function either takes the name for the NeXus Application Definition we are looking for or the root elem from a previously loaded NXDL file @@ -975,32 +1143,38 @@ def get_node_at_nxdl_path(nxdl_path: str = None, (class_path, nxdlpath, elist) = get_inherited_nodes(nxdl_path, nx_name, elem) except ValueError as value_error: if exc: - raise NxdlAttributeError(f"Attributes were not found for {nxdl_path}. " - "Please check this entry in the template dictionary.") \ - from value_error + raise NxdlAttributeError( + f"Attributes were not found for {nxdl_path}. " + "Please check this entry in the template dictionary." + ) from value_error return None if class_path and nxdlpath and elist: elem = elist[0] else: elem = None if exc: - raise NxdlAttributeError(f"Attributes were not found for {nxdl_path}. " - "Please check this entry in the template dictionary.") + raise NxdlAttributeError( + f"Attributes were not found for {nxdl_path}. " + "Please check this entry in the template dictionary." + ) return elem def process_node(hdf_node, hdf_path, parser, logger, doc=True): """Processes an hdf5 node. -- it logs the node found and also checks for its attributes -- retrieves the corresponding nxdl documentation -TODO: -- follow variants -- NOMAD parser: store in NOMAD """ - hdf_info = {'hdf_path': hdf_path, 'hdf_node': hdf_node} + - it logs the node found and also checks for its attributes + - retrieves the corresponding nxdl documentation + TODO: + - follow variants + - NOMAD parser: store in NOMAD""" + hdf_info = {"hdf_path": hdf_path, "hdf_node": hdf_node} if isinstance(hdf_node, h5py.Dataset): - logger.debug(f'===== FIELD (/{hdf_path}): {hdf_node}') - val = str(hdf_node[()]).split('\n') if len(hdf_node.shape) <= 1 else str( - hdf_node[0]).split('\n') + logger.debug(f"===== FIELD (/{hdf_path}): {hdf_node}") + val = ( + str(hdf_node[()]).split("\n") + if len(hdf_node.shape) <= 1 + else str(hdf_node[0]).split("\n") + ) logger.debug(f'value: {val[0]} {"..." if len(val) > 1 else ""}') else: logger.debug( @@ -1010,46 +1184,54 @@ def process_node(hdf_node, hdf_path, parser, logger, doc=True): ) (req_str, nxdef, nxdl_path) = get_nxdl_doc(hdf_info, logger, doc) if parser is not None and isinstance(hdf_node, h5py.Dataset): - parser({"hdf_info": hdf_info, + parser( + { + "hdf_info": hdf_info, "nxdef": nxdef, "nxdl_path": nxdl_path, "val": val, - "logger": logger}) + "logger": logger, + } + ) for key, value in hdf_node.attrs.items(): - logger.debug(f'===== ATTRS (/{hdf_path}@{key})') - val = str(value).split('\n') + logger.debug(f"===== ATTRS (/{hdf_path}@{key})") + val = str(value).split("\n") logger.debug(f'value: {val[0]} {"..." if len(val) > 1 else ""}') - (req_str, nxdef, nxdl_path) = \ - get_nxdl_doc(hdf_info, logger, doc, attr=key) + (req_str, nxdef, nxdl_path) = get_nxdl_doc(hdf_info, logger, doc, attr=key) if ( parser is not None and req_str is not None - and 'NOT IN SCHEMA' not in req_str - and 'None' not in req_str + and "NOT IN SCHEMA" not in req_str + and "None" not in req_str ): - parser({"hdf_info": hdf_info, + parser( + { + "hdf_info": hdf_info, "nxdef": nxdef, "nxdl_path": nxdl_path, "val": val, - "logger": logger}, attr=key) + "logger": logger, + }, + attr=key, + ) def logger_auxiliary_signal(logger, nxdata): """Handle the presence of auxiliary signal""" - aux = nxdata.attrs.get('auxiliary_signals') + aux = nxdata.attrs.get("auxiliary_signals") if aux is not None: if isinstance(aux, str): aux = [aux] for asig in aux: - logger.debug(f'Further auxiliary signal has been identified: {asig}') + logger.debug(f"Further auxiliary signal has been identified: {asig}") return logger def print_default_plotable_header(logger): """Print a three-lines header""" - logger.debug('========================') - logger.debug('=== Default Plotable ===') - logger.debug('========================') + logger.debug("========================") + logger.debug("=== Default Plotable ===") + logger.debug("========================") def get_default_plotable(root, logger): @@ -1067,10 +1249,10 @@ def get_default_plotable(root, logger): if not nxentry: nxentry = entry_helper(root) if not nxentry: - logger.debug('No NXentry has been found') + logger.debug("No NXentry has been found") return - logger.debug('') - logger.debug('NXentry has been identified: ' + nxentry.name) + logger.debug("") + logger.debug("NXentry has been identified: " + nxentry.name) # nxdata nxdata = None nxgroup = nxentry @@ -1086,10 +1268,10 @@ def get_default_plotable(root, logger): else: nxdata = nxgroup if not nxdata: - logger.debug('No NXdata group has been found') + logger.debug("No NXdata group has been found") return - logger.debug('') - logger.debug('NXdata group has been identified: ' + nxdata.name) + logger.debug("") + logger.debug("NXdata group has been identified: " + nxdata.name) process_node(nxdata, nxdata.name, None, logger, False) # signal signal = None @@ -1101,10 +1283,10 @@ def get_default_plotable(root, logger): if not signal: signal = signal_helper(nxdata) if not signal: - logger.debug('No Signal has been found') + logger.debug("No Signal has been found") return - logger.debug('') - logger.debug('Signal has been identified: ' + signal.name) + logger.debug("") + logger.debug("Signal has been identified: " + signal.name) process_node(signal, signal.name, None, logger, False) logger = logger_auxiliary_signal(logger, nxdata) # check auxiliary_signals dim = len(signal.shape) @@ -1116,8 +1298,11 @@ def entry_helper(root): """Check entry related data""" nxentries = [] for key in root.keys(): - if isinstance(root[key], h5py.Group) and root[key].attrs.get('NX_class') and \ - root[key].attrs['NX_class'] == "NXentry": + if ( + isinstance(root[key], h5py.Group) + and root[key].attrs.get("NX_class") + and root[key].attrs["NX_class"] == "NXentry" + ): nxentries.append(root[key]) if len(nxentries) >= 1: return nxentries[0] @@ -1126,11 +1311,14 @@ def entry_helper(root): def nxdata_helper(nxentry): """Check if nxentry hdf5 object has a NX_class and, if it contains NXdata, -return its value""" + return its value""" lnxdata = [] for key in nxentry.keys(): - if isinstance(nxentry[key], h5py.Group) and nxentry[key].attrs.get('NX_class') and \ - nxentry[key].attrs['NX_class'] == "NXdata": + if ( + isinstance(nxentry[key], h5py.Group) + and nxentry[key].attrs.get("NX_class") + and nxentry[key].attrs["NX_class"] == "NXdata" + ): lnxdata.append(nxentry[key]) if len(lnxdata) >= 1: return lnxdata[0] @@ -1143,12 +1331,17 @@ def signal_helper(nxdata): for key in nxdata.keys(): if isinstance(nxdata[key], h5py.Dataset): signals.append(nxdata[key]) - if len(signals) == 1: # v3: as there was no selection given, only 1 data field shall exists + if ( + len(signals) == 1 + ): # v3: as there was no selection given, only 1 data field shall exists return signals[0] if len(signals) > 1: # v2: select the one with an attribute signal="1" attribute for sig in signals: - if sig.attrs.get("signal") and sig.attrs.get("signal") is str and \ - sig.attrs.get("signal") == "1": + if ( + sig.attrs.get("signal") + and sig.attrs.get("signal") is str + and sig.attrs.get("signal") == "1" + ): return sig return None @@ -1160,7 +1353,7 @@ def find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list): for key in nxdata.keys(): if isinstance(nxdata[key], h5py.Dataset): try: - if nxdata[key].attrs['axis'] == a_item + 1: + if nxdata[key].attrs["axis"] == a_item + 1: lax.append(nxdata[key]) except KeyError: pass @@ -1169,7 +1362,7 @@ def find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list): # if there are more alternatives, prioritise the one with an attribute primary="1" elif len(lax) > 1: for sax in lax: - if sax.attrs.get('primary') and sax.attrs.get('primary') == 1: + if sax.attrs.get("primary") and sax.attrs.get("primary") == 1: ax_list.insert(0, sax) else: ax_list.append(sax) @@ -1180,7 +1373,7 @@ def get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list): try: if isinstance(ax_datasets, str): # single axis is defined # explicite definition of dimension number - ind = nxdata.attrs.get(ax_datasets + '_indices') + ind = nxdata.attrs.get(ax_datasets + "_indices") if ind and ind is int: if ind == a_item: ax_list.append(nxdata[ax_datasets]) @@ -1189,7 +1382,7 @@ def get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list): else: # multiple axes are listed # explicite definition of dimension number for aax in ax_datasets: - ind = nxdata.attrs.get(aax + '_indices') + ind = nxdata.attrs.get(aax + "_indices") if ind and isinstance(ind, int): if ind == a_item: ax_list.append(nxdata[aax]) @@ -1207,22 +1400,25 @@ def axis_helper(dim, nxdata, signal, axes, logger): ax_datasets = nxdata.attrs.get("axes") # primary axes listed in attribute axes ax_list = get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list) for attr in nxdata.attrs.keys(): # check for corresponding AXISNAME_indices - if attr.endswith('_indices') and nxdata.attrs[attr] == a_item and \ - nxdata[attr.split('_indices')[0]] not in ax_list: - ax_list.append(nxdata[attr.split('_indices')[0]]) + if ( + attr.endswith("_indices") + and nxdata.attrs[attr] == a_item + and nxdata[attr.split("_indices")[0]] not in ax_list + ): + ax_list.append(nxdata[attr.split("_indices")[0]]) # v2 # check for ':' separated axes defined in Signal if not ax_list: try: - ax_datasets = signal.attrs.get("axes").split(':') + ax_datasets = signal.attrs.get("axes").split(":") ax_list.append(nxdata[ax_datasets[a_item]]) except (KeyError, AttributeError): pass if not ax_list: # check for axis/primary specifications find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list) axes.append(ax_list) - logger.debug('') + logger.debug("") logger.debug( - f'For Axis #{a_item}, {len(ax_list)} axes have been identified: {str(ax_list)}' + f"For Axis #{a_item}, {len(ax_list)} axes have been identified: {str(ax_list)}" ) @@ -1230,38 +1426,43 @@ def get_all_is_a_rel_from_hdf_node(hdf_node, hdf_path): """Return list of nxdl concept paths for a nxdl element which corresponds to hdf node. """ - hdf_info = {'hdf_path': hdf_path, 'hdf_node': hdf_node} - (_, _, elist) = \ - get_inherited_nodes(None, nx_name=get_nxdl_entry(hdf_info), hdf_node=hdf_node, - hdf_path=hdf_info['hdf_path'] if 'hdf_path' in hdf_info else None, - hdf_root=hdf_info['hdf_root'] if 'hdf_root' in hdf_info else None) + hdf_info = {"hdf_path": hdf_path, "hdf_node": hdf_node} + (_, _, elist) = get_inherited_nodes( + None, + nx_name=get_nxdl_entry(hdf_info), + hdf_node=hdf_node, + hdf_path=hdf_info["hdf_path"] if "hdf_path" in hdf_info else None, + hdf_root=hdf_info["hdf_root"] if "hdf_root" in hdf_info else None, + ) return elist def hdf_node_to_self_concept_path(hdf_info, logger): - """ Get concept or nxdl path from given hdf_node. - """ + """Get concept or nxdl path from given hdf_node.""" # The bellow logger is for deactivatine unnecessary debug message above if logger is None: logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) (_, _, nxdl_path) = get_nxdl_doc(hdf_info, logger, None) - con_path = '' + con_path = "" if nxdl_path: for nd_ in nxdl_path: - con_path = con_path + '/' + get_node_name(nd_) + con_path = con_path + "/" + get_node_name(nd_) return con_path class HandleNexus: """documentation""" - def __init__(self, logger, nexus_file, - d_inq_nd=None, c_inq_nd=None): + + def __init__(self, logger, nexus_file, d_inq_nd=None, c_inq_nd=None): self.logger = logger local_dir = os.path.abspath(os.path.dirname(__file__)) - self.input_file_name = nexus_file if nexus_file is not None else \ - os.path.join(local_dir, '../../tests/data/nexus/201805_WSe2_arpes.nxs') + self.input_file_name = ( + nexus_file + if nexus_file is not None + else os.path.join(local_dir, "../../tests/data/nexus/201805_WSe2_arpes.nxs") + ) self.parser = None self.in_file = None self.d_inq_nd = d_inq_nd @@ -1273,46 +1474,55 @@ def visit_node(self, hdf_name, hdf_node): """Function called by h5py that iterates on each node of hdf5file. It allows h5py visititems function to visit nodes.""" if self.d_inq_nd is None and self.c_inq_nd is None: - process_node(hdf_node, '/' + hdf_name, self.parser, self.logger) - elif (self.d_inq_nd is not None - and hdf_name in (self.d_inq_nd, self.d_inq_nd[1:])): - process_node(hdf_node, '/' + hdf_name, self.parser, self.logger) + process_node(hdf_node, "/" + hdf_name, self.parser, self.logger) + elif self.d_inq_nd is not None and hdf_name in ( + self.d_inq_nd, + self.d_inq_nd[1:], + ): + process_node(hdf_node, "/" + hdf_name, self.parser, self.logger) elif self.c_inq_nd is not None: - attributed_concept = self.c_inq_nd.split('@') + attributed_concept = self.c_inq_nd.split("@") attr = attributed_concept[1] if len(attributed_concept) > 1 else None - elist = get_all_is_a_rel_from_hdf_node(hdf_node, '/' + hdf_name) + elist = get_all_is_a_rel_from_hdf_node(hdf_node, "/" + hdf_name) if elist is None: return fnd_superclass = False fnd_superclass_attr = False for elem in reversed(elist): - tmp_path = elem.get('nxdlbase').split('.nxdl')[0] - con_path = '/NX' + tmp_path.split('NX')[-1] + elem.get('nxdlpath') + tmp_path = elem.get("nxdlbase").split(".nxdl")[0] + con_path = "/NX" + tmp_path.split("NX")[-1] + elem.get("nxdlpath") if fnd_superclass or con_path == attributed_concept[0]: fnd_superclass = True if attr is None: self.hdf_path_list_for_c_inq_nd.append(hdf_name) break for attribute in hdf_node.attrs.keys(): - attr_concept = get_nxdl_child(elem, attribute, nexus_type='attribute', - go_base=False) - if attr_concept is not None and \ - attr_concept.get('nxdlpath').endswith(attr): + attr_concept = get_nxdl_child( + elem, attribute, nexus_type="attribute", go_base=False + ) + if attr_concept is not None and attr_concept.get( + "nxdlpath" + ).endswith(attr): fnd_superclass_attr = True - con_path = '/NX' + tmp_path.split('NX')[-1] \ - + attr_concept.get('nxdlpath') - self.hdf_path_list_for_c_inq_nd.append(hdf_name + "@" + attribute) + con_path = ( + "/NX" + + tmp_path.split("NX")[-1] + + attr_concept.get("nxdlpath") + ) + self.hdf_path_list_for_c_inq_nd.append( + hdf_name + "@" + attribute + ) break if fnd_superclass_attr: break def not_yet_visited(self, root, name): """checking if a new node has already been visited in its path""" - path = name.split('/') + path = name.split("/") for i in range(1, len(path)): - act_path = '/'.join(path[:i]) + act_path = "/".join(path[:i]) # print(act_path+' - '+name) - if root['/' + act_path] == root['/' + name]: + if root["/" + act_path] == root["/" + name]: return False return True @@ -1323,7 +1533,7 @@ def full_visit(self, root, hdf_node, name, func): func(name, hdf_node) if isinstance(hdf_node, h5py.Group): for ch_name, child in hdf_node.items(): - full_name = ch_name if len(name) == 0 else name + '/' + ch_name + full_name = ch_name if len(name) == 0 else name + "/" + ch_name if self.not_yet_visited(root, full_name): self.full_visit(root, child, full_name, func) @@ -1333,9 +1543,10 @@ def process_nexus_master_file(self, parser): self.in_file = h5py.File( self.input_file_name[0] if isinstance(self.input_file_name, list) - else self.input_file_name, 'r' + else self.input_file_name, + "r", ) - self.full_visit(self.in_file, self.in_file, '', self.visit_node) + self.full_visit(self.in_file, self.in_file, "", self.visit_node) if self.d_inq_nd is None and self.c_inq_nd is None: get_default_plotable(self.in_file, self.logger) # To log the provided concept and concepts founded @@ -1347,48 +1558,58 @@ def process_nexus_master_file(self, parser): @click.command() @click.option( - '-f', - '--nexus-file', + "-f", + "--nexus-file", required=False, default=None, - help=('NeXus file with extension .nxs to learn NeXus different concept' - ' documentation and concept.') + help=( + "NeXus file with extension .nxs to learn NeXus different concept" + " documentation and concept." + ), ) @click.option( - '-d', - '--documentation', + "-d", + "--documentation", required=False, default=None, - help=("Definition path in nexus output (.nxs) file. Returns debug" - "log relavent with that definition path. Example: /entry/data/delays") + help=( + "Definition path in nexus output (.nxs) file. Returns debug" + "log relavent with that definition path. Example: /entry/data/delays" + ), ) @click.option( - '-c', - '--concept', + "-c", + "--concept", required=False, default=None, - help=("Concept path from application definition file (.nxdl,xml). Finds out" - "all the available concept definition (IS-A realation) for rendered" - "concept path. Example: /NXarpes/ENTRY/INSTRUMENT/analyser") + help=( + "Concept path from application definition file (.nxdl,xml). Finds out" + "all the available concept definition (IS-A realation) for rendered" + "concept path. Example: /NXarpes/ENTRY/INSTRUMENT/analyser" + ), ) def main(nexus_file, documentation, concept): """The main function to call when used as a script.""" logging_format = "%(levelname)s: %(message)s" stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setLevel(logging.DEBUG) - logging.basicConfig(level=logging.INFO, format=logging_format, handlers=[stdout_handler]) + logging.basicConfig( + level=logging.INFO, format=logging_format, handlers=[stdout_handler] + ) logger = logging.getLogger(__name__) logger.addHandler(stdout_handler) logger.setLevel(logging.DEBUG) logger.propagate = False if documentation and concept: - raise ValueError("Only one option either documentation (-d) or is_a relation " - "with a concept (-c) can be requested.") - nexus_helper = HandleNexus(logger, nexus_file, - d_inq_nd=documentation, - c_inq_nd=concept) + raise ValueError( + "Only one option either documentation (-d) or is_a relation " + "with a concept (-c) can be requested." + ) + nexus_helper = HandleNexus( + logger, nexus_file, d_inq_nd=documentation, c_inq_nd=concept + ) nexus_helper.process_nexus_master_file(None) -if __name__ == '__main__': +if __name__ == "__main__": main() # pylint: disable=no-value-for-parameter From 606f1c5b633a51e5b406458c538fb8d482da0393 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Fri, 16 Jun 2023 00:48:53 +0200 Subject: [PATCH 066/136] linting # Conflicts: # dev_tools/docs/nxdl.py --- dev_tools/utils/nexus.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py index 7b09e30f3..def84b160 100644 --- a/dev_tools/utils/nexus.py +++ b/dev_tools/utils/nexus.py @@ -2,15 +2,16 @@ """Read files from different format and print it in a standard NeXus format """ +import logging import os +import sys +import textwrap import xml.etree.ElementTree as ET from functools import lru_cache from glob import glob -import sys -import logging -import textwrap -import h5py + import click +import h5py class NxdlAttributeError(Exception): From d068ad123ba4eb95ae2ab95f16c51df4e6682d9c Mon Sep 17 00:00:00 2001 From: domna Date: Fri, 16 Jun 2023 10:01:05 +0200 Subject: [PATCH 067/136] Adds pyproject # Conflicts: # .gitignore --- MANIFEST.in | 4 ++++ dev_tools/utils/nexus.py | 21 ++++++-------------- pyproject.toml | 43 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 MANIFEST.in create mode 100644 pyproject.toml diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..20485f628 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +recursive-include applications/ *.nxdl.xml +recursive-include contributed_definitions/ *.nxdl.xml +recursive-include base_classes/ *.nxdl.xml +include ./ *.xsd \ No newline at end of file diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py index def84b160..8e8ef771f 100644 --- a/dev_tools/utils/nexus.py +++ b/dev_tools/utils/nexus.py @@ -1457,13 +1457,11 @@ class HandleNexus: def __init__(self, logger, nexus_file, d_inq_nd=None, c_inq_nd=None): self.logger = logger - local_dir = os.path.abspath(os.path.dirname(__file__)) - self.input_file_name = ( - nexus_file - if nexus_file is not None - else os.path.join(local_dir, "../../tests/data/nexus/201805_WSe2_arpes.nxs") - ) + if nexus_file is None: + raise ValueError("Nexus file not specified. Cannot proceed.") + + self.input_file_name = nexus_file self.parser = None self.in_file = None self.d_inq_nd = d_inq_nd @@ -1558,15 +1556,8 @@ def process_nexus_master_file(self, parser): @click.command() -@click.option( - "-f", - "--nexus-file", - required=False, - default=None, - help=( - "NeXus file with extension .nxs to learn NeXus different concept" - " documentation and concept." - ), +@click.argument( + 'nexus_file', ) @click.option( "-d", diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..6a90ec573 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,43 @@ +[build-system] +requires = ["setuptools>=64.0.1", "setuptools-scm[toml]>=6.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "nexusdefinitions" +dynamic = ["version"] +authors = [ + { name = "NIAC" } +] +description = "Nexus definitions" +readme = "README.md" +license = { file = "LGPL.txt" } +requires-python = "" +classifiers = [ + "Operating System :: OS Independent" +] +dependencies = [ + "lxml", + "pyyaml", + "click>=7.1.2", + "h5py>=3.6.0", + "sphinx>=5", + "sphinx-tabs", + "pytest", + "black>=22.3", + "flake8>=4", + "isort>=5.10", + "click>=7.1.2", +] + +[project.urls] +"Homepage" = "https://nexusformat.org" + +[project.scripts] +read_nexus = "dev_tools.utils.nexus:main" + +[tools.setuptools_scm] +version_scheme = "guess-next-dev" +local_scheme = "node-and-date" + +[tool.setuptools] +packages = ["dev_tools"] From 773a3ec69820c84660f5218b20fa1a2199866f5c Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Fri, 16 Jun 2023 10:16:51 +0200 Subject: [PATCH 068/136] linting --- dev_tools/utils/nexus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py index 8e8ef771f..e797092d1 100644 --- a/dev_tools/utils/nexus.py +++ b/dev_tools/utils/nexus.py @@ -1557,7 +1557,7 @@ def process_nexus_master_file(self, parser): @click.command() @click.argument( - 'nexus_file', + "nexus_file", ) @click.option( "-d", From 97beb5a03898c8a513348d59f186d11c6037047d Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Fri, 16 Jun 2023 10:58:21 +0200 Subject: [PATCH 069/136] adjusted default location of definitions inside the module # Conflicts: # Makefile --- dev_tools/utils/nexus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py index e797092d1..4bcb1c9e9 100644 --- a/dev_tools/utils/nexus.py +++ b/dev_tools/utils/nexus.py @@ -45,7 +45,7 @@ def get_nexus_definitions_path(): return os.environ["NEXUS_DEF_PATH"] except KeyError: # or it should be available locally under the dir 'definitions' local_dir = os.path.abspath(os.path.dirname(__file__)) - return os.path.join(local_dir, f"..{os.sep}definitions") + return os.path.join(local_dir, f"..{os.sep}..") def get_hdf_root(hdf_node): From e058946ab680abb72dab7b17b943300fa48fa381 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Wed, 21 Jun 2023 12:40:56 +0200 Subject: [PATCH 070/136] removing h5py dependency # Conflicts: # dev_tools/docs/nxdl.py # dev_tools/utils/nxdl_utils.py --- dev_tools/utils/nexus.py | 1607 -------------------------------------- 1 file changed, 1607 deletions(-) delete mode 100644 dev_tools/utils/nexus.py diff --git a/dev_tools/utils/nexus.py b/dev_tools/utils/nexus.py deleted file mode 100644 index 4bcb1c9e9..000000000 --- a/dev_tools/utils/nexus.py +++ /dev/null @@ -1,1607 +0,0 @@ -# pylint: disable=too-many-lines -"""Read files from different format and print it in a standard NeXus format -""" - -import logging -import os -import sys -import textwrap -import xml.etree.ElementTree as ET -from functools import lru_cache -from glob import glob - -import click -import h5py - - -class NxdlAttributeError(Exception): - """An exception for throwing an error when an Nxdl attribute is not found.""" - - -def get_app_defs_names(): - """Returns all the AppDef names without their extension: .nxdl.xml""" - app_def_path_glob = ( - f"{get_nexus_definitions_path()}{os.sep}applications{os.sep}*.nxdl*" - ) - contrib_def_path_glob = ( - f"{get_nexus_definitions_path()}{os.sep}" - f"contributed_definitions{os.sep}*.nxdl*" - ) - files = sorted(glob(app_def_path_glob)) + sorted(glob(contrib_def_path_glob)) - return [os.path.basename(file).split(".")[0] for file in files] + ["NXroot"] - - -@lru_cache(maxsize=None) -def get_xml_root(file_path): - """Reducing I/O time by caching technique""" - - return ET.parse(file_path).getroot() - - -def get_nexus_definitions_path(): - """Check NEXUS_DEF_PATH variable. - If it is empty, this function is filling it""" - try: # either given by sys env - return os.environ["NEXUS_DEF_PATH"] - except KeyError: # or it should be available locally under the dir 'definitions' - local_dir = os.path.abspath(os.path.dirname(__file__)) - return os.path.join(local_dir, f"..{os.sep}..") - - -def get_hdf_root(hdf_node): - """Get the root HDF5 node""" - node = hdf_node - while node.name != "/": - node = node.parent - return node - - -def get_hdf_parent(hdf_info): - """Get the parent of an hdf_node in an hdf_info""" - if "hdf_path" not in hdf_info: - return hdf_info["hdf_node"].parent - node = ( - get_hdf_root(hdf_info["hdf_node"]) - if "hdf_root" not in hdf_info - else hdf_info["hdf_root"] - ) - for child_name in hdf_info["hdf_path"].split("/"): - node = node[child_name] - return node - - -def get_parent_path(hdf_name): - """Get parent path""" - return "/".join(hdf_name.split("/")[:-1]) - - -def get_hdf_info_parent(hdf_info): - """Get the hdf_info for the parent of an hdf_node in an hdf_info""" - if "hdf_path" not in hdf_info: - return {"hdf_node": hdf_info["hdf_node"].parent} - node = ( - get_hdf_root(hdf_info["hdf_node"]) - if "hdf_root" not in hdf_info - else hdf_info["hdf_root"] - ) - for child_name in hdf_info["hdf_path"].split("/")[1:-1]: - node = node[child_name] - return {"hdf_node": node, "hdf_path": get_parent_path(hdf_info["hdf_path"])} - - -def get_nx_class_path(hdf_info): - """Get the full path of an HDF5 node using nexus classes - in case of a field, end with the field name""" - hdf_node = hdf_info["hdf_node"] - if hdf_node.name == "/": - return "" - if isinstance(hdf_node, h5py.Group): - return ( - get_nx_class_path(get_hdf_info_parent(hdf_info)) - + "/" - + ( - hdf_node.attrs["NX_class"] - if "NX_class" in hdf_node.attrs.keys() - else hdf_node.name.split("/")[-1] - ) - ) - if isinstance(hdf_node, h5py.Dataset): - return ( - get_nx_class_path(get_hdf_info_parent(hdf_info)) - + "/" - + hdf_node.name.split("/")[-1] - ) - return "" - - -def get_nxdl_entry(hdf_info): - """Get the nxdl application definition for an HDF5 node""" - entry = hdf_info - while ( - isinstance(entry["hdf_node"], h5py.Dataset) - or "NX_class" not in entry["hdf_node"].attrs.keys() - or entry["hdf_node"].attrs["NX_class"] != "NXentry" - ): - entry = get_hdf_info_parent(entry) - if entry["hdf_node"].name == "/": - return "NO NXentry found" - try: - nxdef = entry["hdf_node"]["definition"][()] - return nxdef.decode() - except KeyError: # 'NO Definition referenced' - return "NXentry" - - -def get_nx_class(nxdl_elem): - """Get the nexus class for a NXDL node""" - if "category" in nxdl_elem.attrib.keys(): - return None - try: - return nxdl_elem.attrib["type"] - except KeyError: - return "NX_CHAR" - - -def get_nx_namefit(hdf_name, name, name_any=False): - """Checks if an HDF5 node name corresponds to a child of the NXDL element - uppercase letters in front can be replaced by arbitraty name, but - uppercase to lowercase match is preferred, - so such match is counted as a measure of the fit""" - if name == hdf_name: - return len(name) * 2 - # count leading capitals - counting = 0 - while counting < len(name) and name[counting].upper() == name[counting]: - counting += 1 - if ( - name_any - or counting == len(name) - or (counting > 0 and hdf_name.endswith(name[counting:])) - ): # if potential fit - # count the matching chars - fit = 0 - for i in range(min(counting, len(hdf_name))): - if hdf_name[i].upper() == name[i]: - fit += 1 - else: - break - if fit == min(counting, len(hdf_name)): # accept only full fits as better fits - return fit - return 0 - return -1 # no fit - - -def get_nx_classes(): - """Read base classes from the NeXus definition folder. - Check each file in base_classes, applications, contributed_definitions. - If its category attribute is 'base', then it is added to the list.""" - base_classes = sorted( - glob(os.path.join(get_nexus_definitions_path(), "base_classes", "*.nxdl.xml")) - ) - applications = sorted( - glob(os.path.join(get_nexus_definitions_path(), "applications", "*.nxdl.xml")) - ) - contributed = sorted( - glob( - os.path.join( - get_nexus_definitions_path(), "contributed_definitions", "*.nxdl.xml" - ) - ) - ) - nx_clss = [] - for nexus_file in base_classes + applications + contributed: - root = get_xml_root(nexus_file) - if root.attrib["category"] == "base": - nx_clss.append(str(nexus_file[nexus_file.rindex(os.sep) + 1 :])[:-9]) - nx_clss = sorted(nx_clss) - return nx_clss - - -def get_nx_units(): - """Read unit kinds from the NeXus definition/nxdlTypes.xsd file""" - filepath = f"{get_nexus_definitions_path()}{os.sep}nxdlTypes.xsd" - root = get_xml_root(filepath) - units_and_type_list = [] - for child in root: - for i in child.attrib.values(): - units_and_type_list.append(i) - flag = False - for line in units_and_type_list: - if line == "anyUnitsAttr": - flag = True - nx_units = [] - elif "NX" in line and flag is True: - nx_units.append(line) - elif line == "primitiveType": - flag = False - else: - pass - return nx_units - - -def get_nx_attribute_type(): - """Read attribute types from the NeXus definition/nxdlTypes.xsd file""" - filepath = get_nexus_definitions_path() + "/nxdlTypes.xsd" - root = get_xml_root(filepath) - units_and_type_list = [] - for child in root: - for i in child.attrib.values(): - units_and_type_list.append(i) - flag = False - for line in units_and_type_list: - if line == "primitiveType": - flag = True - nx_types = [] - elif "NX" in line and flag is True: - nx_types.append(line) - elif line == "anyUnitsAttr": - flag = False - else: - pass - return nx_types - - -def get_node_name(node): - """Node - xml node. Returns html documentation name. - Either as specified by the 'name' or taken from the type (nx_class). - Note that if only class name is available, the NX prefix is removed and - the string is converted to UPPER case.""" - if "name" in node.attrib.keys(): - name = node.attrib["name"] - else: - name = node.attrib["type"] - if name.startswith("NX"): - name = name[2:].upper() - return name - - -def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): - """Checks if an HDF5 node name corresponds to a child of the NXDL element - uppercase letters in front can be replaced by arbitraty name, but - uppercase to lowercase match is preferred""" - if class_type and get_nx_class(child) != class_type: - return False - act_htmlname = get_node_name(child) - chk_name = hdf_name or name - if act_htmlname == chk_name: - return True - if not hdf_name: # search for name fits is only allowed for hdf_nodes - return False - try: # check if nameType allows different name - name_any = bool(child.attrib["nameType"] == "any") - except KeyError: - name_any = False - params = [act_htmlname, chk_name, name_any, nxdl_elem, child, name] - return belongs_to_capital(params) - - -def belongs_to_capital(params): - """Checking continues for Upper case""" - (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params - # or starts with capital and no reserved words used - if ( - (name_any or "A" <= act_htmlname[0] <= "Z") - and name != "doc" - and name != "enumeration" - ): - fit = get_nx_namefit(chk_name, act_htmlname, name_any) # check if name fits - if fit < 0: - return False - for child2 in nxdl_elem: - if ( - get_local_name_from_xml(child) != get_local_name_from_xml(child2) - or get_node_name(child2) == act_htmlname - ): - continue - # check if the name of another sibling fits better - name_any2 = ( - "nameType" in child2.attrib.keys() - and child2.attrib["nameType"] == "any" - ) - fit2 = get_nx_namefit(chk_name, get_node_name(child2), name_any2) - if fit2 > fit: - return False - # accept this fit - return True - return False - - -def get_local_name_from_xml(element): - """Helper function to extract the element tag without the namespace.""" - return element.tag[element.tag.rindex("}") + 1 :] - - -def get_own_nxdl_child_reserved_elements(child, name, nxdl_elem): - """checking reserved elements, like doc, enumeration""" - if get_local_name_from_xml(child) == "doc" and name == "doc": - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set("nxdlpath", nxdl_elem.get("nxdlpath") + "/doc") - return child - if get_local_name_from_xml(child) == "enumeration" and name == "enumeration": - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set("nxdlpath", nxdl_elem.get("nxdlpath") + "/enumeration") - return child - return False - - -def get_own_nxdl_child_base_types(child, class_type, nxdl_elem, name, hdf_name): - """checking base types of group, field,m attribute""" - if get_local_name_from_xml(child) == "group": - if ( - class_type is None or (class_type and get_nx_class(child) == class_type) - ) and belongs_to(nxdl_elem, child, name, class_type, hdf_name): - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set( - "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) - ) - return child - if get_local_name_from_xml(child) == "field" and belongs_to( - nxdl_elem, child, name, None, hdf_name - ): - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set( - "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) - ) - return child - if get_local_name_from_xml(child) == "attribute" and belongs_to( - nxdl_elem, child, name, None, hdf_name - ): - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set( - "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) - ) - return child - return False - - -def get_own_nxdl_child( - nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None -): - """Checks if an NXDL child node fits to the specific name (either nxdl or hdf) - name - nxdl name - class_type - nxdl type or hdf classname (for groups, it is obligatory) - hdf_name - hdf name""" - for child in nxdl_elem: - if "name" in child.attrib and child.attrib["name"] == name: - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set( - "nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child) - ) - return child - for child in nxdl_elem: - if "name" in child.attrib and child.attrib["name"] == name: - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - return child - - for child in nxdl_elem: - result = get_own_nxdl_child_reserved_elements(child, name, nxdl_elem) - if result is not False: - return result - if nexus_type and get_local_name_from_xml(child) != nexus_type: - continue - result = get_own_nxdl_child_base_types( - child, class_type, nxdl_elem, name, hdf_name - ) - if result is not False: - return result - return None - - -def find_definition_file(bc_name): - """find the nxdl file corresponding to the name. - Note that it first checks in contributed and goes beyond only if no contributed found - """ - bc_filename = None - for nxdl_folder in ["contributed_definitions", "base_classes", "applications"]: - if os.path.exists( - f"{get_nexus_definitions_path()}{os.sep}" - f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml" - ): - bc_filename = ( - f"{get_nexus_definitions_path()}{os.sep}" - f"{nxdl_folder}{os.sep}{bc_name}.nxdl.xml" - ) - break - return bc_filename - - -def get_nxdl_child( - nxdl_elem, name, class_type=None, hdf_name=None, nexus_type=None, go_base=True -): # pylint: disable=too-many-arguments - """Get the NXDL child node corresponding to a specific name - (e.g. of an HDF5 node,or of a documentation) note that if child is not found in application - definition, it also checks for the base classes""" - # search for possible fits for hdf_nodes : skipped - # only exact hits are returned when searching an nxdl child - own_child = get_own_nxdl_child(nxdl_elem, name, class_type, hdf_name, nexus_type) - if own_child is not None: - return own_child - if not go_base: - return None - bc_name = get_nx_class(nxdl_elem) # check in the base class, app def or contributed - if bc_name[2] == "_": # filter primitive types - return None - if ( - bc_name == "group" - ): # Check if it is the root element. Then send to NXroot.nxdl.xml - bc_name = "NXroot" - bc_filename = find_definition_file(bc_name) - if not bc_filename: - raise ValueError("nxdl file not found in definitions folder!") - bc_obj = ET.parse(bc_filename).getroot() - bc_obj.set("nxdlbase", bc_filename) - if "category" in bc_obj.attrib: - bc_obj.set("nxdlbase_class", bc_obj.attrib["category"]) - bc_obj.set("nxdlpath", "") - return get_own_nxdl_child(bc_obj, name, class_type, hdf_name, nexus_type) - - -def get_required_string(nxdl_elem): - """Check for being REQUIRED, RECOMMENDED, OPTIONAL, NOT IN SCHEMA""" - if nxdl_elem is None: - return "<>" - is_optional = ( - "optional" in nxdl_elem.attrib.keys() and nxdl_elem.attrib["optional"] == "true" - ) - is_minoccurs = ( - "minOccurs" in nxdl_elem.attrib.keys() and nxdl_elem.attrib["minOccurs"] == "0" - ) - is_recommended = ( - "recommended" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["recommended"] == "true" - ) - - if is_recommended: - return "<>" - if is_optional or is_minoccurs: - return "<>" - # default optionality: in BASE CLASSES is true; in APPLICATIONS is false - try: - if nxdl_elem.get("nxdlbase_class") == "base": - return "<>" - except TypeError: - return "<>" - return "<>" - - -def chk_nxdataaxis_v2(hdf_node, name, logger): - """Check if dataset is an axis""" - own_signal = hdf_node.attrs.get("signal") # check for being a Signal - if own_signal is str and own_signal == "1": - logger.debug("Dataset referenced (v2) as NXdata SIGNAL") - own_axes = hdf_node.attrs.get("axes") # check for being an axis - if own_axes is str: - axes = own_axes.split(":") - for i in len(axes): - if axes[i] and name == axes[i]: - logger.debug("Dataset referenced (v2) as NXdata AXIS #%d", i) - return None - ownpaxis = hdf_node.attrs.get("primary") - own_axis = hdf_node.attrs.get("axis") - if own_axis is int: - # also convention v1 - if ownpaxis is int and ownpaxis == 1: - logger.debug("Dataset referenced (v2) as NXdata AXIS #%d", own_axis - 1) - else: - logger.debug( - "Dataset referenced (v2) as NXdata (primary/alternative) AXIS #%d", - own_axis - 1, - ) - return None - - -def chk_nxdataaxis(hdf_node, name, logger): - """NEXUS Data Plotting Standard v3: new version from 2014""" - if not isinstance( - hdf_node, h5py.Dataset - ): # check if it is a field in an NXdata node - return None - parent = hdf_node.parent - if not parent or (parent and not parent.attrs.get("NX_class") == "NXdata"): - return None - signal = parent.attrs.get("signal") # chk for Signal - if signal and name == signal: - logger.debug("Dataset referenced as NXdata SIGNAL") - return None - axes = parent.attrs.get("axes") # check for default Axes - if axes is str: - if name == axes: - logger.debug("Dataset referenced as NXdata AXIS") - return None - elif axes is not None: - for i, j in enumerate(axes): - if name == j: - indices = parent.attrs.get(j + "_indices") - if indices is int: - logger.debug(f"Dataset referenced as NXdata AXIS #{indices}") - else: - logger.debug(f"Dataset referenced as NXdata AXIS #{i}") - return None - indices = parent.attrs.get(name + "_indices") # check for alternative Axes - if indices is int: - logger.debug(f"Dataset referenced as NXdata alternative AXIS #{indices}") - return chk_nxdataaxis_v2(hdf_node, name, logger) # check for older conventions - - -# below there are some functions used in get_nxdl_doc function: -def write_doc_string(logger, doc, attr): - """Simple function that prints a line in the logger if doc exists""" - if doc: - logger.debug("@" + attr + " [NX_CHAR]") - return logger, doc, attr - - -def try_find_units(logger, elem, nxdl_path, doc, attr): - """Try to find if units is defined inside the field in the NXDL element, - otherwise try to find if units is defined as a child of the NXDL element.""" - try: # try to find if units is defined inside the field in the NXDL element - unit = elem.attrib[attr] - if doc: - logger.debug(get_node_concept_path(elem) + "@" + attr + " [" + unit + "]") - elem = None - nxdl_path.append(attr) - except ( - KeyError - ): # otherwise try to find if units is defined as a child of the NXDL element - orig_elem = elem - elem = get_nxdl_child(elem, attr, nexus_type="attribute") - if elem is not None: - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - [" - + get_nx_class(elem) - + "]" - ) - nxdl_path.append(elem) - else: # if no units category were defined in NXDL: - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - REQUIRED, but undefined unit category" - ) - nxdl_path.append(attr) - return logger, elem, nxdl_path, doc, attr - - -def check_attr_name_nxdl(param): - """Check for ATTRIBUTENAME_units in NXDL (normal). - If not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE - is in the SCHEMA, but no units category were defined.""" - (logger, elem, nxdl_path, doc, attr, req_str) = param - orig_elem = elem - elem2 = get_nxdl_child(elem, attr, nexus_type="attribute") - if elem2 is not None: # check for ATTRIBUTENAME_units in NXDL (normal) - elem = elem2 - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - [" - + get_nx_class(elem) - + "]" - ) - nxdl_path.append(elem) - else: - # if not defined, check for ATTRIBUTENAME to see if the ATTRIBUTE - # is in the SCHEMA, but no units category were defined - elem2 = get_nxdl_child(elem, attr[:-6], nexus_type="attribute") - if elem2 is not None: - req_str = "<>" - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - RECOMMENDED, but undefined unit category" - ) - nxdl_path.append(attr) - else: # otherwise: NOT IN SCHEMA - elem = elem2 - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - IS NOT IN SCHEMA" - ) - return logger, elem, nxdl_path, doc, attr, req_str - - -def try_find_default( - logger, orig_elem, elem, nxdl_path, doc, attr -): # pylint: disable=too-many-arguments - """Try to find if default is defined as a child of the NXDL element""" - if elem is not None: - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - [" - + get_nx_class(elem) - + "]" - ) - nxdl_path.append(elem) - else: # if no default category were defined in NXDL: - if doc: - logger.debug(get_node_concept_path(orig_elem) + "@" + attr + " - [NX_CHAR]") - nxdl_path.append(attr) - return logger, elem, nxdl_path, doc, attr - - -def other_attrs( - logger, orig_elem, elem, nxdl_path, doc, attr -): # pylint: disable=too-many-arguments - """Handle remaining attributes""" - if elem is not None: - if doc: - logger.debug( - get_node_concept_path(orig_elem) - + "@" - + attr - + " - [" - + get_nx_class(elem) - + "]" - ) - nxdl_path.append(elem) - else: - if doc: - logger.debug( - get_node_concept_path(orig_elem) + "@" + attr + " - IS NOT IN SCHEMA" - ) - return logger, elem, nxdl_path, doc, attr - - -def check_deprecation_enum_axis(variables, doc, elist, attr, hdf_node): - """Check for several attributes. - deprecation - enums - nxdataaxis""" - logger, elem, path = variables - dep_str = elem.attrib.get("deprecated") # check for deprecation - if dep_str: - if doc: - logger.debug("DEPRECATED - " + dep_str) - for base_elem in elist if not attr else [elem]: # check for enums - sdoc = get_nxdl_child(base_elem, "enumeration", go_base=False) - if sdoc is not None: - if doc: - logger.debug("enumeration (" + get_node_concept_path(base_elem) + "):") - for item in sdoc: - if get_local_name_from_xml(item) == "item": - if doc: - logger.debug("-> " + item.attrib["value"]) - chk_nxdataaxis( - hdf_node, path.split("/")[-1], logger - ) # look for NXdata reference (axes/signal) - for base_elem in elist if not attr else [elem]: # check for doc - sdoc = get_nxdl_child(base_elem, "doc", go_base=False) - if doc: - logger.debug("documentation (" + get_node_concept_path(base_elem) + "):") - logger.debug(sdoc.text if sdoc is not None else "") - return logger, elem, path, doc, elist, attr, hdf_node - - -def get_node_concept_path(elem): - """get the short version of nxdlbase:nxdlpath""" - return str(elem.get("nxdlbase").split("/")[-1] + ":" + elem.get("nxdlpath")) - - -def get_nxdl_attr_doc( # pylint: disable=too-many-arguments,too-many-locals - elem, elist, attr, hdf_node, logger, doc, nxdl_path, req_str, path, hdf_info -): - """Get nxdl documentation for an attribute""" - new_elem = [] - old_elem = elem - for elem_index, act_elem1 in enumerate(elist): - act_elem = act_elem1 - # NX_class is a compulsory attribute for groups in a nexus file - # which should match the type of the corresponding NXDL element - if ( - attr == "NX_class" - and not isinstance(hdf_node, h5py.Dataset) - and elem_index == 0 - ): - elem = None - logger, doc, attr = write_doc_string(logger, doc, attr) - new_elem = elem - break - # units category is a compulsory attribute for any fields - if attr == "units" and isinstance(hdf_node, h5py.Dataset): - req_str = "<>" - logger, act_elem, nxdl_path, doc, attr = try_find_units( - logger, act_elem, nxdl_path, doc, attr - ) - # units for attributes can be given as ATTRIBUTENAME_units - elif attr.endswith("_units"): - logger, act_elem, nxdl_path, doc, attr, req_str = check_attr_name_nxdl( - (logger, act_elem, nxdl_path, doc, attr, req_str) - ) - # default is allowed for groups - elif attr == "default" and not isinstance(hdf_node, h5py.Dataset): - req_str = "<>" - # try to find if default is defined as a child of the NXDL element - act_elem = get_nxdl_child( - act_elem, attr, nexus_type="attribute", go_base=False - ) - logger, act_elem, nxdl_path, doc, attr = try_find_default( - logger, act_elem1, act_elem, nxdl_path, doc, attr - ) - else: # other attributes - act_elem = get_nxdl_child( - act_elem, attr, nexus_type="attribute", go_base=False - ) - if act_elem is not None: - logger, act_elem, nxdl_path, doc, attr = other_attrs( - logger, act_elem1, act_elem, nxdl_path, doc, attr - ) - if act_elem is not None: - new_elem.append(act_elem) - if req_str is None: - req_str = get_required_string(act_elem) # check for being required - if doc: - logger.debug(req_str) - variables = [logger, act_elem, path] - ( - logger, - elem, - path, - doc, - elist, - attr, - hdf_node, - ) = check_deprecation_enum_axis(variables, doc, elist, attr, hdf_node) - elem = old_elem - if req_str is None and doc: - if attr != "NX_class": - logger.debug("@" + attr + " - IS NOT IN SCHEMA") - logger.debug("") - return (req_str, get_nxdl_entry(hdf_info), nxdl_path) - - -def get_nxdl_doc(hdf_info, logger, doc, attr=False): - """Get nxdl documentation for an HDF5 node (or its attribute)""" - hdf_node = hdf_info["hdf_node"] - # new way: retrieve multiple inherited base classes - (class_path, nxdl_path, elist) = get_inherited_nodes( - None, - nx_name=get_nxdl_entry(hdf_info), - hdf_node=hdf_node, - hdf_path=hdf_info["hdf_path"] if "hdf_path" in hdf_info else None, - hdf_root=hdf_info["hdf_root"] if "hdf_root" in hdf_info else None, - ) - elem = elist[0] if class_path and elist else None - if doc: - logger.debug("classpath: " + str(class_path)) - logger.debug( - "NOT IN SCHEMA" - if elem is None - else "classes:\n" + "\n".join(get_node_concept_path(e) for e in elist) - ) - # old solution with a single elem instead of using elist - path = get_nx_class_path(hdf_info) - req_str = None - if elem is None: - if doc: - logger.debug("") - return ("None", None, None) - if attr: - return get_nxdl_attr_doc( - elem, elist, attr, hdf_node, logger, doc, nxdl_path, req_str, path, hdf_info - ) - req_str = get_required_string(elem) # check for being required - if doc: - logger.debug(req_str) - variables = [logger, elem, path] - logger, elem, path, doc, elist, attr, hdf_node = check_deprecation_enum_axis( - variables, doc, elist, attr, hdf_node - ) - return (req_str, get_nxdl_entry(hdf_info), nxdl_path) - - -def get_doc(node, ntype, nxhtml, nxpath): - """Get documentation""" - # URL for html documentation - anchor = "" - for n_item in nxpath: - anchor += n_item.lower() + "-" - anchor = ( - "https://manual.nexusformat.org/classes/", - nxhtml + "#" + anchor.replace("_", "-") + ntype, - ) - if not ntype: - anchor = anchor[:-1] - doc = "" # RST documentation from the field 'doc' - doc_field = node.find("doc") - if doc_field is not None: - doc = doc_field.text - (index, enums) = get_enums(node) # enums - if index: - enum_str = ( - "\n " - + ("Possible values:" if len(enums.split(",")) > 1 else "Obligatory value:") - + "\n " - + enums - + "\n" - ) - else: - enum_str = "" - return anchor, doc + enum_str - - -def print_doc(node, ntype, level, nxhtml, nxpath): - """Print documentation""" - anchor, doc = get_doc(node, ntype, nxhtml, nxpath) - print(" " * (level + 1) + anchor) - preferred_width = 80 + level * 2 - wrapper = textwrap.TextWrapper( - initial_indent=" " * (level + 1), - width=preferred_width, - subsequent_indent=" " * (level + 1), - expand_tabs=False, - tabsize=0, - ) - if doc is not None: - for par in doc.split("\n"): - print(wrapper.fill(par)) - - -def get_namespace(element): - """Extracts the namespace for elements in the NXDL""" - return element.tag[element.tag.index("{") : element.tag.rindex("}") + 1] - - -def get_enums(node): - """Makes list of enumerations, if node contains any. - Returns comma separated STRING of enumeration values, if there are enum tag, - otherwise empty string.""" - # collect item values from enumeration tag, if any - namespace = get_namespace(node) - enums = [] - for enumeration in node.findall(f"{namespace}enumeration"): - for item in enumeration.findall(f"{namespace}item"): - enums.append(item.attrib["value"]) - enums = ",".join(enums) - if enums != "": - return (True, "[" + enums + "]") - return (False, "") # if there is no enumeration tag, returns empty string - - -def add_base_classes(elist, nx_name=None, elem: ET.Element = None): - """Add the base classes corresponding to the last eleme in elist to the list. Note that if - elist is empty, a nxdl file with the name of nx_name or a rather room elem is used if provided - """ - if elist and nx_name is None: - nx_name = get_nx_class(elist[-1]) - # to support recursive defintions, like NXsample in NXsample, the following test is removed - # if elist and nx_name and f"{nx_name}.nxdl.xml" in (e.get('nxdlbase') for e in elist): - # return - if elem is None: - if not nx_name: - return - nxdl_file_path = find_definition_file(nx_name) - if nxdl_file_path is None: - nxdl_file_path = f"{nx_name}.nxdl.xml" - elem = ET.parse(nxdl_file_path).getroot() - elem.set("nxdlbase", nxdl_file_path) - else: - elem.set("nxdlbase", "") - if "category" in elem.attrib: - elem.set("nxdlbase_class", elem.attrib["category"]) - elem.set("nxdlpath", "") - elist.append(elem) - # add inherited base class - if "extends" in elem.attrib and elem.attrib["extends"] != "NXobject": - add_base_classes(elist, elem.attrib["extends"]) - else: - add_base_classes(elist) - - -def set_nxdlpath(child, nxdl_elem): - """ - Setting up child nxdlbase, nxdlpath and nxdlbase_class from nxdl_element. - """ - if nxdl_elem.get("nxdlbase"): - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - child.set("nxdlbase_class", nxdl_elem.get("nxdlbase_class")) - child.set("nxdlpath", nxdl_elem.get("nxdlpath") + "/" + get_node_name(child)) - return child - - -def get_direct_child(nxdl_elem, html_name): - """returns the child of nxdl_elem which has a name - corresponding to the the html documentation name html_name""" - for child in nxdl_elem: - if get_local_name_from_xml(child) in ( - "group", - "field", - "attribute", - ) and html_name == get_node_name(child): - decorated_child = set_nxdlpath(child, nxdl_elem) - return decorated_child - return None - - -def get_field_child(nxdl_elem, html_name): - """returns the child of nxdl_elem which has a name - corresponding to the html documentation name html_name""" - data_child = None - for child in nxdl_elem: - if get_local_name_from_xml(child) != "field": - continue - if get_node_name(child) == html_name: - data_child = set_nxdlpath(child, nxdl_elem) - break - return data_child - - -def get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name): - """returns the child of an NXdata nxdl_elem which has a name - corresponding to the hdf_name""" - nxdata = hdf_node.parent - signals = [] - if "signal" in nxdata.attrs.keys(): - signals.append(nxdata.attrs.get("signal")) - if "auxiliary_signals" in nxdata.attrs.keys(): - for aux_signal in nxdata.attrs.get("auxiliary_signals"): - signals.append(aux_signal) - data_child = get_field_child(nxdl_elem, "DATA") - data_error_child = get_field_child(nxdl_elem, "FIELDNAME_errors") - for signal in signals: - if signal == hdf_name: - return (data_child, 100) - if hdf_name.endswith("_errors") and signal == hdf_name[:-7]: - return (data_error_child, 100) - axes = [] - if "axes" in nxdata.attrs.keys(): - for axis in nxdata.attrs.get("axes"): - axes.append(axis) - axis_child = get_field_child(nxdl_elem, "AXISNAME") - for axis in axes: - if axis == hdf_name: - return (axis_child, 100) - return (None, 0) - - -def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): - """returns the child of nxdl_elem which has a name - corresponding to the the html documentation name html_name""" - bestfit = -1 - bestchild = None - if ( - "name" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["name"] == "NXdata" - and hdf_node is not None - and hdf_node.parent is not None - and hdf_node.parent.attrs.get("NX_class") == "NXdata" - ): - (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) - if fnd_child is not None: - return (fnd_child, fit) - for child in nxdl_elem: - fit = -2 - if get_local_name_from_xml(child) == nexus_type and ( - nexus_type != "group" or get_nx_class(child) == hdf_class_name - ): - name_any = ( - "nameType" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["nameType"] == "any" - ) - fit = get_nx_namefit(hdf_name, get_node_name(child), name_any) - if fit > bestfit: - bestfit = fit - bestchild = set_nxdlpath(child, nxdl_elem) - return (bestchild, bestfit) - - -def walk_elist(elist, html_name): - """Handle elist from low priority inheritance classes to higher""" - for ind in range(len(elist) - 1, -1, -1): - child = get_direct_child(elist[ind], html_name) - if child is None: - # check for names fitting to a superclas definition - main_child = None - for potential_direct_parent in elist: - main_child = get_direct_child(potential_direct_parent, html_name) - if main_child is not None: - (fitting_child, _) = get_best_child( - elist[ind], - None, - html_name, - get_nx_class(main_child), - get_local_name_from_xml(main_child), - ) - if fitting_child is not None: - child = fitting_child - break - elist[ind] = child - if elist[ind] is None: - del elist[ind] - continue - # override: remove low priority inheritance classes if class_type is overriden - if len(elist) > ind + 1 and get_nx_class(elist[ind]) != get_nx_class( - elist[ind + 1] - ): - del elist[ind + 1 :] - # add new base class(es) if new element brings such (and not a primitive type) - if len(elist) == ind + 1 and get_nx_class(elist[ind])[0:3] != "NX_": - add_base_classes(elist) - return elist, html_name - - -def helper_get_inherited_nodes(hdf_info2, elist, pind, attr): - """find the best fitting name in all children""" - hdf_path, hdf_node, hdf_class_path = hdf_info2 - hdf_name = hdf_path[pind] - hdf_class_name = hdf_class_path[pind] - if pind < len(hdf_path) - (2 if attr else 1): - act_nexus_type = "group" - elif pind == len(hdf_path) - 1 and attr: - act_nexus_type = "attribute" - else: - act_nexus_type = "field" if isinstance(hdf_node, h5py.Dataset) else "group" - # find the best fitting name in all children - bestfit = -1 - html_name = None - for ind in range(len(elist) - 1, -1, -1): - newelem, fit = get_best_child( - elist[ind], hdf_node, hdf_name, hdf_class_name, act_nexus_type - ) - if fit >= bestfit and newelem is not None: - html_name = get_node_name(newelem) - return hdf_path, hdf_node, hdf_class_path, elist, pind, attr, html_name - - -def get_hdf_path(hdf_info): - """Get the hdf_path from an hdf_info""" - if "hdf_path" in hdf_info: - return hdf_info["hdf_path"].split("/")[1:] - return hdf_info["hdf_node"].name.split("/")[1:] - - -@lru_cache(maxsize=None) -def get_inherited_nodes( - nxdl_path: str = None, # pylint: disable=too-many-arguments,too-many-locals - nx_name: str = None, - elem: ET.Element = None, - hdf_node=None, - hdf_path=None, - hdf_root=None, - attr=False, -): - """Returns a list of ET.Element for the given path.""" - # let us start with the given definition file - elist = [] # type: ignore[var-annotated] - add_base_classes(elist, nx_name, elem) - nxdl_elem_path = [elist[0]] - - class_path = [] # type: ignore[var-annotated] - if hdf_node is not None: - hdf_info = {"hdf_node": hdf_node} - if hdf_path: - hdf_info["hdf_path"] = hdf_path - if hdf_root: - hdf_root["hdf_root"] = hdf_root - hdf_node = hdf_info["hdf_node"] - hdf_path = get_hdf_path(hdf_info) - hdf_class_path = get_nx_class_path(hdf_info).split("/")[1:] - if attr: - hdf_path.append(attr) - hdf_class_path.append(attr) - path = hdf_path - else: - html_path = nxdl_path.split("/")[1:] - path = html_path - for pind in range(len(path)): - if hdf_node is not None: - hdf_info2 = [hdf_path, hdf_node, hdf_class_path] - [ - hdf_path, - hdf_node, - hdf_class_path, - elist, - pind, - attr, - html_name, - ] = helper_get_inherited_nodes(hdf_info2, elist, pind, attr) - if html_name is None: # return if NOT IN SCHEMA - return (class_path, nxdl_elem_path, None) - else: - html_name = html_path[pind] - elist, html_name = walk_elist(elist, html_name) - if elist: - class_path.append(get_nx_class(elist[0])) - nxdl_elem_path.append(elist[0]) - return (class_path, nxdl_elem_path, elist) - - -def get_node_at_nxdl_path( - nxdl_path: str = None, - nx_name: str = None, - elem: ET.Element = None, - exc: bool = True, -): - """Returns an ET.Element for the given path. - This function either takes the name for the NeXus Application Definition - we are looking for or the root elem from a previously loaded NXDL file - and finds the corresponding XML element with the needed attributes.""" - try: - (class_path, nxdlpath, elist) = get_inherited_nodes(nxdl_path, nx_name, elem) - except ValueError as value_error: - if exc: - raise NxdlAttributeError( - f"Attributes were not found for {nxdl_path}. " - "Please check this entry in the template dictionary." - ) from value_error - return None - if class_path and nxdlpath and elist: - elem = elist[0] - else: - elem = None - if exc: - raise NxdlAttributeError( - f"Attributes were not found for {nxdl_path}. " - "Please check this entry in the template dictionary." - ) - return elem - - -def process_node(hdf_node, hdf_path, parser, logger, doc=True): - """Processes an hdf5 node. - - it logs the node found and also checks for its attributes - - retrieves the corresponding nxdl documentation - TODO: - - follow variants - - NOMAD parser: store in NOMAD""" - hdf_info = {"hdf_path": hdf_path, "hdf_node": hdf_node} - if isinstance(hdf_node, h5py.Dataset): - logger.debug(f"===== FIELD (/{hdf_path}): {hdf_node}") - val = ( - str(hdf_node[()]).split("\n") - if len(hdf_node.shape) <= 1 - else str(hdf_node[0]).split("\n") - ) - logger.debug(f'value: {val[0]} {"..." if len(val) > 1 else ""}') - else: - logger.debug( - f"===== GROUP (/{hdf_path} " - f"[{get_nxdl_entry(hdf_info)}" - f"::{get_nx_class_path(hdf_info)}]): {hdf_node}" - ) - (req_str, nxdef, nxdl_path) = get_nxdl_doc(hdf_info, logger, doc) - if parser is not None and isinstance(hdf_node, h5py.Dataset): - parser( - { - "hdf_info": hdf_info, - "nxdef": nxdef, - "nxdl_path": nxdl_path, - "val": val, - "logger": logger, - } - ) - for key, value in hdf_node.attrs.items(): - logger.debug(f"===== ATTRS (/{hdf_path}@{key})") - val = str(value).split("\n") - logger.debug(f'value: {val[0]} {"..." if len(val) > 1 else ""}') - (req_str, nxdef, nxdl_path) = get_nxdl_doc(hdf_info, logger, doc, attr=key) - if ( - parser is not None - and req_str is not None - and "NOT IN SCHEMA" not in req_str - and "None" not in req_str - ): - parser( - { - "hdf_info": hdf_info, - "nxdef": nxdef, - "nxdl_path": nxdl_path, - "val": val, - "logger": logger, - }, - attr=key, - ) - - -def logger_auxiliary_signal(logger, nxdata): - """Handle the presence of auxiliary signal""" - aux = nxdata.attrs.get("auxiliary_signals") - if aux is not None: - if isinstance(aux, str): - aux = [aux] - for asig in aux: - logger.debug(f"Further auxiliary signal has been identified: {asig}") - return logger - - -def print_default_plotable_header(logger): - """Print a three-lines header""" - logger.debug("========================") - logger.debug("=== Default Plotable ===") - logger.debug("========================") - - -def get_default_plotable(root, logger): - """Get default plotable""" - print_default_plotable_header(logger) - # v3 from 2014 - # nxentry - nxentry = None - default_nxentry_group_name = root.attrs.get("default") - if default_nxentry_group_name: - try: - nxentry = root[default_nxentry_group_name] - except KeyError: - nxentry = None - if not nxentry: - nxentry = entry_helper(root) - if not nxentry: - logger.debug("No NXentry has been found") - return - logger.debug("") - logger.debug("NXentry has been identified: " + nxentry.name) - # nxdata - nxdata = None - nxgroup = nxentry - default_group_name = nxgroup.attrs.get("default") - while default_group_name: - try: - nxgroup = nxgroup[default_group_name] - default_group_name = nxgroup.attrs.get("default") - except KeyError: - pass - if nxgroup == nxentry: - nxdata = nxdata_helper(nxentry) - else: - nxdata = nxgroup - if not nxdata: - logger.debug("No NXdata group has been found") - return - logger.debug("") - logger.debug("NXdata group has been identified: " + nxdata.name) - process_node(nxdata, nxdata.name, None, logger, False) - # signal - signal = None - signal_dataset_name = nxdata.attrs.get("signal") - try: - signal = nxdata[signal_dataset_name] - except (TypeError, KeyError): - signal = None - if not signal: - signal = signal_helper(nxdata) - if not signal: - logger.debug("No Signal has been found") - return - logger.debug("") - logger.debug("Signal has been identified: " + signal.name) - process_node(signal, signal.name, None, logger, False) - logger = logger_auxiliary_signal(logger, nxdata) # check auxiliary_signals - dim = len(signal.shape) - axes = [] # axes - axis_helper(dim, nxdata, signal, axes, logger) - - -def entry_helper(root): - """Check entry related data""" - nxentries = [] - for key in root.keys(): - if ( - isinstance(root[key], h5py.Group) - and root[key].attrs.get("NX_class") - and root[key].attrs["NX_class"] == "NXentry" - ): - nxentries.append(root[key]) - if len(nxentries) >= 1: - return nxentries[0] - return None - - -def nxdata_helper(nxentry): - """Check if nxentry hdf5 object has a NX_class and, if it contains NXdata, - return its value""" - lnxdata = [] - for key in nxentry.keys(): - if ( - isinstance(nxentry[key], h5py.Group) - and nxentry[key].attrs.get("NX_class") - and nxentry[key].attrs["NX_class"] == "NXdata" - ): - lnxdata.append(nxentry[key]) - if len(lnxdata) >= 1: - return lnxdata[0] - return None - - -def signal_helper(nxdata): - """Check signal related data""" - signals = [] - for key in nxdata.keys(): - if isinstance(nxdata[key], h5py.Dataset): - signals.append(nxdata[key]) - if ( - len(signals) == 1 - ): # v3: as there was no selection given, only 1 data field shall exists - return signals[0] - if len(signals) > 1: # v2: select the one with an attribute signal="1" attribute - for sig in signals: - if ( - sig.attrs.get("signal") - and sig.attrs.get("signal") is str - and sig.attrs.get("signal") == "1" - ): - return sig - return None - - -def find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list): - """Finds axis that have defined dimensions""" - # find those with attribute axis= actual dimension number - lax = [] - for key in nxdata.keys(): - if isinstance(nxdata[key], h5py.Dataset): - try: - if nxdata[key].attrs["axis"] == a_item + 1: - lax.append(nxdata[key]) - except KeyError: - pass - if len(lax) == 1: - ax_list.append(lax[0]) - # if there are more alternatives, prioritise the one with an attribute primary="1" - elif len(lax) > 1: - for sax in lax: - if sax.attrs.get("primary") and sax.attrs.get("primary") == 1: - ax_list.insert(0, sax) - else: - ax_list.append(sax) - - -def get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list): - """Gets either single or multiple axes from the NXDL""" - try: - if isinstance(ax_datasets, str): # single axis is defined - # explicite definition of dimension number - ind = nxdata.attrs.get(ax_datasets + "_indices") - if ind and ind is int: - if ind == a_item: - ax_list.append(nxdata[ax_datasets]) - elif a_item == 0: # positional determination of the dimension number - ax_list.append(nxdata[ax_datasets]) - else: # multiple axes are listed - # explicite definition of dimension number - for aax in ax_datasets: - ind = nxdata.attrs.get(aax + "_indices") - if ind and isinstance(ind, int): - if ind == a_item: - ax_list.append(nxdata[aax]) - if not ax_list: # positional determination of the dimension number - ax_list.append(nxdata[ax_datasets[a_item]]) - except KeyError: - pass - return ax_list - - -def axis_helper(dim, nxdata, signal, axes, logger): - """Check axis related data""" - for a_item in range(dim): - ax_list = [] - ax_datasets = nxdata.attrs.get("axes") # primary axes listed in attribute axes - ax_list = get_single_or_multiple_axes(nxdata, ax_datasets, a_item, ax_list) - for attr in nxdata.attrs.keys(): # check for corresponding AXISNAME_indices - if ( - attr.endswith("_indices") - and nxdata.attrs[attr] == a_item - and nxdata[attr.split("_indices")[0]] not in ax_list - ): - ax_list.append(nxdata[attr.split("_indices")[0]]) - # v2 # check for ':' separated axes defined in Signal - if not ax_list: - try: - ax_datasets = signal.attrs.get("axes").split(":") - ax_list.append(nxdata[ax_datasets[a_item]]) - except (KeyError, AttributeError): - pass - if not ax_list: # check for axis/primary specifications - find_attrib_axis_actual_dim_num(nxdata, a_item, ax_list) - axes.append(ax_list) - logger.debug("") - logger.debug( - f"For Axis #{a_item}, {len(ax_list)} axes have been identified: {str(ax_list)}" - ) - - -def get_all_is_a_rel_from_hdf_node(hdf_node, hdf_path): - """Return list of nxdl concept paths for a nxdl element which corresponds to - hdf node. - """ - hdf_info = {"hdf_path": hdf_path, "hdf_node": hdf_node} - (_, _, elist) = get_inherited_nodes( - None, - nx_name=get_nxdl_entry(hdf_info), - hdf_node=hdf_node, - hdf_path=hdf_info["hdf_path"] if "hdf_path" in hdf_info else None, - hdf_root=hdf_info["hdf_root"] if "hdf_root" in hdf_info else None, - ) - return elist - - -def hdf_node_to_self_concept_path(hdf_info, logger): - """Get concept or nxdl path from given hdf_node.""" - # The bellow logger is for deactivatine unnecessary debug message above - if logger is None: - logger = logging.getLogger(__name__) - logger.setLevel(logging.INFO) - (_, _, nxdl_path) = get_nxdl_doc(hdf_info, logger, None) - con_path = "" - if nxdl_path: - for nd_ in nxdl_path: - con_path = con_path + "/" + get_node_name(nd_) - return con_path - - -class HandleNexus: - """documentation""" - - def __init__(self, logger, nexus_file, d_inq_nd=None, c_inq_nd=None): - self.logger = logger - - if nexus_file is None: - raise ValueError("Nexus file not specified. Cannot proceed.") - - self.input_file_name = nexus_file - self.parser = None - self.in_file = None - self.d_inq_nd = d_inq_nd - self.c_inq_nd = c_inq_nd - # Aggregating hdf path corresponds to concept query node - self.hdf_path_list_for_c_inq_nd = [] - - def visit_node(self, hdf_name, hdf_node): - """Function called by h5py that iterates on each node of hdf5file. - It allows h5py visititems function to visit nodes.""" - if self.d_inq_nd is None and self.c_inq_nd is None: - process_node(hdf_node, "/" + hdf_name, self.parser, self.logger) - elif self.d_inq_nd is not None and hdf_name in ( - self.d_inq_nd, - self.d_inq_nd[1:], - ): - process_node(hdf_node, "/" + hdf_name, self.parser, self.logger) - elif self.c_inq_nd is not None: - attributed_concept = self.c_inq_nd.split("@") - attr = attributed_concept[1] if len(attributed_concept) > 1 else None - elist = get_all_is_a_rel_from_hdf_node(hdf_node, "/" + hdf_name) - if elist is None: - return - fnd_superclass = False - fnd_superclass_attr = False - for elem in reversed(elist): - tmp_path = elem.get("nxdlbase").split(".nxdl")[0] - con_path = "/NX" + tmp_path.split("NX")[-1] + elem.get("nxdlpath") - if fnd_superclass or con_path == attributed_concept[0]: - fnd_superclass = True - if attr is None: - self.hdf_path_list_for_c_inq_nd.append(hdf_name) - break - for attribute in hdf_node.attrs.keys(): - attr_concept = get_nxdl_child( - elem, attribute, nexus_type="attribute", go_base=False - ) - if attr_concept is not None and attr_concept.get( - "nxdlpath" - ).endswith(attr): - fnd_superclass_attr = True - con_path = ( - "/NX" - + tmp_path.split("NX")[-1] - + attr_concept.get("nxdlpath") - ) - self.hdf_path_list_for_c_inq_nd.append( - hdf_name + "@" + attribute - ) - break - if fnd_superclass_attr: - break - - def not_yet_visited(self, root, name): - """checking if a new node has already been visited in its path""" - path = name.split("/") - for i in range(1, len(path)): - act_path = "/".join(path[:i]) - # print(act_path+' - '+name) - if root["/" + act_path] == root["/" + name]: - return False - return True - - def full_visit(self, root, hdf_node, name, func): - """visiting recursivly all children, but avoiding endless cycles""" - # print(name) - if len(name) > 0: - func(name, hdf_node) - if isinstance(hdf_node, h5py.Group): - for ch_name, child in hdf_node.items(): - full_name = ch_name if len(name) == 0 else name + "/" + ch_name - if self.not_yet_visited(root, full_name): - self.full_visit(root, child, full_name, func) - - def process_nexus_master_file(self, parser): - """Process a nexus master file by processing all its nodes and their attributes""" - self.parser = parser - self.in_file = h5py.File( - self.input_file_name[0] - if isinstance(self.input_file_name, list) - else self.input_file_name, - "r", - ) - self.full_visit(self.in_file, self.in_file, "", self.visit_node) - if self.d_inq_nd is None and self.c_inq_nd is None: - get_default_plotable(self.in_file, self.logger) - # To log the provided concept and concepts founded - if self.c_inq_nd is not None: - for hdf_path in self.hdf_path_list_for_c_inq_nd: - self.logger.info(hdf_path) - self.in_file.close() - - -@click.command() -@click.argument( - "nexus_file", -) -@click.option( - "-d", - "--documentation", - required=False, - default=None, - help=( - "Definition path in nexus output (.nxs) file. Returns debug" - "log relavent with that definition path. Example: /entry/data/delays" - ), -) -@click.option( - "-c", - "--concept", - required=False, - default=None, - help=( - "Concept path from application definition file (.nxdl,xml). Finds out" - "all the available concept definition (IS-A realation) for rendered" - "concept path. Example: /NXarpes/ENTRY/INSTRUMENT/analyser" - ), -) -def main(nexus_file, documentation, concept): - """The main function to call when used as a script.""" - logging_format = "%(levelname)s: %(message)s" - stdout_handler = logging.StreamHandler(sys.stdout) - stdout_handler.setLevel(logging.DEBUG) - logging.basicConfig( - level=logging.INFO, format=logging_format, handlers=[stdout_handler] - ) - logger = logging.getLogger(__name__) - logger.addHandler(stdout_handler) - logger.setLevel(logging.DEBUG) - logger.propagate = False - if documentation and concept: - raise ValueError( - "Only one option either documentation (-d) or is_a relation " - "with a concept (-c) can be requested." - ) - nexus_helper = HandleNexus( - logger, nexus_file, d_inq_nd=documentation, c_inq_nd=concept - ) - nexus_helper.process_nexus_master_file(None) - - -if __name__ == "__main__": - main() # pylint: disable=no-value-for-parameter From c68374e9fbe997035a724fbf5675e48212bde31a Mon Sep 17 00:00:00 2001 From: Sherjeel Shabih Date: Wed, 5 Jul 2023 15:09:03 +0200 Subject: [PATCH 071/136] Move all of nyaml2nxdl files in a folder # Conflicts: # dev_tools/nyaml2nxdl/__init__.py # dev_tools/nyaml2nxdl/comment_collector.py # dev_tools/nyaml2nxdl/nyaml2nxdl.py # dev_tools/nyaml2nxdl/nyaml2nxdl_backward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_forward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_helper.py --- README.md => dev_tools/nyaml2nxdl/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README.md => dev_tools/nyaml2nxdl/README.md (100%) diff --git a/README.md b/dev_tools/nyaml2nxdl/README.md similarity index 100% rename from README.md rename to dev_tools/nyaml2nxdl/README.md From e15d75c21ad35f61d30cadb17e783f6b94bbeefa Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Wed, 12 Jul 2023 16:30:22 +0200 Subject: [PATCH 072/136] fixing typos and dependencies # Conflicts: # README.md # dev_tools/nyaml2nxdl/README.md # dev_tools/nyaml2nxdl/nyaml2nxdl.py --- dev_tools/nyaml2nxdl/README.md => README.md | 0 pyproject.toml | 1 + 2 files changed, 1 insertion(+) rename dev_tools/nyaml2nxdl/README.md => README.md (100%) diff --git a/dev_tools/nyaml2nxdl/README.md b/README.md similarity index 100% rename from dev_tools/nyaml2nxdl/README.md rename to README.md diff --git a/pyproject.toml b/pyproject.toml index 6a90ec573..e691189b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ dependencies = [ "h5py>=3.6.0", "sphinx>=5", "sphinx-tabs", + "sphinx-toolbox", "pytest", "black>=22.3", "flake8>=4", From 771aef574a7592aa4d7d48736b0ea7b0b9a49685 Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Thu, 20 Jul 2023 11:12:35 +0200 Subject: [PATCH 073/136] Typo fixes # Conflicts: # dev_tools/docs/nxdl_index.py --- dev_tools/docs/nxdl_index.py | 38 ++---------------------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index e3f9c9371..bcb8ac666 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -66,22 +66,13 @@ def nxdl_indices() -> Dict[str, dict]: else: file = "" print("---------++++++++-", section) - if file.endswith(("applications/index.rst", "base_classes/index.rst")): - rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") - rst_lines.append(f"{indentation}mpes-structure\n") - rst_lines.append(f"{indentation}apm-structure\n") - if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") + rst_lines.append(f"{indentation}ellipsometry-structure\n") rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") - rst_lines.append(f"{indentation}sts-structure\n") rst_lines.append(f"{indentation}cgms-structure\n") - rst_lines.append(f"{indentation}icme-structure\n") - rst_lines.append(f"{indentation}sample-prep-structure\n") for cname in sorted(classes): rst_lines.append(f"{indentation}{cname}\n") @@ -119,18 +110,6 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: *might* be used in an instance of that class. Consider the base classes as a set of *components* that are used to construct a data file. - -Some contributions are grouped together: - :ref:`Optical Spectroscopy ` - - :ref:`Multi-dimensional Photoemission Spectroscopy ` - - :ref:`Atomprobe Microscopy ` - - :ref:`Electron Microscopy ` - -and others are simply listed here: - """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "applications": """ @@ -159,19 +138,6 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: In application definitions involving raw data, write the raw data in the :ref:`NXinstrument` tree and then link to it from the location(s) defined in the relevant application definition. - -Some contributions are grouped together: - :ref:`Optical Spectroscopy ` - - :ref:`Multi-dimensional Photoemission Spectroscopy ` - - :ref:`Atomprobe Microscopy ` - - :ref:`Electron Microscopy ` - - -and others are simply listed here: - """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "contributed_definitions": """ @@ -194,7 +160,7 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: and acceptance as either a base class or application definition. Some contributions are grouped together: - :ref:`Optical Spectroscopy ` + :ref:`Optical Spectroscopy ` :ref:`Multi-dimensional Photoemission Spectroscopy ` From cd7f763fb043ac25c3b54655d82969de24e51a7b Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Mon, 24 Jul 2023 13:30:35 +0200 Subject: [PATCH 074/136] Remaining refactoring to remove unnecessary duplicates of old fairmat-proposal introductions and explanations which have now been replaced by the respective subgroups in contributed_classes, fixed typos, rerouted ci pipeline to point to fairmat branch # Conflicts: # manual/source/apm-structure.rst # manual/source/cgms-structure.rst # manual/source/classes/applications/optical-spectroscopy-structure.rst # manual/source/classes/contributed_definitions/apm-structure.rst # manual/source/classes/contributed_definitions/cgms-structure.rst # manual/source/classes/contributed_definitions/em-structure.rst # manual/source/classes/contributed_definitions/icme-structure.rst # manual/source/classes/contributed_definitions/sample-prep-structure.rst # manual/source/classes/contributed_definitions/transport-structure.rst # manual/source/conf.py # manual/source/em-structure.rst # manual/source/index.rst # manual/source/laboratory-structure.rst # manual/source/mpes-structure.rst # manual/source/north-structure.rst # manual/source/stm-structure.rst # manual/source/transport-structure.rst --- .github/workflows/ci.yaml | 4 +- dev_tools/docs/nxdl_index.py | 2 + .../optical-spectroscopy-structure.rst | 185 ---------- .../contributed_definitions/apm-structure.rst | 339 +++++++++++++----- .../icme-structure.rst | 25 -- .../mpes-structure.rst | 4 +- .../sample-prep-structure.rst | 18 - manual/source/icme-structure.rst | 9 + manual/source/img/FAIRmat_new.png | Bin 0 -> 24990 bytes manual/source/img/FAIRmat_new_with_text.png | Bin 0 -> 29306 bytes 10 files changed, 256 insertions(+), 330 deletions(-) delete mode 100644 manual/source/classes/applications/optical-spectroscopy-structure.rst delete mode 100644 manual/source/classes/contributed_definitions/icme-structure.rst delete mode 100644 manual/source/classes/contributed_definitions/sample-prep-structure.rst create mode 100644 manual/source/icme-structure.rst create mode 100644 manual/source/img/FAIRmat_new.png create mode 100644 manual/source/img/FAIRmat_new_with_text.png diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4da534ddf..489cac82a 100755 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,10 +3,10 @@ name: Documentation build on: push: branches: - - main # push commit to the main branch + - fairmat # push commit to the fairmat branch pull_request: branches: - - main # pull request to the main branch + - fairmat # pull request to the fairmat branch workflow_dispatch: # allow manual triggering inputs: deploy: diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index bcb8ac666..259464c6b 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -73,6 +73,8 @@ def nxdl_indices() -> Dict[str, dict]: rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") rst_lines.append(f"{indentation}cgms-structure\n") + rst_lines.append(f"{indentation}icme-structure\n") + rst_lines.append(f"{indentation}sample-prep-structure\n") for cname in sorted(classes): rst_lines.append(f"{indentation}{cname}\n") diff --git a/manual/source/classes/applications/optical-spectroscopy-structure.rst b/manual/source/classes/applications/optical-spectroscopy-structure.rst deleted file mode 100644 index 8208bc35b..000000000 --- a/manual/source/classes/applications/optical-spectroscopy-structure.rst +++ /dev/null @@ -1,185 +0,0 @@ -.. _Optical-Spectroscopy-Structure-APP: - -==================== -Optical Spectroscopy -==================== - -.. index:: - Ellipsometry - Raman - DispersiveMaterial - - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS - - -.. _Ellipsometry-APP: - -Ellipsometry -############ - -Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. -The measurements are based on determining how the polarization state of light changes upon transmission and reflection. -Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. - -In the application definition, we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. - -.. _Raman-APP: - -Raman -############ - -Raman spectroscopy is a characterization method to analyze vibrational properties for liquids, gases, or solids. -The measurements is based on the inelastic light scattering due to the material's vibrations. -Interpretation can be done based on peaks, which represent the phonon properties (intensity, center, width). - -The application definition contains a minimum of descriptive elements required to understand Raman spectroscopy measurements. - - -Application Definitions ------------------------ - - - :ref:`NXellipsometry`: - An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - - - -Base Classes ------------- - -This is the set of base classes for describing an optical experiment. - - :ref:`NXbeam` - Beam properties such as intensity, polarization, wavelength or direction. - - :ref:`NXdetector` - A detector for signal detection. - - :ref:`NXsource` - A light source such as laser, lamp or LED. - - :ref:`NXmonochromator` - A monochromator is often used to energetically disperse the scattered or emitted light. - - :ref:`NXsensor` - Specify external parameters that have influenced the sample such as - varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. - - - -.. _DispersiveMaterial-APP: - -Dispersive Material -################### - -A dispersive material is a description for the optical dispersion of materials. -This description may be used to store optical model data from an ellipsometric analysis -(or any other technique) or to build a database of optical constants for optical properties of materials. - -Application Definition ----------------------- - - :ref:`NXdispersive_material`: - An application definition to describe the dispersive properties of a material. - The material may be isotropic, uniaxial or biaxial. Hence, it may contain up - to three dispersive functions or tables. - - - -Base Classes ------------- - -There is a set of base classes for describing a dispersion. - - :ref:`NXdispersion` - This is an umbrella base class for a group of dispersion functions to describe the material. - For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. - If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. - This allows for, e.g. splitting real and imaginary parts and describing them seperately or - adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). - - :ref:`NXdispersion_function` - This dispersion is described by a function and its single and repeated parameter values. - It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` - (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. - - :ref:`NXdispersion_single_parameter` - This denotes a parameter which is used outside the summed part of a dispersion function, - e.g. ``eps_inf`` in the formula example above. - - :ref:`NXdispersion_repeated_parameter` - This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. - ``A`` and ``B`` are repeated parameters in the formula above. - - :ref:`NXdispersion_table` - This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. - -Formula Grammar ---------------- - -Below you find a grammar to which the formula should adhere and which can be used to parse and -evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be -filled with the respective single and repeated params from the stored data. -The grammer is written in the `EBNF `_ dialect -of `Lark `_, which is a parsing toolkit for python. -It is easily translatable to general EBNF and other parser generator dialects. -`Here `_ is a reference implementation in Rust/Python with a -`grammar `_ -written in `lalrpop `_. - -.. code-block:: - - ?assignment: "eps" "=" kkr_expression -> eps - | "n" "=" kkr_expression -> n - - ?kkr_expression: expression - | "" "+" "1j" "*" term -> kkr_term - - ?expression: term - | expression "+" term -> add - | expression "-" term -> sub - - ?term: factor - | term "*" factor -> mul - | term "/" factor -> div - - ?factor: power - | power "**" power -> power - - - ?power: "(" expression ")" - | FUNC "(" expression ")" -> func - | "sum" "[" repeated_expression "]" -> sum_expr - | NAME -> single_param_name - | SIGNED_NUMBER -> number - | BUILTIN -> builtin - - ?repeated_expression: repeated_term - | repeated_expression "+" repeated_term -> add - | repeated_expression "-" repeated_term -> sub - - - ?repeated_term: repeated_factor - | repeated_term "*" repeated_factor -> mul - | repeated_term "/" repeated_factor -> div - - ?repeated_factor: repeated_power - | repeated_power "**" repeated_power -> power - - ?repeated_power: "(" repeated_expression ")" - | FUNC "(" repeated_expression ")" -> func - | SIGNED_NUMBER -> number - | NAME -> param_name - | BUILTIN -> builtin - - FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" - BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" - - %import common.CNAME -> NAME - %import common.SIGNED_NUMBER - %import common.WS_INLINE - - %ignore WS_INLINE - diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index 4ce8dc1d3..10e2c77c3 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -1,35 +1,38 @@ .. _Apm-Structure: -===================== +========================= Atom-probe tomography -===================== +========================= .. index:: IntroductionApm ApmAppDef ApmBC - StatusQuoApm + WhatHasBeenAchieved ApmParaprobeAppDef - ApmGermanNfdi + ApmParaprobeNewBC + NextStep + + + .. _IntroductionApm: Introduction -############ +############## -Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, -steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. -The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. +Set of data storage objects to describe the acquisition/measurement side, the reconstruction, and the ranging for atom probe microscopy experiments. The data storage objects can be useful as well for field-ion microscopy experiments. .. _ApmAppDef: Application Definition ###################### +It is proposed to use one application definition to serve atom probe tomography +and field-ion microscopy measurements, i.e. the data collection with the instrument: + :ref:`NXapm`: - A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. The structure of the schema has been designed to also document a simulation of an atom probe - experiment. Having a combined schema for the measurement and the simulation is beneficial to document that - there are many similarities between the measurement and a computer simulation of it. + A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. .. _ApmBC: @@ -40,144 +43,284 @@ The following base classes are proposed to support modularizing the storage of p :ref:`NXchamber`: A base class to describe a component of the instrument which houses other components. - A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities - for storing and loading specimens. + A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. - :ref:`NXcoordinate_system_set`: - Base classes to describe different coordinate systems used and/or to be harmonized + :ref:`NXcoordinate_system_set` + A base class to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. :ref:`NXion`: - A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. - For the usage in atom probe research the maximum number of atoms supported building a molecular ion - is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with - which all possible nuclides (stable, radioactive, or synthetically generated ones) can be described. + A base class to describe charged molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion + is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with + which all possible isotopes can be described. :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about - a component or device of an instrument. + A base class to bundle manufacturer/technology-partner-specific details about a + component or device of an instrument. + :ref:`NXpeak`: + A base class to describe peaks mathematically to detail how peaks in + mass-to-charge-state ratio histograms (aka mass spectra) are + defined and labelled as iontypes. -Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of -data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named -instances of the :ref:`NXprocess` base class. + :ref:`NXpump`: + A base class to describe details about pump(s) of an instrument. -Several base classes were defined to document processing of atom probe data with established algorithms: + :ref:`NXpulser_apm`: + A base class to describe the high-voltage and/or laser pulsing capabilities of + an atom probe microscope. + :ref:`NXreflectron`: + A base class to describe a kinetic-energy-sensitive filtering device + for time of flight (ToF) mass spectrometry. -These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented -to enable reproducible research, if possible even numerical reproducibility of the results, -and learn how pieces of information are connected. In what follows, an example is presented how an -open-source community software can be modified to use descriptions of these computational steps. + :ref:`NXstage_lab`: + A base class to describe the specimen fixture including the cryo-head. + Nowadays, these stages represent small-scale laboratory platforms. + Therefore, there is a need to define the characteristics of such stages in more detail, + especially in light of in-situ experiments. Many similarities exists between a stage + in an electron microscope and one in an atom probe instrument. Both offer fixture functionalities and additional components for applying e.g. stimuli on the specimen. -A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe -data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: +Microscopy experiments, not only taking into account those performed on commercial instruments, offer the user usually to apply a set of data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. -The respective research software here is the `paraprobe-toolbox `_ -The software is developed by `M. Kühbach et al. `_. -For atom probe research the proposal can also serve as a blue print how computational steps of other software -tool including commercial ones could be developed further to benefit from NeXus. +Like every research community data processing steps are essential to transform measurements +into knowledge. These processing steps should be documented to enable reproducible research +and learn how pieces of information were connected. In what follows, an example is presented +how an open-source community software can be modified to use descriptions of these computational +steps. The respective research software here is the `paraprobe-toolbox `_ .. _IntroductionApmParaprobe: apmtools ######## -The paraprobe-toolbox is an example of an open-source parallelized software for analyzing -point cloud data, for assessing meshes in 3D continuum space, and for studying the effects of -parameterization on descriptors of micro- and nanoscale structural features (crystal defects) -within materials when characterized and studied with atom probe. +One tool is the paraprobe-toolbox software package in the the apmtools container. +The software is developed by `M. Kühbach et al. `_. + +Here we show how NeXus is used to consistently define application definitions for scientific software +in the field of atom probe. In this community the paraprobe-toolbox is an example of an +open-source parallelized software for analyzing point cloud data, for assessing meshes in +3D continuum space, and for studying the effects of parameterization on descriptors +which describe the micro- and nanostructure of materials that are studied with +atom probe microscopy. The need for a thorough documentation of the tools in not only the paraprobe-toolbox was motivated by several needs: -First, users of software would like to better understand and also be able to study for themselves -which individual parameters and settings for each tool exist and how configuring these -affects analyses quantitatively. This stresses the aspect how to improve documentation. +First, users of software would like to better understand and also be able to +study for themselves which individual parameters and settings for each tool exist +and how configuring these affects their analyses quantitatively. -Second, scientific software like paraprobe-toolbox implement numerical/algorithmical -(computational) workflows whereby data coming from multiple input sources -(like previous analysis results) are processed and carried through more involved analyses -within several steps inside the tool. The tool then creates output as files. This -provenance and workflow should be documented. +Second, scientific software like the tools in the paraprobe-toolbox implement a +numerical/algorithmical (computational) workflow whereby data from multiple input sources +(like previous analysis results) are processed and carried through more involved analysis +within several steps inside the tool. The tool then creates output as files. Individual tools of paraprobe-toolbox are developed in C/C++ and/or Python. Provenance tracking is useful as it is one component and requirement for making -workflows exactly numerically reproducible and thus to enable reproducibility (the "R" -of the FAIR principles of data stewardship). +workflows exactly numerically reproducible and thereby empower scientists +to fulfill better the "R", i.e. reproducibility of their daily FAIR research practices. -For tools of the paraprobe-toolbox each workflow step is a pair or triple of sub-steps: -1. The creation of a configuration file. -2. The actual analysis using the Python/or C/C++ tools. -3. The optional analyses/visualization of the results based on data in NeXus/HDF5 files generated by each tool. +The paraprobe-toolbox is one example of a software which implements a workflow +via a sequence of operations executed within a jupyter notebook +(or Python script respectively). Specifically, individual tools are chained. +Convenience functions are available to create well-defined input/configuration +files for each tool. These config files instruct the tool upon processing. -.. _StatusQuoApm: +In this design, each workflow step (with a tool) is in fact a pair (or triple) of +at least two sub-steps: i) the creation of a configuration file, +ii) the actual analysis using the Python/or C/C++ tools, +iii) the optional post-processing/visualizing of the results inside the NeXus/HDF5 +files generated from each tool run using other software. -What has been achieved so far? -############################## -This proposal summarizes work of members of the FAIRmat project, which is part of the `German -National Research Data Infrastructure `_. The here detailed -proposal documents how all tools of the paraprobe-toolbox were modified to generate -only well-defined configuration files as accepted input and yield specifically formatted output -files according to the following NeXus application definitions. +.. _WhatHasBeenAchieved: -Data and metadata between the tools are exchanged with NeXus/HDF5 files. This means that data -inside HDF5 binary containers are named, formatted, and hierarchically structured according -to application definitions. +What has been achieved so far? +############################## -For example the application definition NXapm_paraprobe_config_surfacer specifies +This proposal summarizes work of members of the FAIRmat project, which is part +of the German National Research Data Infrastructure aimed at a change of the paraprobe-toolbox +and its interaction with files for all tools so that only well-defined configuration files +are accepted as input and results end up as specifically formatted output. For this +NeXus application definitions are used. + +Data and metadata between the tools are exchanged with NeXus/HDF5 files. +Specifically, we created for each tool an application definition (see below) +which details all possible settings and options for the configuration as to +guide users. The config(uration) files are currently implemented as HDF5 files, +whose content matches to the naming conventions of the respective `config` application +definition for each tool. As an example NXapm_paraprobe_config_surfacer specifies how a configuration file for the paraprobe-surfacer tool should be formatted -and which parameters it contains including optionality and cardinality constraints. +and which parameter it should and/or may contain. -Thereby, each config file uses a controlled vocabulary of terms. Furthermore, -the config files store a SHA256 checksum for each input file. This implements a full -provenance tracking on the input files along the workflow. +That is each config file uses a controlled vocabulary of terms. Furthermore, +the config files store a SHA256 checksum for each input file. +This implements a full provenance tracking on the input files along the +processing chain/workflow. -As an example, a user may first range their reconstruction and then compute spatial +As an example, a user may first range their reconstruction and then compute correlation functions. The config file for the ranging tool stores the files which hold the reconstructed ion position and ranging definitions. -The ranging tool generates a results file with the labels of each molecular ion. +The ranging tool generates a results file with the ion type labels stored. This results file is formatted according to the tool-specific `results` -application definition. The generated results file and the reconstruction is -imported by the spatial statistics tool which again keeps track of all files -and reports its results in a spatial statistics tool results file. +application definition. This results file and the reconstruction is +imported by the spatial statistics tool which again keeps track of all files. -This design makes it possible to rigorously trace which numerical results were achieved -with specific inputs and settings using specifically-versioned tools. Noteworthy -this includes Y-junction on a graph which is where multiple input sources are -combined to generate new results. - -We are convinced that defining, documenting, using, and sharing application definitions -is useful and future-proof strategy for software development and data analyses as it enables -automated provenance tracking which happens silently in the background. +This design makes it possible to rigorously trace which numerical results +were achieved with a specific input and settings using specifically-versioned tools. -Base classes have been defined to group common pieces of information for each tool of the -toolbox. For each tool we define a pair of base classes. One for the configuration (input) side -and one for the results (output) side: +We understand that this additional handling of metadata and provenance tracking +may not be at first glance super relevant for scientists or appears to be an +unnecessarily complex feature. There is indeed an additional layer of work which +came with the development and maintenance of this functionality. +However, we are convinced that this is the preferred way of performing software +development and data analyses as it enables users to take advantage of a completely +automated provenance tracking which happens silently in the background. .. _ApmParaprobeAppDef: Application Definitions ####################### -NXapm_paraprobe application definitions are in fact pairs of application definitions. -One for the configuration (input) side and one for the results (output) side. For each -tool one such pair is proposed: +Application definitions for the input side (configuration) of each tool were defined. + + :ref:`NXapm_paraprobe_config_transcoder`: + Configuration of paraprobe-transcoder + Load POS, ePOS, APSuite APT, RRNG, RNG, and NXapm HDF5 files. + + :ref:`NXapm_paraprobe_config_ranger`: + Configuration of paraprobe-ranger + Apply ranging definitions and explore possible molecular ions. + + :ref:`NXapm_paraprobe_config_selector`: + Configuration of paraprobe-selector + Defining complex spatial regions-of-interest to filter reconstructed datasets. + :ref:`NXapm_paraprobe_config_surfacer`: + Configuration of paraprobe-surfacer + Create a model for the edge of a point cloud via convex hulls, alpha shapes. -.. _ApmGermanNfdi: + :ref:`NXapm_paraprobe_config_distancer`: + Configuration of paraprobe-distancer + Compute analytical distances between ions to a set of triangles. -Joint work German NFDI consortia NFDI-MatWerk and FAIRmat -####################################################################### + :ref:`NXapm_paraprobe_config_tessellator`: + Configuration of paraprobe-tessellator + Compute Voronoi cells for if desired all ions in a dataset. -Members of the NFDI-MatWerk and the FAIRmat consortium of the German National Research Data Infrastructure -are working together within the Infrastructure Use Case IUC09 of the NFDI-MatWerk project to work on examples -how software tools in both consortia become better documented and interoperable to use. Within this project, -we have also added the `CompositionSpace tool that has been developed at the Max-Planck-Institut für Eisenforschung -GmbH in Düsseldorf `_ by A. Saxena et al. + :ref:`NXapm_paraprobe_config_nanochem`: + Configuration of paraprobe-nanochem + Compute delocalization, iso-surfaces, analyze 3D objects, and composition profiles. + + :ref:`NXapm_paraprobe_config_intersector`: + Configuration of paraprobe-intersector + Assess intersections and proximity of 3D triangulated surface meshes in + continuum space to study the effect the parameterization of surface + extraction algorithms on the resulting shape, spatial arrangement, + and colocation of 3D objects via graph-based techniques. + + :ref:`NXapm_paraprobe_config_spatstat`: + Configuration of paraprobe-spatstat + Spatial statistics on the entire or selected regions of the reconstructed dataset. + + :ref:`NXapm_paraprobe_config_clusterer`: + Configuration of paraprobe-clusterer + Import cluster analysis results of IVAS/APSuite and perform clustering + analyses in a Python ecosystem. + +Application definitions for the output side (results) of each tool were defined. + + :ref:`NXapm_paraprobe_results_transcoder`: + Results of paraprobe-transcoder + Store reconstructed positions, ions, and charge states. + + :ref:`NXapm_paraprobe_results_ranger`: + Results of paraprobe-ranger + Store applied ranging definitions and combinatorial analyses of all possible iontypes. + + :ref:`NXapm_paraprobe_results_selector`: + Results of paraprobe-selector + Store which points are inside or on the boundary of complex spatial regions-of-interest. + + :ref:`NXapm_paraprobe_results_surfacer`: + Results of paraprobe-surfacer + Store triangulated surface meshes of models for the edge of a dataset. + + :ref:`NXapm_paraprobe_results_distancer`: + Results of paraprobe-distancer + Store analytical distances between ions to a set of triangles. + + :ref:`NXapm_paraprobe_results_tessellator`: + Results of paraprobe-tessellator + Store volume of all Voronoi cells about each ion in the dataset. + + :ref:`NXapm_paraprobe_results_nanochem`: + Results of paraprobe-nanochem + Store all results of delocalization, isosurface, and interface detection algorithms, + store all extracted triangulated surface meshes of found microstructural features, + store composition profiles and corresponding geometric primitives (ROIs). + + :ref:`NXapm_paraprobe_results_intersector`: + Results of paraprobe-intersector + Store graph of microstructural features and relations/link identified between them. + + :ref:`NXapm_paraprobe_results_spatstat`: + Results of paraprobe-spatstat + Store spatial correlation functions. + + :ref:`NXapm_paraprobe_results_clusterer`: + Results of paraprobe-clusterer + Store results of cluster analyses. + +.. _ApmParaprobeNewBC: + +Base Classes +############ -Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: - +We envision that the above-mentioned definitions can be useful not only to take +inspiration for other software tools in the field of atom probe but also to support +a discussion towards a stronger standardization of the vocabulary used. +Therefore, we are happy for comments and suggestions. + +The majority of data analyses in atom probe use a common set of operations and +conditions on the input data even though this might not be immediately evident +or might not have been so explicitly communicated in the literature. +Some tools have a specific scope because of which algorithms are hardcoded +to work for specific material systems. A typical example is a ranging tool +which exploits that all the examples it is used for apply to a specific material +and thus specific iontypes can be hardcoded. + +Instead, we are convinced it is better to follow a more generalized approach. +The following base classes and the above application definitions present examples +how one can use NeXus for this. + + :ref:`NXapm_input_reconstruction`: + A description from which file the reconstructed ion positions are imported. + + :ref:`NXapm_input_ranging`: + A description from which file the ranging definitions are imported. + The design of the ranging definitions is, thanks to :ref:`NXion`, so + general that all possible nuclids can be considered, be they observationally + stable, be they radioactive or transuranium nuclids. + +A detailed inspection of spatial and other type of filters frequently used in +analysis of atom probe data revealed that it is better to define atom-probe-agnostic, +i.e. more general filters: + + :ref:`NXspatial_filter`: + A proposal how a point cloud can be spatially filtered in a specific yet general manner. + This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, + and :ref:`NXcg_hexahedron_set` to cater for all of the most commonly used + geometric primitives in atom probe. + + :ref:`NXsubsampling_filter`: + A proposal for a filter that can also be used for specifying how entries + like ions can be filtered via sub-sampling. + + :ref:`NXmatch_filter`: + A proposal for a filter that can also be used for specifying how entries + like ions can be filtered based on their type (ion species) + or hit multiplicity. diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst deleted file mode 100644 index 87c2d5766..000000000 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. _Icme-Structure: - -============================================== -Integrated Computational Materials Engineering -============================================== - -.. index:: - IcmeMsModels - -.. _IcmeMsModels: - -Application definitions for ICME models -####################################### - -It is important to embrace the large research community of materials engineers -as they are frequent users of electron microscopy and atom probe microscopy. -ICME is an abbreviation for Integrated Computational Materials Engineering, which is -a design strategy and workflow whereby physics-based modelling of microstructure -evolution is used to understand the relations between the microstructure and -its technologically relevant descriptors to understand and tailor properties of materials. - -The following application definitions are proposed to support the discussion on how -materials-engineering-specific data schemas can connect to or be mapped on -concepts which are equally modellable with NeXus: - diff --git a/manual/source/classes/contributed_definitions/mpes-structure.rst b/manual/source/classes/contributed_definitions/mpes-structure.rst index 1d37fdba6..df89809bf 100644 --- a/manual/source/classes/contributed_definitions/mpes-structure.rst +++ b/manual/source/classes/contributed_definitions/mpes-structure.rst @@ -1,8 +1,8 @@ .. _Mpes-Structure: -============================================== +======================================= Photoemission & core-level spectroscopy -============================================== +======================================= .. index:: IntroductionMpes diff --git a/manual/source/classes/contributed_definitions/sample-prep-structure.rst b/manual/source/classes/contributed_definitions/sample-prep-structure.rst deleted file mode 100644 index 5a2820f22..000000000 --- a/manual/source/classes/contributed_definitions/sample-prep-structure.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _Synthesis-Structure: - -================== -Sample preparation -================== - -.. index:: - SamplePreparation - -.. _SamplePreparation: - -Document steps of wet-lab sample preparation -############################################ - -Virtually all experiments require a preparation of the sample. As most techniques are surface-sensitive or probe exclusively the surface, the use of careful preparation -techniques is the key to successful experiments. Unfortunately, the quality of such processes is often difficult to reproduce. Nevertheless, documenting how samples -are prepared is relevant. This part of the proposal provides prototypes how descriptions of steps performed by human or robots in a lab could be described using NeXus. - diff --git a/manual/source/icme-structure.rst b/manual/source/icme-structure.rst new file mode 100644 index 000000000..8ff31eaf7 --- /dev/null +++ b/manual/source/icme-structure.rst @@ -0,0 +1,9 @@ +.. _Icme-Structure-Fairmat: + +============================================== +Integrated Computational Materials Engineering +============================================== + +With a large set of data schemas for computational geometry, and methods from condensed-matter physics as well as materials engineering we are convinced that the NeXus standardization framework can be one component of efforts to harmonize and consolidate the zoo of descriptions and data schemas used within the field of Integrated Computational Materials Engineering (ICME). + +A status report along these lines of thoughts and ongoing efforts is available here: :ref:`Icme-Structure`. diff --git a/manual/source/img/FAIRmat_new.png b/manual/source/img/FAIRmat_new.png new file mode 100644 index 0000000000000000000000000000000000000000..eeddabe3400c469ed1619f50d834533d2afc0303 GIT binary patch literal 24990 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 literal 0 HcmV?d00001 From 52c7ded60267fa75772ebd8a3d79e444e1c52bc6 Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Wed, 26 Jul 2023 11:18:26 +0200 Subject: [PATCH 075/136] Added mvp doc for sts # Conflicts: # manual/source/classes/contributed_definitions/sts-structure.rst # manual/source/index.rst # manual/source/sts-structure.rst --- dev_tools/docs/nxdl_index.py | 1 + .../contributed_definitions/sts-structure.rst | 22 ------------------- 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 manual/source/classes/contributed_definitions/sts-structure.rst diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index 259464c6b..e5840aaeb 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -72,6 +72,7 @@ def nxdl_indices() -> Dict[str, dict]: rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") + rst_lines.append(f"{indentation}sts-structure\n") rst_lines.append(f"{indentation}cgms-structure\n") rst_lines.append(f"{indentation}icme-structure\n") rst_lines.append(f"{indentation}sample-prep-structure\n") diff --git a/manual/source/classes/contributed_definitions/sts-structure.rst b/manual/source/classes/contributed_definitions/sts-structure.rst deleted file mode 100644 index 5c3b18708..000000000 --- a/manual/source/classes/contributed_definitions/sts-structure.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. _Stm-Structure: - -=============================== -Scanning Tunneling Spectroscopy -=============================== - -.. index:: - StsAppDef - StsBC - -.. _StsAppDef: - -Application Definition -###################### - - -.. _StsNewBC: - -Base Classes -############ - - From 70e89d67cff5cf3ce382fc10a1e6151a3cabe7d8 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Fri, 3 Nov 2023 11:38:02 +0100 Subject: [PATCH 076/136] Add nyaml2nxdl updates from NIAC PR1303 (#102) * fixing imports * Modification for changes request from 1303 PR. * changes from Peter and Pete. * Change request in nyaml2nxdl_backward_tools.py * nyaml2nxdl backward tools: fixing requested changes in that file. * Updating nyaml2nxdl.py with '--do-not-store-nxdl' * Removed unused and not functioned functions ('append_yaml', 'compaire_niac_and_my'), and CLI options. * Updating nyaml_forward_tools.py. * Improved Makefile from fairmat branch * Removes unused code * Addresses some review comments in nxdl_utils * Addresses comments in nxdl_utils * Fixes typo in readme * Updating nyam2nxdl converter files. * Fix typo in setuptools_scm * Resolving requested changes. * Fixing attributes for nxdl and yaml separately. * REsolving PR comments * Fixes Makefile pickung up nxdl rules for `make nyaml` * Updating PR comments. * updating PR comments. * updating PR comments. * updating PR comments. * Replacing os, and xml from dependencies and add lxml and pathlib as dependencies. * updating PR comments. * Implementing black on nyal2nxdl converter files. * Fixing test. * Fixing build errors. * Remove pyproject.toml and adapt makefile * Remove $(DIRS) from nyaml command * Updates a warning for using make nxdl * Fix codestyle * Build nxdl names from existing variables * Fixing indentation miss alignment in comments commeing from nxdl to nyaml. * Remove multiple build targets in Makefile * Remove duplicate --do-not-store-nxdl * Adjust variable names in generate_nxdl_or_retrieve_nxdl * Update long_doc * Align with nyaml2nxdl-migration branch * Rename parameters to generate_nxdl_or_retrieve * Align docstring * Adds python setup step for ci/cd * Fix test * Skip package install in ci/cd * Adds setup of python to build pages ci/cd * Fix dimensions notation in NXcalibration.yaml * Adapt NXidentifer and NXserialized to new nyaml2nxdl --------- Co-authored-by: Sandor Brockhauser Co-authored-by: Rubel # Conflicts: # .github/workflows/fairmat-build-pages.yaml # .github/workflows/fairmat-nxdl-yaml-consistency.yaml # Makefile # README.md # contributed_definitions/NXcalibration.nxdl.xml # contributed_definitions/NXidentifier.nxdl.xml # contributed_definitions/NXserialized.nxdl.xml # contributed_definitions/nyaml/NXcalibration.yaml # dev_tools/nyaml2nxdl/README.md # dev_tools/nyaml2nxdl/__init__.py # dev_tools/nyaml2nxdl/comment_collector.py # dev_tools/nyaml2nxdl/nyaml2nxdl.py # dev_tools/nyaml2nxdl/nyaml2nxdl_backward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_forward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_helper.py # dev_tools/tests/test_nyaml2nxdl.py # dev_tools/utils/nxdl_utils.py # pyproject.toml --- dev_tools/docs/nxdl.py | 28 ++++++++------------------- pyproject.toml | 44 ------------------------------------------ 2 files changed, 8 insertions(+), 64 deletions(-) delete mode 100644 pyproject.toml diff --git a/dev_tools/docs/nxdl.py b/dev_tools/docs/nxdl.py index 8c9d548be..b95d2eb1d 100644 --- a/dev_tools/docs/nxdl.py +++ b/dev_tools/docs/nxdl.py @@ -17,10 +17,6 @@ from ..utils.types import PathLike from .anchor_list import AnchorRegistry -# controlling the length of progressively more indented sub-node -MIN_COLLAPSE_HINT_LINE_LENGTH = 20 -MAX_COLLAPSE_HINT_LINE_LENGTH = 80 - class NXClassDocGenerator: """Generate documentation in reStructuredText markup @@ -530,30 +526,24 @@ def _print_doc(self, indent, ns, node, required=False): self._print(f"{indent}{line}") self._print() - def long_doc(self, ns, node, left_margin): + def long_doc(self, ns, node): length = 0 line = "documentation" fnd = False blocks = self._get_doc_blocks(ns, node) - max_characters = max( - MIN_COLLAPSE_HINT_LINE_LENGTH, (MAX_COLLAPSE_HINT_LINE_LENGTH - left_margin) - ) for block in blocks: lines = block.splitlines() length += len(lines) for single_line in lines: if len(single_line) > 2 and single_line[0] != "." and not fnd: fnd = True - line = single_line[:max_characters] + line = single_line return (length, line, blocks) def _print_doc_enum(self, indent, ns, node, required=False): collapse_indent = indent node_list = node.xpath("nx:enumeration", namespaces=ns) - (doclen, line, blocks) = self.long_doc(ns, node, len(indent)) - if len(node_list) + doclen > 1: - collapse_indent = f"{indent} " - self._print(f"{indent}{self._INDENTATION_UNIT}.. collapse:: {line} ...\n") + (doclen, line, blocks) = self.long_doc(ns, node) self._print_doc( collapse_indent + self._INDENTATION_UNIT, ns, node, required=required ) @@ -678,8 +668,9 @@ def _print(self, *args, end="\n"): self._rst_lines.append(" ".join(args) + end) def get_first_parent_ref(self, path, tag): - nx_name = path[1 : path.find("/", 1)] - path = path[path.find("/", 1) :] + spliter = path.find("/", 1) + nx_name = path[1:spliter] + path = path[spliter:] try: parents = get_inherited_nodes(path, nx_name)[2] @@ -689,11 +680,8 @@ def get_first_parent_ref(self, path, tag): parent = parents[1] parent_path = parent_display_name = parent.attrib["nxdlpath"] parent_path_segments = parent_path[1:].split("/") - parent_def_name = parent.attrib["nxdlbase"][ - parent.attrib["nxdlbase"] - .rfind("/") : parent.attrib["nxdlbase"] - .rfind(".nxdl") - ] + nxdl_attr = parent.attrib["nxdlbase"] + parent_def_name = nxdl_attr[nxdl_attr.rfind("/") : nxdl_attr.rfind(".nxdl")] # Case where the first parent is a base_class if parent_path_segments[0] == "": diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index e691189b9..000000000 --- a/pyproject.toml +++ /dev/null @@ -1,44 +0,0 @@ -[build-system] -requires = ["setuptools>=64.0.1", "setuptools-scm[toml]>=6.2"] -build-backend = "setuptools.build_meta" - -[project] -name = "nexusdefinitions" -dynamic = ["version"] -authors = [ - { name = "NIAC" } -] -description = "Nexus definitions" -readme = "README.md" -license = { file = "LGPL.txt" } -requires-python = "" -classifiers = [ - "Operating System :: OS Independent" -] -dependencies = [ - "lxml", - "pyyaml", - "click>=7.1.2", - "h5py>=3.6.0", - "sphinx>=5", - "sphinx-tabs", - "sphinx-toolbox", - "pytest", - "black>=22.3", - "flake8>=4", - "isort>=5.10", - "click>=7.1.2", -] - -[project.urls] -"Homepage" = "https://nexusformat.org" - -[project.scripts] -read_nexus = "dev_tools.utils.nexus:main" - -[tools.setuptools_scm] -version_scheme = "guess-next-dev" -local_scheme = "node-and-date" - -[tool.setuptools] -packages = ["dev_tools"] From 9764a561fc1b6a94e6b1aa8181492c20e843be8e Mon Sep 17 00:00:00 2001 From: Rubel Date: Mon, 6 Nov 2023 11:57:35 +0100 Subject: [PATCH 077/136] Fix rebase conflict. # Conflicts: # dev_tools/nyaml2nxdl/nyaml2nxdl.py # dev_tools/nyaml2nxdl/nyaml2nxdl_backward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_forward_tools.py --- dev_tools/utils/nxdl_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index ebb7ce62a..afb3c54ee 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -78,7 +78,7 @@ def get_hdf_parent(hdf_info): if "hdf_root" not in hdf_info else hdf_info["hdf_root"] ) - for child_name in hdf_info["hdf_path"].split("/"): + for child_name in hdf_info["hdf_path"].rsplit("/"): node = node[child_name] return node From 174be362881186f42dd53730514f7b8b8b842fcc Mon Sep 17 00:00:00 2001 From: Rubel Date: Mon, 6 Nov 2023 11:58:41 +0100 Subject: [PATCH 078/136] Fix rebase conflict. # Conflicts: # dev_tools/utils/nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index afb3c54ee..ebb7ce62a 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -78,7 +78,7 @@ def get_hdf_parent(hdf_info): if "hdf_root" not in hdf_info else hdf_info["hdf_root"] ) - for child_name in hdf_info["hdf_path"].rsplit("/"): + for child_name in hdf_info["hdf_path"].split("/"): node = node[child_name] return node From 8b23ccb08aeb43f430d688e9a8238231dce42132 Mon Sep 17 00:00:00 2001 From: Rubel Date: Mon, 6 Nov 2023 12:08:53 +0100 Subject: [PATCH 079/136] Fix rebase conflict and PR change request. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix rebase conflict. Fix rebase conflict. Disable fail-fast to check which versions work Actually *disable* fail-fast 🙈 Fix rebase conflict. Fix rebase conflict. Fix rebase conflict. Fix rebase conflict. Fix rebase conflict. Fix rebase conflict. Responding on PR review comments. Changes for PR review. Changes for PR review. Changes for PR review. Changes for PR review. Changes for PR review. Changes for PR review. Changes for PR revie. # Conflicts: # Makefile # dev_tools/nyaml2nxdl/README.md # dev_tools/nyaml2nxdl/comment_collector.py # dev_tools/nyaml2nxdl/nyaml2nxdl.py # dev_tools/nyaml2nxdl/nyaml2nxdl_backward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_forward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_helper.py # dev_tools/tests/test_nyaml2nxdl.py # dev_tools/utils/nxdl_utils.py --- dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml | 72 +++++++++++++++++++ dev_tools/tests/data/doc_yaml2nxdl.yaml | 48 +++++++++++++ dev_tools/tests/data/ref_doc_nxdl2yaml.yaml | 47 ++++++++++++ .../tests/data/ref_doc_yaml2nxdl.nxdl.xml | 72 +++++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml create mode 100644 dev_tools/tests/data/doc_yaml2nxdl.yaml create mode 100644 dev_tools/tests/data/ref_doc_nxdl2yaml.yaml create mode 100644 dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml diff --git a/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml b/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml new file mode 100644 index 000000000..ad75b96ea --- /dev/null +++ b/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml @@ -0,0 +1,72 @@ + + + + + + This is a definition for data to be archived by ICAT (http://www.icatproject.org/). + + .. text from the icatproject.org site + + the database (with supporting software) that provides an + interface to all ISIS experimental data and will provide + a mechanism to link all aspects of ISIS research from + proposal through to publication. + + + + + + + unique identifier for the experimenta + lkokö + sddfdfd + + This concept is related to term `term`_ of the spec standard. + .. _term: url + + This is test doc. + + + + + Part1: Text line 1. + part1: Text line 2 + + This concept is related to term `term`_ of the spec standard. + .. _term: url + + + + + ID of user or DAQ define group of data files + Brief summary of the collection, including grouping criteria + + + + + unique identifier for this measurement as provided by the facility + + + + + diff --git a/dev_tools/tests/data/doc_yaml2nxdl.yaml b/dev_tools/tests/data/doc_yaml2nxdl.yaml new file mode 100644 index 000000000..df25dbb91 --- /dev/null +++ b/dev_tools/tests/data/doc_yaml2nxdl.yaml @@ -0,0 +1,48 @@ +category: application +doc: | + This is a definition for data to be archived by ICAT (http://www.icatproject.org/). + + .. text from the icatproject.org site + + the database (with supporting software) that provides an + interface to all ISIS experimental data and will provide + a mechanism to link all aspects of ISIS research from + proposal through to publication. +type: group +NXarchive(NXobject): + (NXentry)entry: + \@index: + title: + experiment_identifier(NX_CHAR): + doc: + - | + "unique identifier for the experimenta + lkokö + sddfdfd" + - | + "xref: + spec: spec + term: term + url: url" + - | + "This is test doc." + experiment_description(NX_CHAR): + doc: + - | + Part1: Text line 1. + part1: Text line 2 + + - | + xref: + spec: spec + term: term + url: url" + + collection_identifier(NX_CHAR): + doc: | + ID of user or DAQ define group of data files + Brief summary of the collection, including grouping criteria + entry_identifier(NX_CHAR): + doc: | + unique identifier for this measurement as provided by the facility + start_time(NX_DATE_TIME): diff --git a/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml b/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml new file mode 100644 index 000000000..75e867198 --- /dev/null +++ b/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml @@ -0,0 +1,47 @@ +category: application +doc: + - | + This is a definition for data to be archived by ICAT (http://www.icatproject.org/). + - | + .. text from the icatproject.org site + - | + the database (with supporting software) that provides an + interface to all ISIS experimental data and will provide + a mechanism to link all aspects of ISIS research from + proposal through to publication. +type: group +NXarchive(NXobject): + (NXentry)entry: + \@index: + title: + experiment_identifier(NX_CHAR): + doc: + - | + unique identifier for the experimenta + lkokö + sddfdfd + - | + "xref: + spec: spec + term: term + url: url" + - | + This is test doc. + experiment_description(NX_CHAR): + doc: + - | + Part1: Text line 1. + part1: Text line 2 + - | + "xref: + spec: spec + term: term + url: url" + collection_identifier(NX_CHAR): + doc: | + ID of user or DAQ define group of data files + Brief summary of the collection, including grouping criteria + entry_identifier(NX_CHAR): + doc: | + unique identifier for this measurement as provided by the facility + start_time(NX_DATE_TIME): diff --git a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml new file mode 100644 index 000000000..ad75b96ea --- /dev/null +++ b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml @@ -0,0 +1,72 @@ + + + + + + This is a definition for data to be archived by ICAT (http://www.icatproject.org/). + + .. text from the icatproject.org site + + the database (with supporting software) that provides an + interface to all ISIS experimental data and will provide + a mechanism to link all aspects of ISIS research from + proposal through to publication. + + + + + + + unique identifier for the experimenta + lkokö + sddfdfd + + This concept is related to term `term`_ of the spec standard. + .. _term: url + + This is test doc. + + + + + Part1: Text line 1. + part1: Text line 2 + + This concept is related to term `term`_ of the spec standard. + .. _term: url + + + + + ID of user or DAQ define group of data files + Brief summary of the collection, including grouping criteria + + + + + unique identifier for this measurement as provided by the facility + + + + + From ef2bb2b8f330e73617f5c19c7989f79d0010ec48 Mon Sep 17 00:00:00 2001 From: RubelMozumder <32923026+RubelMozumder@users.noreply.github.com> Date: Fri, 10 Nov 2023 17:28:56 +0100 Subject: [PATCH 080/136] Resolving xref issue 115-nyaml2nxdl-xref-edge-cases (#116) * Resolving xref issue 115-nyaml2nxdl-xref-edge-cases * Suggestion for new xref function * Remove unused re * Adds test for xref handling * Use strip short notation * Adds tests for invalid xref * update nyaml2nxdl readme * Add edge cases for xref * Re-introduce removal of starting " * Remove unused import * Remove support for " in xref docstring --------- Co-authored-by: domna Co-authored-by: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> # Conflicts: # dev_tools/nyaml2nxdl/README.md # dev_tools/nyaml2nxdl/nyaml2nxdl_backward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_forward_tools.py # dev_tools/tests/test_nyaml2nxdl.py --- dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml | 4 ++-- dev_tools/tests/data/doc_yaml2nxdl.yaml | 16 ++++++++-------- dev_tools/tests/data/ref_doc_nxdl2yaml.yaml | 6 +++--- dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml | 10 +++++----- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml b/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml index ad75b96ea..54e539153 100644 --- a/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml +++ b/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml @@ -41,8 +41,8 @@ lkokö sddfdfd - This concept is related to term `term`_ of the spec standard. - .. _term: url + This concept is related to term `12.58`_ of the ISO 18115-1:2023 standard. + .. _12.58: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 This is test doc. diff --git a/dev_tools/tests/data/doc_yaml2nxdl.yaml b/dev_tools/tests/data/doc_yaml2nxdl.yaml index df25dbb91..5129c3a9d 100644 --- a/dev_tools/tests/data/doc_yaml2nxdl.yaml +++ b/dev_tools/tests/data/doc_yaml2nxdl.yaml @@ -19,16 +19,16 @@ NXarchive(NXobject): "unique identifier for the experimenta lkokö sddfdfd" - - | - "xref: - spec: spec - term: term - url: url" - - | + - | + xref: + spec: ISO 18115-1:2023 + term: 12.58 + url: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 + - | "This is test doc." experiment_description(NX_CHAR): doc: - - | + - | Part1: Text line 1. part1: Text line 2 @@ -36,7 +36,7 @@ NXarchive(NXobject): xref: spec: spec term: term - url: url" + url: url collection_identifier(NX_CHAR): doc: | diff --git a/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml b/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml index 75e867198..8ad3bb82b 100644 --- a/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml +++ b/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml @@ -22,9 +22,9 @@ NXarchive(NXobject): sddfdfd - | "xref: - spec: spec - term: term - url: url" + spec: ISO 18115-1:2023 + term: 12.58 + url: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58" - | This is test doc. experiment_description(NX_CHAR): diff --git a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml index ad75b96ea..983cd8a84 100644 --- a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml +++ b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml @@ -37,14 +37,14 @@ - unique identifier for the experimenta + "unique identifier for the experimenta lkokö - sddfdfd + sddfdfd" - This concept is related to term `term`_ of the spec standard. - .. _term: url + This concept is related to term `12.58`_ of the ISO 18115-1:2023 standard. + .. _12.58: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 - This is test doc. + "This is test doc." From ec78763e0153f4cd4979fd143bd684cdbc458666 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 15 Nov 2023 18:39:57 +0100 Subject: [PATCH 081/136] Allow xref in root-level docstring # Conflicts: # dev_tools/nyaml2nxdl/nyaml2nxdl_backward_tools.py # dev_tools/nyaml2nxdl/nyaml2nxdl_forward_tools.py --- dev_tools/tests/data/doc_yaml2nxdl.yaml | 24 ++++++++++++------- .../tests/data/ref_doc_yaml2nxdl.nxdl.xml | 3 +++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/dev_tools/tests/data/doc_yaml2nxdl.yaml b/dev_tools/tests/data/doc_yaml2nxdl.yaml index 5129c3a9d..94b376325 100644 --- a/dev_tools/tests/data/doc_yaml2nxdl.yaml +++ b/dev_tools/tests/data/doc_yaml2nxdl.yaml @@ -1,13 +1,19 @@ category: application -doc: | - This is a definition for data to be archived by ICAT (http://www.icatproject.org/). - - .. text from the icatproject.org site - - the database (with supporting software) that provides an - interface to all ISIS experimental data and will provide - a mechanism to link all aspects of ISIS research from - proposal through to publication. +doc: + - | + This is a definition for data to be archived by ICAT (http://www.icatproject.org/). + + .. text from the icatproject.org site + + the database (with supporting software) that provides an + interface to all ISIS experimental data and will provide + a mechanism to link all aspects of ISIS research from + proposal through to publication. + - | + xref: + spec: ISO 18115-1:2023 + term: 1.1 + url: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:1.1 type: group NXarchive(NXobject): (NXentry)entry: diff --git a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml index 983cd8a84..854447e26 100644 --- a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml +++ b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml @@ -31,6 +31,9 @@ interface to all ISIS experimental data and will provide a mechanism to link all aspects of ISIS research from proposal through to publication. + + This concept is related to term `1.1`_ of the ISO 18115-1:2023 standard. + .. _1.1: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:1.1 From f2bc5af3d267fbfb1a55f568a77deeda4ac42c1e Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Wed, 29 Nov 2023 09:58:16 +0100 Subject: [PATCH 082/136] Readd collapsible feature and super-concept links for documentation + removes nyaml2nxdl (#117) * Readd collapsible features * Restore super-concept links * Remove nyaml2nxdl * Use nyaml package * Readd pyyaml # Conflicts: # Makefile # base_classes/NXroot.nxdl.xml # contributed_definitions/NXcalibration.nxdl.xml # contributed_definitions/NXidentifier.nxdl.xml # contributed_definitions/NXserialized.nxdl.xml # dev_tools/utils/nxdl_utils.py # requirements.txt --- dev_tools/docs/nxdl.py | 28 +++++-- dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml | 72 ------------------ dev_tools/tests/data/doc_yaml2nxdl.yaml | 54 ------------- dev_tools/tests/data/ref_doc_nxdl2yaml.yaml | 47 ------------ .../tests/data/ref_doc_yaml2nxdl.nxdl.xml | 75 ------------------- 5 files changed, 20 insertions(+), 256 deletions(-) delete mode 100644 dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml delete mode 100644 dev_tools/tests/data/doc_yaml2nxdl.yaml delete mode 100644 dev_tools/tests/data/ref_doc_nxdl2yaml.yaml delete mode 100644 dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml diff --git a/dev_tools/docs/nxdl.py b/dev_tools/docs/nxdl.py index b95d2eb1d..8c9d548be 100644 --- a/dev_tools/docs/nxdl.py +++ b/dev_tools/docs/nxdl.py @@ -17,6 +17,10 @@ from ..utils.types import PathLike from .anchor_list import AnchorRegistry +# controlling the length of progressively more indented sub-node +MIN_COLLAPSE_HINT_LINE_LENGTH = 20 +MAX_COLLAPSE_HINT_LINE_LENGTH = 80 + class NXClassDocGenerator: """Generate documentation in reStructuredText markup @@ -526,24 +530,30 @@ def _print_doc(self, indent, ns, node, required=False): self._print(f"{indent}{line}") self._print() - def long_doc(self, ns, node): + def long_doc(self, ns, node, left_margin): length = 0 line = "documentation" fnd = False blocks = self._get_doc_blocks(ns, node) + max_characters = max( + MIN_COLLAPSE_HINT_LINE_LENGTH, (MAX_COLLAPSE_HINT_LINE_LENGTH - left_margin) + ) for block in blocks: lines = block.splitlines() length += len(lines) for single_line in lines: if len(single_line) > 2 and single_line[0] != "." and not fnd: fnd = True - line = single_line + line = single_line[:max_characters] return (length, line, blocks) def _print_doc_enum(self, indent, ns, node, required=False): collapse_indent = indent node_list = node.xpath("nx:enumeration", namespaces=ns) - (doclen, line, blocks) = self.long_doc(ns, node) + (doclen, line, blocks) = self.long_doc(ns, node, len(indent)) + if len(node_list) + doclen > 1: + collapse_indent = f"{indent} " + self._print(f"{indent}{self._INDENTATION_UNIT}.. collapse:: {line} ...\n") self._print_doc( collapse_indent + self._INDENTATION_UNIT, ns, node, required=required ) @@ -668,9 +678,8 @@ def _print(self, *args, end="\n"): self._rst_lines.append(" ".join(args) + end) def get_first_parent_ref(self, path, tag): - spliter = path.find("/", 1) - nx_name = path[1:spliter] - path = path[spliter:] + nx_name = path[1 : path.find("/", 1)] + path = path[path.find("/", 1) :] try: parents = get_inherited_nodes(path, nx_name)[2] @@ -680,8 +689,11 @@ def get_first_parent_ref(self, path, tag): parent = parents[1] parent_path = parent_display_name = parent.attrib["nxdlpath"] parent_path_segments = parent_path[1:].split("/") - nxdl_attr = parent.attrib["nxdlbase"] - parent_def_name = nxdl_attr[nxdl_attr.rfind("/") : nxdl_attr.rfind(".nxdl")] + parent_def_name = parent.attrib["nxdlbase"][ + parent.attrib["nxdlbase"] + .rfind("/") : parent.attrib["nxdlbase"] + .rfind(".nxdl") + ] # Case where the first parent is a base_class if parent_path_segments[0] == "": diff --git a/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml b/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml deleted file mode 100644 index 54e539153..000000000 --- a/dev_tools/tests/data/doc_nxdl2yaml.nxdl.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - This is a definition for data to be archived by ICAT (http://www.icatproject.org/). - - .. text from the icatproject.org site - - the database (with supporting software) that provides an - interface to all ISIS experimental data and will provide - a mechanism to link all aspects of ISIS research from - proposal through to publication. - - - - - - - unique identifier for the experimenta - lkokö - sddfdfd - - This concept is related to term `12.58`_ of the ISO 18115-1:2023 standard. - .. _12.58: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 - - This is test doc. - - - - - Part1: Text line 1. - part1: Text line 2 - - This concept is related to term `term`_ of the spec standard. - .. _term: url - - - - - ID of user or DAQ define group of data files - Brief summary of the collection, including grouping criteria - - - - - unique identifier for this measurement as provided by the facility - - - - - diff --git a/dev_tools/tests/data/doc_yaml2nxdl.yaml b/dev_tools/tests/data/doc_yaml2nxdl.yaml deleted file mode 100644 index 94b376325..000000000 --- a/dev_tools/tests/data/doc_yaml2nxdl.yaml +++ /dev/null @@ -1,54 +0,0 @@ -category: application -doc: - - | - This is a definition for data to be archived by ICAT (http://www.icatproject.org/). - - .. text from the icatproject.org site - - the database (with supporting software) that provides an - interface to all ISIS experimental data and will provide - a mechanism to link all aspects of ISIS research from - proposal through to publication. - - | - xref: - spec: ISO 18115-1:2023 - term: 1.1 - url: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:1.1 -type: group -NXarchive(NXobject): - (NXentry)entry: - \@index: - title: - experiment_identifier(NX_CHAR): - doc: - - | - "unique identifier for the experimenta - lkokö - sddfdfd" - - | - xref: - spec: ISO 18115-1:2023 - term: 12.58 - url: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 - - | - "This is test doc." - experiment_description(NX_CHAR): - doc: - - | - Part1: Text line 1. - part1: Text line 2 - - - | - xref: - spec: spec - term: term - url: url - - collection_identifier(NX_CHAR): - doc: | - ID of user or DAQ define group of data files - Brief summary of the collection, including grouping criteria - entry_identifier(NX_CHAR): - doc: | - unique identifier for this measurement as provided by the facility - start_time(NX_DATE_TIME): diff --git a/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml b/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml deleted file mode 100644 index 8ad3bb82b..000000000 --- a/dev_tools/tests/data/ref_doc_nxdl2yaml.yaml +++ /dev/null @@ -1,47 +0,0 @@ -category: application -doc: - - | - This is a definition for data to be archived by ICAT (http://www.icatproject.org/). - - | - .. text from the icatproject.org site - - | - the database (with supporting software) that provides an - interface to all ISIS experimental data and will provide - a mechanism to link all aspects of ISIS research from - proposal through to publication. -type: group -NXarchive(NXobject): - (NXentry)entry: - \@index: - title: - experiment_identifier(NX_CHAR): - doc: - - | - unique identifier for the experimenta - lkokö - sddfdfd - - | - "xref: - spec: ISO 18115-1:2023 - term: 12.58 - url: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58" - - | - This is test doc. - experiment_description(NX_CHAR): - doc: - - | - Part1: Text line 1. - part1: Text line 2 - - | - "xref: - spec: spec - term: term - url: url" - collection_identifier(NX_CHAR): - doc: | - ID of user or DAQ define group of data files - Brief summary of the collection, including grouping criteria - entry_identifier(NX_CHAR): - doc: | - unique identifier for this measurement as provided by the facility - start_time(NX_DATE_TIME): diff --git a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml b/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml deleted file mode 100644 index 854447e26..000000000 --- a/dev_tools/tests/data/ref_doc_yaml2nxdl.nxdl.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - This is a definition for data to be archived by ICAT (http://www.icatproject.org/). - - .. text from the icatproject.org site - - the database (with supporting software) that provides an - interface to all ISIS experimental data and will provide - a mechanism to link all aspects of ISIS research from - proposal through to publication. - - This concept is related to term `1.1`_ of the ISO 18115-1:2023 standard. - .. _1.1: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:1.1 - - - - - - - "unique identifier for the experimenta - lkokö - sddfdfd" - - This concept is related to term `12.58`_ of the ISO 18115-1:2023 standard. - .. _12.58: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 - - "This is test doc." - - - - - Part1: Text line 1. - part1: Text line 2 - - This concept is related to term `term`_ of the spec standard. - .. _term: url - - - - - ID of user or DAQ define group of data files - Brief summary of the collection, including grouping criteria - - - - - unique identifier for this measurement as provided by the facility - - - - - From d44886995b510db4e7adbb931ea49164ab649edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20K=C3=BChbach?= Date: Thu, 30 Nov 2023 20:19:51 +0100 Subject: [PATCH 083/136] Base class templates (#51) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactored cg_primitive base classes for two key aspects: i) make all primitives inherit from new base class NXcg_primitive_set which makes a substantial number of repeated properties of specialized primitive base classes unnecessary, ii) introducing a rigorous mathematical set theoretical approach to describe the number type N, N0, Z, R, R+, R, iii) introduce short hand notation to reduce writing costs for shape/dimensions of arrays: now numpy syntax is used, for scalars (), (1, can be omitted, experience in FAIRmat has shown that in almost all cases the optional doc string to a dimension was almost never used and thus yaml based descriptions can be written more succinct, iv) proof-read docstrings and shortened them, introduced the suggestion to use info: as a keyword which should for now be just appended to the docstring as usual but in the future should be treated as a comment, i.e. only meant for human contextualization but ignored for semantic interpretation of concepts, a key difference that I hope this will bring is to reduce also the length of base classes and appdef as they show up in html pages, specifically for appdefs like NXem many of the conceptual ideas which these docstrings currently contain would be much better placed in a proper documentation instead of the actual class definition in the hope that the overall appearance of classes becomes easier and faster for people to power read; maybe this also works against some criticism that NeXus is considered complex, I have to say with the outsourcing of NXcg_primitive_set I feel it is damn simple now * Refactoring of NXcs base classes * First lot of refactoring EM base classes, the rest tomorrow, NXapm will not be refactored before the APT&M2023 conference in Sept2023, also because feedback from Leoben was positive enough that no immediate changes wrt to appdefs and base classes were required * Summarize the current state of the discussion about coordinate systems with the proposed NXcoordinate_system and NXcoordinate_system_set base classes and best practice recommendations how they should be used including feedback from discussions with Florian Dobner and Tamás Haraszti * Summary of the discussion how to handle conventions and method-specific conventions for EM and methods used in EM * Base classes for implemented examples for pole figures, orientation distribution function, event_data, stage_lab, and ebsd_crystal_structure_model * NXms_ipf base class and dos2unix to correct newlines * Introducing NXem_method base class as a template how to write method-specific deep base classes to describe the terms and taxononmy of method-specific branches to be hooked into appdefs like NXem * Base class inheritance proposal for a now even stronger modularized schema set for electron microscopy research, two tasks remain: i) refactor what is now a method-specific instance rather than an appdef (NXem_ebsd) (mainly to be able to fuse all examples of em-specific data converters including new ebsd examples into one em parser for pynxtools), ii) refactor NXem which is now clearly a specific appdef specializing the NXem_base deep base class, specialization work needs to define which fields and groups from all the possible ones now composable via base classes (inheritance) are required in an appdef NXem for NOMAD OASIS * NXem_ebsd refactored into a base class to use it as a method-specific group inside the NXem application definition, next step: i) refactor NXem_sim, ii) finalize refactoring of NXem appdef (for Nomad oasis) * finished draft of NXem_ebsd, NXem_correlation, and NXem appdef, cleaning the branch * Add proposal for storing mtx cfg, fixed nxtime datatypes * 2d microstructure projection * Inspection how proposed, info, N0, N, R, Z value type abbreviations, and dimensions could be added to nyamlforward * A likely too simplistic but at least working nyaml2nxdl forward mapping to explore further usage of refactored EM base classes. Info keyword has to be a child of doc or the respective text be removed from the standard and put into proposal-specific documentation, how to store what and where so that the schema docstring remain succinct and slim but all these conceptual ideas get not forgotten, typically the would be part of a tech report, i.e. in my opinion all what is under info: sections of a docstring should move to some documentation to tell the story to humans, next test these NXDLs with the NeXus documentation system * Minor fix to handle info keyword spotted while compiling the documentation * Fixes to compile with NeXus documentation test suite and sphinx * Deactivated the annoying clean yaml via make clean for dev purposes * Minor fix in em_base, this completes the appdef/base class work for now on the refactored EM, there are still some spurious info fields now, which should be removed when a decision has been made wrt to how to deal with info: keyword fields in general, next steps: i) make decision on info, ii) test refactored EM proposal with pynxtools em-parser v2, iii) implement backwards * Styling via black * Added yaml2nxdl-forward-converted NXDL files to all refactored base classes and the refactored NXem * Added NXroot header for the em appdef and its base template appdef * Continuing the refactoring of EM and APM plus related base classes for CG and MS based on suggestions from user meetings, discussions with Sandor, represents work with the MPES sprint #83 * Continuing on #83 * Continuing #83, NXcs_* * Continuing #83, ipf, pf, odf * Continuing on #83, support classes for EM * Continued on #83, coordinate system, further base classes supporting EM * Continuing #83, event_data_set and event_data description substantially condensed amongst other points * Added cross-references to base classes for rst, continuing #83 * Aligned old NXem_ebsd_conventions with NXcoordinate_system for #83 * Reviewed method-specific base classes, ebsd, eds, eels, #83 * #83, NXms_recon * #83, composed constraints on the NXem appdef * Consolidated with changes that happened in between on the fairmat branch based on 1016aa0, NXms_recon has still an issue and is therefore deactivated currently, method-specific landing pages need to be updated * Consolidated further with fairmat 15624c0be77be13a * Fixing some missing references * Fixed syntax error to compile NXms_recon, docs building also now, reviewing intro pages remains * Consistencies of dimensionality to use NX_POSINT and an enumeration * Recompiled NXDL files using new nyaml module 3d500ced7e4ca57683957c1d61a8d0cb62eccf53, removed, modified by taking the one from fairmat, and synced all files which were binarily different between this feature branch and the fairmat branch specifically commit a15798bab795d92b587527f2cff0819e26f550ee of the fairmat branch * Deactivated em-based tests which because of a refactoring of em are not expected to work anymore * Fix improper Latex notation in math environment for polyline, face_list, nanochem * Added recompiled NXidentifier, NXserialized NXDLs which triggered pipeline errors in CatChen gh action * Some round of proof-reading * Fixed test_nxdl_utils to reflect and use refactored locations of refactored NXem * Added feedback from @phyy-nx, @PeterC-DLS, and @prjemian from discussed here https://github.com/nexusformat/definitions PR #1271 * Black formatting * Reactivated data type check for e.g. NXem NX_NUMBER * Implementing NX_DATE_TIME suggestion of @sanbrock --------- Co-authored-by: markus.kuehbach # Conflicts: # contributed_definitions/NXaberration.nxdl.xml # contributed_definitions/NXaberration_model.nxdl.xml # contributed_definitions/NXaberration_model_ceos.nxdl.xml # contributed_definitions/NXaberration_model_nion.nxdl.xml # contributed_definitions/NXaperture_em.nxdl.xml # contributed_definitions/NXapm.nxdl.xml # contributed_definitions/NXapm_paraprobe_results_nanochem.nxdl.xml # contributed_definitions/NXcg_alpha_complex.nxdl.xml # contributed_definitions/NXcg_cylinder_set.nxdl.xml # contributed_definitions/NXcg_ellipsoid_set.nxdl.xml # contributed_definitions/NXcg_face_list_data_structure.nxdl.xml # contributed_definitions/NXcg_geodesic_mesh.nxdl.xml # contributed_definitions/NXcg_grid.nxdl.xml # contributed_definitions/NXcg_half_edge_data_structure.nxdl.xml # contributed_definitions/NXcg_hexahedron_set.nxdl.xml # contributed_definitions/NXcg_marching_cubes.nxdl.xml # contributed_definitions/NXcg_parallelogram_set.nxdl.xml # contributed_definitions/NXcg_point_set.nxdl.xml # contributed_definitions/NXcg_polygon_set.nxdl.xml # contributed_definitions/NXcg_polyhedron_set.nxdl.xml # contributed_definitions/NXcg_polyline_set.nxdl.xml # contributed_definitions/NXcg_roi_set.nxdl.xml # contributed_definitions/NXcg_sphere_set.nxdl.xml # contributed_definitions/NXcg_tetrahedron_set.nxdl.xml # contributed_definitions/NXcg_triangle_set.nxdl.xml # contributed_definitions/NXcg_triangulated_surface_mesh.nxdl.xml # contributed_definitions/NXcg_unit_normal_set.nxdl.xml # contributed_definitions/NXchamber.nxdl.xml # contributed_definitions/NXcoordinate_system_set.nxdl.xml # contributed_definitions/NXcorrector_cs.nxdl.xml # contributed_definitions/NXcs_computer.nxdl.xml # contributed_definitions/NXcs_filter_boolean_mask.nxdl.xml # contributed_definitions/NXcs_io_obj.nxdl.xml # contributed_definitions/NXcs_io_sys.nxdl.xml # contributed_definitions/NXcs_mm_sys.nxdl.xml # contributed_definitions/NXcs_prng.nxdl.xml # contributed_definitions/NXcs_profiling.nxdl.xml # contributed_definitions/NXcs_profiling_event.nxdl.xml # contributed_definitions/NXdeflector.nxdl.xml # contributed_definitions/NXebeam_column.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_conventions.nxdl.xml # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXem_ebsd_crystal_structure_model.nxdl.xml # contributed_definitions/NXem_img.nxdl.xml # contributed_definitions/NXem_sim.nxdl.xml # contributed_definitions/NXevent_data_em.nxdl.xml # contributed_definitions/NXevent_data_em_set.nxdl.xml # contributed_definitions/NXfabrication.nxdl.xml # contributed_definitions/NXgraph_edge_set.nxdl.xml # contributed_definitions/NXgraph_node_set.nxdl.xml # contributed_definitions/NXgraph_root.nxdl.xml # contributed_definitions/NXibeam_column.nxdl.xml # contributed_definitions/NXimage_set.nxdl.xml # contributed_definitions/NXimage_set_em_adf.nxdl.xml # contributed_definitions/NXimage_set_em_kikuchi.nxdl.xml # contributed_definitions/NXion.nxdl.xml # contributed_definitions/NXisocontour.nxdl.xml # contributed_definitions/NXlens_em.nxdl.xml # contributed_definitions/NXms.nxdl.xml # contributed_definitions/NXms_feature_set.nxdl.xml # contributed_definitions/NXms_score_results.nxdl.xml # contributed_definitions/NXoptical_system_em.nxdl.xml # contributed_definitions/NXorientation_set.nxdl.xml # contributed_definitions/NXpump.nxdl.xml # contributed_definitions/NXrotation_set.nxdl.xml # contributed_definitions/NXscanbox_em.nxdl.xml # contributed_definitions/NXspectrum_set.nxdl.xml # contributed_definitions/NXspectrum_set_em_eels.nxdl.xml # contributed_definitions/NXspectrum_set_em_xray.nxdl.xml # contributed_definitions/NXstage_lab.nxdl.xml # contributed_definitions/nyaml/NXaberration.yaml # contributed_definitions/nyaml/NXaberration_model.yaml # contributed_definitions/nyaml/NXaberration_model_ceos.yaml # contributed_definitions/nyaml/NXaberration_model_nion.yaml # contributed_definitions/nyaml/NXaperture_em.yaml # contributed_definitions/nyaml/NXapm.yaml # contributed_definitions/nyaml/NXapm_paraprobe_results_nanochem.yaml # contributed_definitions/nyaml/NXcg_alpha_complex.yaml # contributed_definitions/nyaml/NXcg_cylinder_set.yaml # contributed_definitions/nyaml/NXcg_ellipsoid_set.yaml # contributed_definitions/nyaml/NXcg_face_list_data_structure.yaml # contributed_definitions/nyaml/NXcg_geodesic_mesh.yaml # contributed_definitions/nyaml/NXcg_grid.yaml # contributed_definitions/nyaml/NXcg_half_edge_data_structure.yaml # contributed_definitions/nyaml/NXcg_hexahedron_set.yaml # contributed_definitions/nyaml/NXcg_marching_cubes.yaml # contributed_definitions/nyaml/NXcg_parallelogram_set.yaml # contributed_definitions/nyaml/NXcg_point_set.yaml # contributed_definitions/nyaml/NXcg_polygon_set.yaml # contributed_definitions/nyaml/NXcg_polyhedron_set.yaml # contributed_definitions/nyaml/NXcg_polyline_set.yaml # contributed_definitions/nyaml/NXcg_roi_set.yaml # contributed_definitions/nyaml/NXcg_sphere_set.yaml # contributed_definitions/nyaml/NXcg_tetrahedron_set.yaml # contributed_definitions/nyaml/NXcg_triangle_set.yaml # contributed_definitions/nyaml/NXcg_triangulated_surface_mesh.yaml # contributed_definitions/nyaml/NXcg_unit_normal_set.yaml # contributed_definitions/nyaml/NXchamber.yaml # contributed_definitions/nyaml/NXcoordinate_system_set.yaml # contributed_definitions/nyaml/NXcorrector_cs.yaml # contributed_definitions/nyaml/NXcs_computer.yaml # contributed_definitions/nyaml/NXcs_filter_boolean_mask.yaml # contributed_definitions/nyaml/NXcs_io_obj.yaml # contributed_definitions/nyaml/NXcs_io_sys.yaml # contributed_definitions/nyaml/NXcs_mm_sys.yaml # contributed_definitions/nyaml/NXcs_prng.yaml # contributed_definitions/nyaml/NXcs_profiling.yaml # contributed_definitions/nyaml/NXcs_profiling_event.yaml # contributed_definitions/nyaml/NXdeflector.yaml # contributed_definitions/nyaml/NXebeam_column.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXem_img.yaml # contributed_definitions/nyaml/NXem_sim.yaml # contributed_definitions/nyaml/NXevent_data_em.yaml # contributed_definitions/nyaml/NXevent_data_em_set.yaml # contributed_definitions/nyaml/NXfabrication.yaml # contributed_definitions/nyaml/NXgraph_edge_set.yaml # contributed_definitions/nyaml/NXgraph_node_set.yaml # contributed_definitions/nyaml/NXgraph_root.yaml # contributed_definitions/nyaml/NXibeam_column.yaml # contributed_definitions/nyaml/NXimage_set.yaml # contributed_definitions/nyaml/NXinteraction_vol_em.yaml # contributed_definitions/nyaml/NXion.yaml # contributed_definitions/nyaml/NXisocontour.yaml # contributed_definitions/nyaml/NXlens_em.yaml # contributed_definitions/nyaml/NXms.yaml # contributed_definitions/nyaml/NXms_feature_set.yaml # contributed_definitions/nyaml/NXms_score_results.yaml # contributed_definitions/nyaml/NXoptical_system_em.yaml # contributed_definitions/nyaml/NXpump.yaml # contributed_definitions/nyaml/NXrotation_set.yaml # contributed_definitions/nyaml/NXscanbox_em.yaml # contributed_definitions/nyaml/NXspectrum_set.yaml # contributed_definitions/nyaml/NXstage_lab.yaml # dev_tools/tests/test_nxdl_utils.py # manual/source/classes/contributed_definitions/cgms-structure.rst # manual/source/classes/contributed_definitions/em-structure.rst # manual/source/classes/contributed_definitions/icme-structure.rst --- .../NXcomponent_em.nxdl.xml | 69 ++++ contributed_definitions/NXcs_cpu_obj.nxdl.xml | 39 ++ contributed_definitions/NXcs_cpu_sys.nxdl.xml | 48 +++ contributed_definitions/NXcs_gpu_obj.nxdl.xml | 39 ++ contributed_definitions/NXcs_gpu_sys.nxdl.xml | 47 +++ contributed_definitions/NXcs_mm_obj.nxdl.xml | 51 +++ .../{NXem_img.nxdl.xml => NXem_adf.nxdl.xml} | 42 +- contributed_definitions/NXem_base.nxdl.xml | 389 ++++++++++++++++++ .../NXem_conventions_ebsd.nxdl.xml | 230 +++++++++++ contributed_definitions/NXem_eds.nxdl.xml | 144 +++++++ contributed_definitions/NXem_method.nxdl.xml | 47 +++ contributed_definitions/NXem_sim.nxdl.xml | 59 --- .../NXimage_c_set.nxdl.xml | 247 +++++++++++ .../NXimage_r_set.nxdl.xml | 100 +++++ .../NXimage_r_set_diff.nxdl.xml | 179 ++++++++ .../nyaml/NXcomponent_em.yaml | 39 ++ .../nyaml/NXcs_cpu_obj.yaml | 12 + .../nyaml/NXcs_cpu_sys.yaml | 21 + .../nyaml/NXcs_gpu_obj.yaml | 12 + .../nyaml/NXcs_gpu_sys.yaml | 20 + .../nyaml/NXcs_mm_obj.yaml | 21 + .../nyaml/{NXem_img.yaml => NXem_adf.yaml} | 23 +- contributed_definitions/nyaml/NXem_base.yaml | 297 +++++++++++++ .../nyaml/NXem_conventions.yaml | 296 +++++++++++++ .../nyaml/NXem_conventions_ebsd.yaml | 125 ++++++ contributed_definitions/nyaml/NXem_eds.yaml | 80 ++++ .../nyaml/NXem_method.yaml | 21 + contributed_definitions/nyaml/NXem_sim.yaml | 33 -- .../nyaml/NXimage_c_set.yaml | 140 +++++++ .../nyaml/NXimage_r_set.yaml | 45 ++ .../nyaml/NXimage_r_set_diff.yaml | 123 ++++++ 31 files changed, 2915 insertions(+), 123 deletions(-) create mode 100644 contributed_definitions/NXcomponent_em.nxdl.xml create mode 100644 contributed_definitions/NXcs_cpu_obj.nxdl.xml create mode 100644 contributed_definitions/NXcs_cpu_sys.nxdl.xml create mode 100644 contributed_definitions/NXcs_gpu_obj.nxdl.xml create mode 100644 contributed_definitions/NXcs_gpu_sys.nxdl.xml create mode 100644 contributed_definitions/NXcs_mm_obj.nxdl.xml rename contributed_definitions/{NXem_img.nxdl.xml => NXem_adf.nxdl.xml} (74%) create mode 100644 contributed_definitions/NXem_base.nxdl.xml create mode 100644 contributed_definitions/NXem_conventions_ebsd.nxdl.xml create mode 100644 contributed_definitions/NXem_eds.nxdl.xml create mode 100644 contributed_definitions/NXem_method.nxdl.xml delete mode 100644 contributed_definitions/NXem_sim.nxdl.xml create mode 100644 contributed_definitions/NXimage_c_set.nxdl.xml create mode 100644 contributed_definitions/NXimage_r_set.nxdl.xml create mode 100644 contributed_definitions/NXimage_r_set_diff.nxdl.xml create mode 100644 contributed_definitions/nyaml/NXcomponent_em.yaml create mode 100644 contributed_definitions/nyaml/NXcs_cpu_obj.yaml create mode 100644 contributed_definitions/nyaml/NXcs_cpu_sys.yaml create mode 100644 contributed_definitions/nyaml/NXcs_gpu_obj.yaml create mode 100644 contributed_definitions/nyaml/NXcs_gpu_sys.yaml create mode 100644 contributed_definitions/nyaml/NXcs_mm_obj.yaml rename contributed_definitions/nyaml/{NXem_img.yaml => NXem_adf.yaml} (58%) create mode 100644 contributed_definitions/nyaml/NXem_base.yaml create mode 100644 contributed_definitions/nyaml/NXem_conventions.yaml create mode 100644 contributed_definitions/nyaml/NXem_conventions_ebsd.yaml create mode 100644 contributed_definitions/nyaml/NXem_eds.yaml create mode 100644 contributed_definitions/nyaml/NXem_method.yaml delete mode 100644 contributed_definitions/nyaml/NXem_sim.yaml create mode 100644 contributed_definitions/nyaml/NXimage_c_set.yaml create mode 100644 contributed_definitions/nyaml/NXimage_r_set.yaml create mode 100644 contributed_definitions/nyaml/NXimage_r_set_diff.yaml diff --git a/contributed_definitions/NXcomponent_em.nxdl.xml b/contributed_definitions/NXcomponent_em.nxdl.xml new file mode 100644 index 000000000..bedba8b6f --- /dev/null +++ b/contributed_definitions/NXcomponent_em.nxdl.xml @@ -0,0 +1,69 @@ + + + + + + + Base class for components used in an electron microscope. + + The electron microscope can be a real one or a simulated microscope. + The key motivation behind this generalization is the observation that in all + cases a controlled electron beam is generated in reality or that beam is simulated + and this beam is then used or modified in a controlled manner for the purpose + of studying physical interaction mechanisms of the beam with matter. + Here it does not matter whether one considers a real specimen or a simulated one. + + Using a common description for the real experiment in the lab and - what is + typically a simplification of it - via a computer simulation, has the benefit + that many pieces of information can be stored in the same way. In effect, + users are guided with finding information and unnecessary descriptive + variety for what are exactly the same concept is avoided to work towards + more interoperability. + + Another motivation to make no fundamental distinction between a scanning and + a transmission electron microscope is that both are electron microscopes whose + components are often very similar. + + + + Given name to the component e.g stage, lens C1, etc. + + + + + Ideally, a (globally) unique persistent identifier, link, or text to a + resource which gives further details to this component. + If such resource does not exist, a free-text field to report + further details about the component is possible. + + + + + + + Collection of axis-based translations and rotations to describe the + location and geometry of the component in the instrument. + + + diff --git a/contributed_definitions/NXcs_cpu_obj.nxdl.xml b/contributed_definitions/NXcs_cpu_obj.nxdl.xml new file mode 100644 index 000000000..6ce5370a3 --- /dev/null +++ b/contributed_definitions/NXcs_cpu_obj.nxdl.xml @@ -0,0 +1,39 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a (central) processing unit (C)PU of a computer. + + + + Given name of the CPU. Users should be as specific as possible. + + + + diff --git a/contributed_definitions/NXcs_cpu_sys.nxdl.xml b/contributed_definitions/NXcs_cpu_sys.nxdl.xml new file mode 100644 index 000000000..0de162c66 --- /dev/null +++ b/contributed_definitions/NXcs_cpu_sys.nxdl.xml @@ -0,0 +1,48 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a system of classical central processing units. + + For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. + + + + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single CPU one + could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of + :ref:`NXcs_cpu_sys`. + A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` + inside one instance of :ref:`NXcs_cpu_sys`. + A server with two dual-socket server nodes one could describe + with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. + + + diff --git a/contributed_definitions/NXcs_gpu_obj.nxdl.xml b/contributed_definitions/NXcs_gpu_obj.nxdl.xml new file mode 100644 index 000000000..3c5b6c26a --- /dev/null +++ b/contributed_definitions/NXcs_gpu_obj.nxdl.xml @@ -0,0 +1,39 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a graphic processing unit (GPU) of a computer. + + + + Given name of the GPU. Users should be as specific as possible. + + + + diff --git a/contributed_definitions/NXcs_gpu_sys.nxdl.xml b/contributed_definitions/NXcs_gpu_sys.nxdl.xml new file mode 100644 index 000000000..217f1adb2 --- /dev/null +++ b/contributed_definitions/NXcs_gpu_sys.nxdl.xml @@ -0,0 +1,47 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a system of coprocessor or graphics processors. + + + + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single GPU one + could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of + :ref:`NXcs_gpu_sys`. + A desktop computer with two GPUs one could describe using two instances + of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. + A GPU server like nowadays used for artificial intelligence + one could describe as a system with n instances of :ref:`NXcs_gpu_obj` + in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. + + + diff --git a/contributed_definitions/NXcs_mm_obj.nxdl.xml b/contributed_definitions/NXcs_mm_obj.nxdl.xml new file mode 100644 index 000000000..e2b247079 --- /dev/null +++ b/contributed_definitions/NXcs_mm_obj.nxdl.xml @@ -0,0 +1,51 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a memory in a memory system. + + + + Qualifier for the type of random access memory. + + + + + + Total amount of data which the medium can hold. + + + + + + Given name to the I/O unit. + + + + diff --git a/contributed_definitions/NXem_img.nxdl.xml b/contributed_definitions/NXem_adf.nxdl.xml similarity index 74% rename from contributed_definitions/NXem_img.nxdl.xml rename to contributed_definitions/NXem_adf.nxdl.xml index cbe26c4b8..64534699c 100644 --- a/contributed_definitions/NXem_img.nxdl.xml +++ b/contributed_definitions/NXem_adf.nxdl.xml @@ -21,9 +21,26 @@ # # For further information, see http://www.nexusformat.org --> - + + + + + Number of images in the stack. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + - Base class for method-specific generic imaging. + Base class method-specific for annular dark field imaging. In the majority of cases simple d-dimensional regular scan patterns are used to probe a region-of-interest (ROI). Examples can be single point aka spot @@ -33,18 +50,7 @@ For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. - - - Which imaging mode was used? - - - - - - - - - + Annulus inner (first value) and outer (second value) half angle. @@ -53,11 +59,7 @@ - - - A reconstruction of the microstructure or some of its features - based on image information in the parent class. - - + diff --git a/contributed_definitions/NXem_base.nxdl.xml b/contributed_definitions/NXem_base.nxdl.xml new file mode 100644 index 000000000..479819893 --- /dev/null +++ b/contributed_definitions/NXem_base.nxdl.xml @@ -0,0 +1,389 @@ + + + + + + + + Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. + + This base class combines a method-specific and technical-design-level base class + instance to provide a template for storing parameterized descriptions of + pieces of information collected when performing electron microscopy research. + + The base class here shows all possible branches without making any statements + as to which of these have to be used in an instance. Thereby, the base class + provides a template how to name and structure concepts in a hierarchy + to support finding information and reducing the need for renaming and + restructuring information for a research field where many scientists perform + very specific research but who all also share commonalities like usage of + controlled electron beams, a focus on studies of electron beam matter interaction + to explore physical mechanisms and phenomena, or the desire to characterize materials + using electron microscopy. + + + + A collection of all programs and libraries which are considered relevant + to understand with which software tools this NeXus file instance was + generated. Ideally, to enable a binary recreation from the input data. + + Examples include the name and version of the libraries used to write the + instance. Ideally, the software that writes these :ref:`NXprogram` instances + also includes the version of the set of NeXus classes i.e. the specific + set of base classes, application definitions, and contributed definitions + with which the here described concepts can be resolved. + + For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ + which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ + research data management system, it makes sense to store e.g. the GitHub + repository commit and respective submodule references used. + + + + + + The configuration of the I/O writer software (e.g. `pynxtools <https://github.com/FAIRmat-NFDI/pynxtools>`_) + which was used to generate this NeXus file instance. + + + + + + An at least as strong as SHA256 hashvalue of the file + which specifies the application definition. + + + + + NeXus NXDL schema to which this file conforms. + + + + + + + + Ideally, a (globally) unique persistent identifier + for referring to this experiment. + + An experiment should be understood in that this can be an experiment + in reality or a computer simulation because also the latter is an + experiment (see the Cambridge Dictionary experiment: + *a test done in order to find out something, eg if an idea is correct*). + + The identifier is usually issued by the facility, laboratory, + or the principle investigator. The identifier enables to link + experiments/simulations to e.g. proposals. + + + + + Free-text description about the experiment. + + Users are strongly advised to parameterize their description of the + experiment by using the respective base classes instead of writing prose + into this field. + + The reason is that such free-text field is difficult to machine-interpret. + The motivation behind keeping this field for now is to learn through + the information entered in this field in how far the current base + classes are incomplete. + + + + + ISO 8601 time code with local time zone offset to UTC information included + when the microscope session started. If the application demands that time + codes in this section of the application definition should only be used + for specifying when the experiment was performed - and the exact + duration is not relevant - this start_time field should be used. + + Often though it is useful to specify a time interval via setting both + a start_time and an end_time because this enables software tools and + users to collect a more detailed bookkeeping of the experiment. + + The user should be aware that even with having both time instances specified, + it may not be possible to infer how long the experiment took or for how + long data were acquired. + + More detailed timing data over the course of the experiment have + to be collected to compute this. These computations can take + advantage of individual time stamps start_time and end_time + in :ref:`NXevent_data_em` instances. + + + + + ISO 8601 time code with local time zone offset to UTC included when + the microscope session ended. See docstring of the start_time field + to see how the start_time and end_time should be used together. + + + + + + The program and eventual software libraries used with which the + NeXus instance was created. For the NOMAD OASIS research data + management system e.g. pynxtools and eventually all modules + if desired. + + + + + + Possibility to store a collection of data artifacts + associated with the experiment. + + + + + + Contact information and eventually details of at least one person + who performed or was involved in the session. This can be the + principle investigator who performed this experiment or the student + who performed the simulation. + Adding multiple users if relevant is recommended. + + + + Given (first) name and surname of the user. + + + + + Name of the affiliation of the user at the point in time + when the experiment was performed. + + + + + Postal address of the affiliation. + + + + + Email address of the user at the point in time when the experiment + was performed. Writing the most permanently used email is recommended. + + + + + Service as another mean of identification of a user than by the name. + Examples could be details about an ORCID or social media account of + the user. + + + + + (Business) (tele)phone number of the user at the point + in time when the experiment was performed. + + + + + Which role does the user have in the place and at the point + in time when the experiment was performed? Technician operating + the microscope, student, postdoc, principle investigator, or guest + are common examples. + + + + + + + A description of the material characterized in the experiment. + Sample and specimen are threaded as de facto synonyms. + Samples can be real specimens or virtual (see method). + + + + A qualifier whether the sample is a real one or a + virtual one (in a computer simulation) + + + + + + + + + + Ideally, (globally) unique persistent identifier which distinguishes + the specimen from all others and especially the predecessor/origin + from where the specimen was cut. + + This field must not be used for an alias! Instead, use name. + + In cases where multiple specimens were loaded into the microscope, + the identifier has to resolve the specific sample, whose results are + stored by this :ref:`NXentry` instance, because a single NXentry should be + used only for the characterization of a single specimen. + + Details about the specimen preparation should be + stored in resources referring to parent_identifier. + + + + + Identifier of the sample from which the sample was cut or the string + *None*. The purpose of this field is to support functionalities + for tracking sample provenance via a research data management system. + + + + + ISO 8601 time code with local time zone offset to UTC information + when the specimen was prepared. + + Ideally, report the end of the preparation, i.e. the last known time + the measured specimen surface was actively prepared. Ideally, this + matches the last timestamp that is mentioned in the digital resource + pointed to by parent_identifier. + + Knowing when the specimen was exposed to e.g. specific atmosphere is + especially required for environmentally sensitive material such as + hydrogen charged specimens or experiments including tracers with a + short half time. Additional time stamps prior to preparation_date + should better be placed in resources which describe but which do not pollute + the description here with prose. Resolving these connected pieces of information + is considered within the responsibility of the research data management + system. + + + + + An alias used to refer to the specimen to please readability for humans. + + + + + List of comma-separated elements from the periodic table that are + contained in the sample. If the sample substance has multiple + components, all elements from each component must be included in + `atom_types`. + + The purpose of the field is to offer research data management systems an + opportunity to parse the relevant elements without having to interpret + these from the resources pointed to by parent_identifier or walk through + eventually deeply nested groups in data instances. + + + + + + (Measured) sample thickness. + + The information is recorded to qualify if the beam used was likely + able to shine through the specimen. For scanning electron microscopy, + in many cases the specimen is typically thicker than what is + illuminatable by the electron beam. + + In this case the value should be set to the actual thickness of + the specimen viewed for an illumination situation where the nominal + surface normal of the specimen is parallel to the optical axis. + + + + + + + (Measured) density of the specimen. + + For multi-layered specimens this field should only be used to describe + the density of the excited volume. For scanning electron microscopy + the usage of this field is discouraged and instead an instance of an + :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` + instances can provide a cleaner description of the relevant details + why one may wish to store the density of the specimen. + + + + + Discouraged free-text field to provide further detail although adding + parent_identifier and having a working research data management system + should provide this contextualization. + + + + + + + + + + + + A region-of-interest analyzed either during or after the session + for which specific processed data generated from the measured or the + simulated data are available. + + + + + + + + + + + + diff --git a/contributed_definitions/NXem_conventions_ebsd.nxdl.xml b/contributed_definitions/NXem_conventions_ebsd.nxdl.xml new file mode 100644 index 000000000..8a19f1e29 --- /dev/null +++ b/contributed_definitions/NXem_conventions_ebsd.nxdl.xml @@ -0,0 +1,230 @@ + + + + + + + Base class for method-specific conventions EBSD. + + This base class is expected to be used with :ref:`NXem_conventions`. + + This is the main issue which currently is not in all cases documented + and thus limits the interoperability and value of collected EBSD data. + Not communicating EBSD data with such contextual pieces of information + and the use of file formats which do not store this information is the + key unsolved problem. + + + + Details about the gnomonic projection reference frame. + + + + Type of coordinate system/reference frame used for identifying + positions in the gnomonic projection space Xg, Yg, Zg + according to DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + Handedness of coordinate system. + + + + + + + + + Is the origin of the gnomonic coordinate system located + where we assume the location of the pattern centre. + This is the location Xg = 0, Yg = 0, Zg = 0 according to + reference DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + Direction of the positively pointing "gnomomic" x-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + + + + + + + + + + + + + + Direction of the positively pointing "gnomomic" y-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + Direction of the positively pointing "gnomomic" z-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + + Details about the definition of the pattern centre + as a special point in the gnomonic projection reference frame. + + + + From which border of the EBSP (in the detector reference frame) + is the pattern centre's x-position (PCx) measured? + Keywords assume the region-of-interest is defined by + a rectangle. We observe this rectangle and inspect the + direction of the outer-unit normals to the edges of + this rectangle. + + + + + + + + + + + + In which direction are positive values for PCx measured from + the specified boundary. Keep in mind that the gnomonic space + is in virtually all cases embedded in the detector space. + Specifically, the XgYg plane is defined such that it is + embedded/laying inside the XdYd plane (of the detector + reference frame). + When the normalization direction is the same as e.g. the + detector x-axis direction, we state that we effectively + normalize in fractions of the width of the detector. + + The issue with terms like width and height is that these + degenerate if the detector region-of-interest is square-shaped. + This is why we should better avoid talking about width and height but + state how we would measure distances practically with a ruler and + how we then measure positive distances. + + + + + + + + + + + + From which border of the EBSP (in the detector reference + frame) is the pattern centre's y-position (PCy) measured? + For further details inspect the help button of + xaxis_boundary_convention. + + + + + + + + + + + + In which direction are positive values for PCy measured from + the specified boundary. + For further details inspect the help button of + xaxis_normalization_direction. + + + + + + + + + + + + diff --git a/contributed_definitions/NXem_eds.nxdl.xml b/contributed_definitions/NXem_eds.nxdl.xml new file mode 100644 index 000000000..735bfe897 --- /dev/null +++ b/contributed_definitions/NXem_eds.nxdl.xml @@ -0,0 +1,144 @@ + + + + + + + + + + Number of pixel along the y direction, the slow direction + + + + + Number of pixel along the x direction, the fast direction + + + + + Number of X-ray photon energy (bins), the fastest direction. + + + + + Number of identified elements + + + + + Number of peaks detected + + + + + Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). + + `IUPAC instead of Siegbahn notation <https://doi.org/10.1002/xrs.1300200308>`_ should be used. + + + + + Details about computational steps how peaks were indexed as elements. + + + + The program with which the indexing was performed. + + + + + Name and location of each X-ray line which was indexed as a known ion. + For each ion, an NXion instance should be created which specifies + the origin of the signal. For each ion also the relevant IUPAC notation + X-ray lines should be specified. + + + + + Associated lower :math:`[e_{min}, e_{max}]` bounds of the + energy which is assumed associated with this peak. + + + + + + + + Theoretical energy of the line according to IUPAC. + + + + + IUPAC notation identifier of the line which the peak represents. + + This can be a list of IUPAC notations for (the seldom) case that + multiple lines are grouped with the same peak. + + + + + + + + + + List of the names of identified elements. + + + + + + + + Individual element-specific EDS/EDX/EDXS/SXES mapping + + A composition map is an image whose intensities for each pixel are the + accumulated X-ray quanta *under the curve(s)* of a set of peaks. + + These element-specific EDS maps are NXimage_r_set instances + and need to be named with the name of the element from the + element_names field. + + + + + A list of NXpeak instance names whose X-ray quanta + where accumulated for each pixel which yields an element-specific + EDS map. + + + + + + + + + + diff --git a/contributed_definitions/NXem_method.nxdl.xml b/contributed_definitions/NXem_method.nxdl.xml new file mode 100644 index 000000000..086d4833d --- /dev/null +++ b/contributed_definitions/NXem_method.nxdl.xml @@ -0,0 +1,47 @@ + + + + + + + Base class to describe specific analysis methods in electron microscopy. + + This base class represent a template how specialized, deep, and method-specific + base classes can be defined with which an (NXem) application + definition gets equipped with specific groups to document method-specific + processing steps and report analyzed quantities. + + The template base class name :ref:`NXem_method` needs to be changed for each + method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. + + + + Details about processing steps. + + + + + + + diff --git a/contributed_definitions/NXem_sim.nxdl.xml b/contributed_definitions/NXem_sim.nxdl.xml deleted file mode 100644 index 560fee2fd..000000000 --- a/contributed_definitions/NXem_sim.nxdl.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - Base class for simulating electron microscopy relevant beam-matter interaction. - - The concept behind this base class is to keep it as generic as possible - that simulations of electron/ion beam interaction with matter can be - represented. This base class is envisioned as the twin of the :ref:`NXem_msr` - base class. - - It is an attempt to test the idea if at some point one might even use the - same base class template to describe measurements and computer simulations - of electron microscopy. This idea is attractive because the only practical - difference between a description of a measurement with a microscope and a - computer simulation is that the latter is typically a substantially simplified - representation of the real microscope surplus the focus of the research - in such cases on specific questions. - - Such simplification can be with respect to the optical setup, typically the - ignoring of the fact that the electron beam is produced by a complex setup - of lenses while in simulations often single Einzel lenses are considered. - Dynamics of the environment like temperature fluctuation in a lab, vibrations, - users, and multiple detectors are typically either ignored or reduced in - complexity and number and coming with idealizations to keep the simulations - focused on the specific reason questions and efficiently numerically executable. - - - - Details about the simulation. - - - - - - diff --git a/contributed_definitions/NXimage_c_set.nxdl.xml b/contributed_definitions/NXimage_c_set.nxdl.xml new file mode 100644 index 000000000..64c945c99 --- /dev/null +++ b/contributed_definitions/NXimage_c_set.nxdl.xml @@ -0,0 +1,247 @@ + + + + + + + + Number of images in the (hyper)stack. + + + + + Number of pixel per image in the slowest direction. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + + + Specialized base class container for reporting a set of images in reciprocal space. + + In practice, complex numbers are encoded via some formatted pair of real values. + Typically, fast Algorithms for computing Fourier Transformations (FFT) are + used to encode images in reciprocal (frequency) space. FFT libraries are used + for implementing the key functionalities of these mathematical operations. + + Different libraries use different representations and encoding of the + image computed. Details can be found in the respective sections of the + typical FFT libraries: + + * `FFTW by M. Frigo and S. G. Johnson <https://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial>`_ + * `Intel MKL by the Intel Co. <https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2023-0/fourier-transform-functions.html>`_ + * `cuFFT by the NVidia Co. <https://docs.nvidia.com/cuda/cufft/index.html>`_ + + Users are strongly advised to inspect carefully which specific conventions + their library uses to be able to store and modify the implementation of their + code so that the serialized representations as it is detailed + here for NeXus matches with their intention. + + One- and two-dimensional FFTs should use the stack(NXdata) instances. + Three-dimensional FFTs should use the hyperstack(NXdata) instances. + + + + + Image stack. + + + + Image intensity of the real part. + + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + + Pixel coordinate center along j direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + + + Image hyperstack. + + + + Image intensity of the real part. + + + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along k direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along j direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + diff --git a/contributed_definitions/NXimage_r_set.nxdl.xml b/contributed_definitions/NXimage_r_set.nxdl.xml new file mode 100644 index 000000000..3ef371809 --- /dev/null +++ b/contributed_definitions/NXimage_r_set.nxdl.xml @@ -0,0 +1,100 @@ + + + + + + + + Number of images in the stack. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + + + Specialized base class container for reporting a set of images in real space. + + + + + Image (stack). + + + + Image intensity values. + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along y direction. + + + + + + + Coordinate along y direction. + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + + diff --git a/contributed_definitions/NXimage_r_set_diff.nxdl.xml b/contributed_definitions/NXimage_r_set_diff.nxdl.xml new file mode 100644 index 000000000..c9ff02c0d --- /dev/null +++ b/contributed_definitions/NXimage_r_set_diff.nxdl.xml @@ -0,0 +1,179 @@ + + + + + + + + Number of scanned points. Scan point may have none, one, or more pattern. + + + + + Number of diffraction pattern. + + + + + Number of pixel per pattern in the slow direction. + + + + + Number of pixel per pattern in the fast direction. + + + + + Base class specialized for reporting a cuboidal stack of diffraction pattern. + + Diffraction pattern, whether they were simulated or measured are the raw data + for computational workflows to characterize the phase and orientation + of crystalline regions in matter. + + Steps of post-processing the diffraction patterns should be documented using + method-specific specialized base classes. All eventual post-processing of + resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. + + To implement an example how this base class can be used we focused in FAIRmat + on Kikuchi diffraction pattern here specifically the research community + of Electron Backscatter Diffraction (EBSD). + + For this reason, this base class and related :ref:`NXem_base` classes extend the + work of `M. A. Jackson et al. <https://doi.org/10.1186/2193-9772-3-4>`_ + (one of the developers of DREAM.3D) and the H5OINA public file format developed by + `P. Pinard et al. <https://doi.org/10.1017/S1431927621006103>`_ with Oxford Instruments. + + Kikuchi pattern are typically collected with FIB/SEM microscopes, + for two- and three-dimensional orientation microscopy. + + For a detailed overview of these techniques see e.g. + + * `M. A. Groeber et al. <https://doi.org/10.1186/2193-9772-3-5>`_ + * `A. J. Schwartz et al. <https://doi.org/10.1007/978-1-4757-3205-4>`_ + * `P. A. Rottman et al. <https://doi.org/10.1016/j.mattod.2021.05.003>`_ + + Serial-sectioning demands a recurrent sequence of ion milling and measuring. + This suggests that each serial section is at least an own NXevent_data_em + instance. The three-dimensional characterization as such demands a computational + step where the maps for each serial section get cleaned, aligned, and registered + into an image stack. This image stack represents a digital model of the + inspected microstructural volume. Often this volume is called a (representative) + volume element (RVE). Several software packages exists for performing + these post-processing tasks. + + This example may inspire users of other types of diffraction methods. + + + + Category which type of diffraction pattern is reported. + + + + + + + + Collected diffraction pattern as an image stack. As raw and closest to the + first retrievable measured data as possible, i.e. do not use this + container to store already averaged, filtered or whatever post-processed + pattern unless these are generated unmodifiably in such manner by the + instrument given the way how the instrument and control software + was configured for your microscope session. + + + + Array which resolves the scan point to which each pattern belongs. + + Scan points are evaluated in sequence starting from scan point zero + until scan point n_sc - 1. Evaluating the cumulated of this array + decodes which pattern in intensity belongs to which scan point. + + Take an example with three scan points: The first scan point has one + pattern, the second has three pattern, the last scan point has no + pattern. In this case the scan_point_identifier are 0, 1, 1, 1. + The length of the scan_point_identifier array is four because four + pattern were measured in total. + + In most cases usually one pattern is averaged by the detector for + some amount of time and then reported as one pattern. + + + + + + + + Intensity of the diffraction pattern. + + + + + + + + + + Pattern intensity + + + + + + + Pattern are enumerated starting from 0 to n_p - 1. + + + + + + + Pattern identifier + + + + + + + diff --git a/contributed_definitions/nyaml/NXcomponent_em.yaml b/contributed_definitions/nyaml/NXcomponent_em.yaml new file mode 100644 index 000000000..78870cc26 --- /dev/null +++ b/contributed_definitions/nyaml/NXcomponent_em.yaml @@ -0,0 +1,39 @@ +category: base +doc: | + Base class for components used in an electron microscope. + + The electron microscope can be a real one or a simulated microscope. + The key motivation behind this generalization is the observation that in all + cases a controlled electron beam is generated in reality or that beam is simulated + and this beam is then used or modified in a controlled manner for the purpose + of studying physical interaction mechanisms of the beam with matter. + Here it does not matter whether one considers a real specimen or a simulated one. + + Using a common description for the real experiment in the lab and - what is + typically a simplification of it - via a computer simulation, has the benefit + that many pieces of information can be stored in the same way. In effect, + users are guided with finding information and unnecessary descriptive + variety for what are exactly the same concept is avoided to work towards + more interoperability. + + Another motivation to make no fundamental distinction between a scanning and + a transmission electron microscope is that both are electron microscopes whose + components are often very similar. +# `point Electronic GmbH `_ +type: group +NXcomponent_em(NXobject): + name(NX_CHAR): + doc: | + Given name to the component e.g stage, lens C1, etc. + description(NX_CHAR): # NXidentifier + doc: | + Ideally, a (globally) unique persistent identifier, link, or text to a + resource which gives further details to this component. + If such resource does not exist, a free-text field to report + further details about the component is possible. + (NXfabrication): + (NXprogram): + (NXtransformations): + doc: | + Collection of axis-based translations and rotations to describe the + location and geometry of the component in the instrument. diff --git a/contributed_definitions/nyaml/NXcs_cpu_obj.yaml b/contributed_definitions/nyaml/NXcs_cpu_obj.yaml new file mode 100644 index 000000000..73097d5ca --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_cpu_obj.yaml @@ -0,0 +1,12 @@ +category: base +doc: | + Computer science description of a (central) processing unit (C)PU of a computer. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_cpu_obj(NXobject): + name(NX_CHAR): + doc: | + Given name of the CPU. Users should be as specific as possible. + (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_cpu_sys.yaml b/contributed_definitions/nyaml/NXcs_cpu_sys.yaml new file mode 100644 index 000000000..5eaf8f0ea --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_cpu_sys.yaml @@ -0,0 +1,21 @@ +category: base +doc: | + Computer science description of a system of classical central processing units. + + For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_cpu_sys(NXobject): + cpuID(NXcs_cpu_obj): + doc: | + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single CPU one + could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of + :ref:`NXcs_cpu_sys`. + A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` + inside one instance of :ref:`NXcs_cpu_sys`. + A server with two dual-socket server nodes one could describe + with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml new file mode 100644 index 000000000..04468b7b2 --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml @@ -0,0 +1,12 @@ +category: base +doc: | + Computer science description of a graphic processing unit (GPU) of a computer. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_gpu_obj(NXobject): # NXcircuit_board ? + name(NX_CHAR): + doc: | + Given name of the GPU. Users should be as specific as possible. + (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_gpu_sys.yaml b/contributed_definitions/nyaml/NXcs_gpu_sys.yaml new file mode 100644 index 000000000..dee199330 --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_gpu_sys.yaml @@ -0,0 +1,20 @@ +category: base +doc: | + Computer science description of a system of coprocessor or graphics processors. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_gpu_sys(NXobject): + gpuID(NXcs_gpu_obj): + doc: | + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single GPU one + could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of + :ref:`NXcs_gpu_sys`. + A desktop computer with two GPUs one could describe using two instances + of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. + A GPU server like nowadays used for artificial intelligence + one could describe as a system with n instances of :ref:`NXcs_gpu_obj` + in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_mm_obj.yaml b/contributed_definitions/nyaml/NXcs_mm_obj.yaml new file mode 100644 index 000000000..d1fead8c8 --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_mm_obj.yaml @@ -0,0 +1,21 @@ +category: base +doc: | + Computer science description of a memory in a memory system. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_mm_obj(NXobject): + technology(NX_CHAR): + doc: | + Qualifier for the type of random access memory. + # make an enumeration + max_physical_capacity(NX_NUMBER): + doc: | + Total amount of data which the medium can hold. + unit: NX_ANY + # NX_BIT + name(NX_CHAR): + doc: | + Given name to the I/O unit. + (NXfabrication): diff --git a/contributed_definitions/nyaml/NXem_img.yaml b/contributed_definitions/nyaml/NXem_adf.yaml similarity index 58% rename from contributed_definitions/nyaml/NXem_img.yaml rename to contributed_definitions/nyaml/NXem_adf.yaml index 015e6fa7d..b7011639e 100644 --- a/contributed_definitions/nyaml/NXem_img.yaml +++ b/contributed_definitions/nyaml/NXem_adf.yaml @@ -1,6 +1,6 @@ category: base doc: | - Base class for method-specific generic imaging. + Base class method-specific for annular dark field imaging. In the majority of cases simple d-dimensional regular scan patterns are used to probe a region-of-interest (ROI). Examples can be single point aka spot @@ -9,19 +9,20 @@ doc: | For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. +symbols: + n_images: | + Number of images in the stack. + n_y: | + Number of pixel per image in the slow direction. + n_x: | + Number of pixel per image in the fast direction. type: group -NXem_img(NXem_method): - imaging_mode(NX_CHAR): - doc: | - Which imaging mode was used? - enumeration: [secondary_electron, backscattered_electron, annular_dark_field, cathodoluminescence] - (NXimage_set): +NXem_adf(NXem_method): + IMAGE_R_SET(NXimage_r_set): half_angle_interval(NX_NUMBER): doc: | Annulus inner (first value) and outer (second value) half angle. unit: NX_ANGLE dim: (2,) - (NXmicrostructure): - doc: | - A reconstruction of the microstructure or some of its features - based on image information in the parent class. + # all information about annular dark field images is composed from + # the NXimage_r_set_em base class diff --git a/contributed_definitions/nyaml/NXem_base.yaml b/contributed_definitions/nyaml/NXem_base.yaml new file mode 100644 index 000000000..2de8081a8 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_base.yaml @@ -0,0 +1,297 @@ +category: base +# template to be used for an application definition +doc: | + Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. + + This base class combines a method-specific and technical-design-level base class + instance to provide a template for storing parameterized descriptions of + pieces of information collected when performing electron microscopy research. + + The base class here shows all possible branches without making any statements + as to which of these have to be used in an instance. Thereby, the base class + provides a template how to name and structure concepts in a hierarchy + to support finding information and reducing the need for renaming and + restructuring information for a research field where many scientists perform + very specific research but who all also share commonalities like usage of + controlled electron beams, a focus on studies of electron beam matter interaction + to explore physical mechanisms and phenomena, or the desire to characterize materials + using electron microscopy. +# flesh out the description of that to read the docs, because currently the +# description on the NeXus front-page is overwhelming +# considering what we learned from the diataxis workshop we write here a +# specification neither a how to nor a tutorial which explains all the context +# because we address here developers of software +type: group +NXem_base(NXroot): + (NXprogram): + doc: | + A collection of all programs and libraries which are considered relevant + to understand with which software tools this NeXus file instance was + generated. Ideally, to enable a binary recreation from the input data. + + Examples include the name and version of the libraries used to write the + instance. Ideally, the software that writes these :ref:`NXprogram` instances + also includes the version of the set of NeXus classes i.e. the specific + set of base classes, application definitions, and contributed definitions + with which the here described concepts can be resolved. + + For the `pynxtools library `_ + which is used by the `NOMAD `_ + research data management system, it makes sense to store e.g. the GitHub + repository commit and respective submodule references used. + # each NeXus file instance should have a default plot + # however as there are cases when this cannot be assured we cannot + # make the default required, one example is e.g. a NeXus instance + # where scientists just store conventions without a default plot + cs_profiling(NXcs_profiling): + doc: | + The configuration of the I/O writer software (e.g. `pynxtools `_) + which was used to generate this NeXus file instance. + (NXentry): # means ENTRY(NXentry) + \@version(NX_CHAR): + doc: | + An at least as strong as SHA256 hashvalue of the file + which specifies the application definition. + definition(NX_CHAR): + doc: | + NeXus NXDL schema to which this file conforms. + enumeration: [NXem] + experiment_identifier(NXidentifier): + doc: | + Ideally, a (globally) unique persistent identifier + for referring to this experiment. + + An experiment should be understood in that this can be an experiment + in reality or a computer simulation because also the latter is an + experiment (see the Cambridge Dictionary experiment: + *a test done in order to find out something, eg if an idea is correct*). + + The identifier is usually issued by the facility, laboratory, + or the principle investigator. The identifier enables to link + experiments/simulations to e.g. proposals. + experiment_description(NX_CHAR): + doc: | + Free-text description about the experiment. + + Users are strongly advised to parameterize their description of the + experiment by using the respective base classes instead of writing prose + into this field. + + The reason is that such free-text field is difficult to machine-interpret. + The motivation behind keeping this field for now is to learn through + the information entered in this field in how far the current base + classes are incomplete. + start_time(NX_DATE_TIME): + doc: | + ISO 8601 time code with local time zone offset to UTC information included + when the microscope session started. If the application demands that time + codes in this section of the application definition should only be used + for specifying when the experiment was performed - and the exact + duration is not relevant - this start_time field should be used. + + Often though it is useful to specify a time interval via setting both + a start_time and an end_time because this enables software tools and + users to collect a more detailed bookkeeping of the experiment. + + The user should be aware that even with having both time instances specified, + it may not be possible to infer how long the experiment took or for how + long data were acquired. + + More detailed timing data over the course of the experiment have + to be collected to compute this. These computations can take + advantage of individual time stamps start_time and end_time + in :ref:`NXevent_data_em` instances. + end_time(NX_DATE_TIME): + doc: | + ISO 8601 time code with local time zone offset to UTC included when + the microscope session ended. See docstring of the start_time field + to see how the start_time and end_time should be used together. + (NXcite): + (NXprogram): + doc: | + The program and eventual software libraries used with which the + NeXus instance was created. For the NOMAD OASIS research data + management system e.g. pynxtools and eventually all modules + if desired. + # the above-description overwrites the default description of the NXprogram base class + # this is composed from the NXprogram base class + # program: + # \@version: + # \@url: + # NXnote and thumbnail dropped for the reason that these are + # arbitrary binary containers without any clear provenance. + (NXserialized): + doc: | + Possibility to store a collection of data artifacts + associated with the experiment. + # using NXserialized here instead of NXnote as the former is more specific + (NXuser): + doc: | + Contact information and eventually details of at least one person + who performed or was involved in the session. This can be the + principle investigator who performed this experiment or the student + who performed the simulation. + Adding multiple users if relevant is recommended. + name(NX_CHAR): + doc: | + Given (first) name and surname of the user. + affiliation(NX_CHAR): + doc: | + Name of the affiliation of the user at the point in time + when the experiment was performed. + address(NX_CHAR): + doc: | + Postal address of the affiliation. + email(NX_CHAR): + doc: | + Email address of the user at the point in time when the experiment + was performed. Writing the most permanently used email is recommended. + identifier(NXidentifier): + doc: | + Service as another mean of identification of a user than by the name. + Examples could be details about an ORCID or social media account of + the user. + telephone_number(NX_CHAR): + doc: | + (Business) (tele)phone number of the user at the point + in time when the experiment was performed. + role(NX_CHAR): + doc: | + Which role does the user have in the place and at the point + in time when the experiment was performed? Technician operating + the microscope, student, postdoc, principle investigator, or guest + are common examples. + sample(NXsample): + # NEW ISSUE: inject the conclusion from the discussion with Andrea + # according to SAMPLE.yaml 0f8df14 2022/06/15 + # ID: -> maps to name + # name: -> short_title + # user: -> not matched right now + # citation: doi ->why relevant, should be solved by RDMS + doc: | + A description of the material characterized in the experiment. + Sample and specimen are threaded as de facto synonyms. + Samples can be real specimens or virtual (see method). + method(NX_CHAR): + doc: | + A qualifier whether the sample is a real one or a + virtual one (in a computer simulation) + enumeration: [experiment, simulation] + # MK:: declared_by_vendor I would rather expect this for a substance + # COMPONENT.yaml + # SUBSTANCE: + # QUANTIFY + identifier(NXidentifier): + doc: | + Ideally, (globally) unique persistent identifier which distinguishes + the specimen from all others and especially the predecessor/origin + from where the specimen was cut. + + This field must not be used for an alias! Instead, use name. + + In cases where multiple specimens were loaded into the microscope, + the identifier has to resolve the specific sample, whose results are + stored by this :ref:`NXentry` instance, because a single NXentry should be + used only for the characterization of a single specimen. + + Details about the specimen preparation should be + stored in resources referring to parent_identifier. + parent_identifier(NXidentifier): + doc: | + Identifier of the sample from which the sample was cut or the string + *None*. The purpose of this field is to support functionalities + for tracking sample provenance via a research data management system. + preparation_date(NX_DATE_TIME): + doc: | + ISO 8601 time code with local time zone offset to UTC information + when the specimen was prepared. + + Ideally, report the end of the preparation, i.e. the last known time + the measured specimen surface was actively prepared. Ideally, this + matches the last timestamp that is mentioned in the digital resource + pointed to by parent_identifier. + + Knowing when the specimen was exposed to e.g. specific atmosphere is + especially required for environmentally sensitive material such as + hydrogen charged specimens or experiments including tracers with a + short half time. Additional time stamps prior to preparation_date + should better be placed in resources which describe but which do not pollute + the description here with prose. Resolving these connected pieces of information + is considered within the responsibility of the research data management + system. + name(NX_CHAR): + doc: | + An alias used to refer to the specimen to please readability for humans. + atom_types(NX_CHAR): + doc: | + List of comma-separated elements from the periodic table that are + contained in the sample. If the sample substance has multiple + components, all elements from each component must be included in + `atom_types`. + + The purpose of the field is to offer research data management systems an + opportunity to parse the relevant elements without having to interpret + these from the resources pointed to by parent_identifier or walk through + eventually deeply nested groups in data instances. + # NEW ISSUE: use Andrea and MarkusK groups for describing the geometry of the sample + thickness(NX_NUMBER): + doc: | + (Measured) sample thickness. + + The information is recorded to qualify if the beam used was likely + able to shine through the specimen. For scanning electron microscopy, + in many cases the specimen is typically thicker than what is + illuminatable by the electron beam. + + In this case the value should be set to the actual thickness of + the specimen viewed for an illumination situation where the nominal + surface normal of the specimen is parallel to the optical axis. + unit: NX_LENGTH + # \@units: nm + # NEW ISSUE: error estimates of the thickness and origin, i.e. how the value was obtained would be useful + # NEW ISSUE: error model + # NEW ISSUE: the KIT/SCC SEM, TEM schemata further qualify samples whether they are conductive e/ibeam sensitive + # etc. The problem with this is that beam sensitivity is too vague but spatiotemporal electron dose integral dependent + # KIT/SCC distinguish further conductivity and magnetic properties. While the motivation is clear, making + # it thus simple is likely problematic when the data entered in such fields remaining qualitative. + # what are good or bad properties, it would make sense though to quantify these values + # this includes the description of eventual plasma cleaning steps, + # just knowing that a sample was plasma cleaned is insufficient, maybe it was not cleaned long enough + # if plasma cleaning is done outside the EM than its certainly history, if it happens inside the EM + # are the ibeam description capabilities not sufficient enough? + density(NX_NUMBER): + # NX_MASS_PER_VOLUME + doc: | + (Measured) density of the specimen. + + For multi-layered specimens this field should only be used to describe + the density of the excited volume. For scanning electron microscopy + the usage of this field is discouraged and instead an instance of an + :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` + instances can provide a cleaner description of the relevant details + why one may wish to store the density of the specimen. + unit: NX_ANY + description: + doc: | + Discouraged free-text field to provide further detail although adding + parent_identifier and having a working research data management system + should provide this contextualization. + # (NXmonitor): + (NXdata): + (NXcoordinate_system_set): + # link to an instance of an NXinstrument but that is anyway specialized for EM + measurement(NXem_msr): + simulation(NXem_sim): + (NXroi): + doc: | + A region-of-interest analyzed either during or after the session + for which specific processed data generated from the measured or the + simulated data are available. + se(NXem_img): + bse(NXem_img): + ebsd(NXem_ebsd): + eds(NXem_eds): + adf(NXem_adf): + eels(NXem_eels): + correlation(NXem_correlation): + # cl(NXem_cl): diff --git a/contributed_definitions/nyaml/NXem_conventions.yaml b/contributed_definitions/nyaml/NXem_conventions.yaml new file mode 100644 index 000000000..7835d9a65 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_conventions.yaml @@ -0,0 +1,296 @@ +category: base +# symbols: +doc: | + Conventions for rotations and coordinate systems to interpret crystal orientation + and other data and results collected with electron microscopy research. + + Documenting explicitly all used conventions and coordinate systems is + the decisive context whereby many results from electron microscopy are + at all interpretable. + +# This base class provides several sets of such assumptions and conventions. +# Further base classes should be defined when specific techniques and methods +# demand further specifications or have specialized demands. NXem_conventions_ebsd +# is an example for such method-specific base class to summarize key conventions +# for Electron Backscatter Diffraction (EBSD). + +# What is could be a best practice for application definition developers +# who would like to describe an electron microscopy case where multiple +# methods and/or detectors are used. In this case one should define a +# method-specific base class like the template NXem_conventions_ebsd. +# Even though this may come at a cost of some duplicated information where +# the same physical detector is used in different ways, i.e. the signal collect +# from the detector is interpreted in a different way. +# As in most cases established types of signal and thus detectors are used +# (secondary electron, backscattered electron, etc.) one could equally use +# just one NXem_conventions base class instance in an application definition +# and use detector_reference_frame as a template. For each method and detector +# one then creates one NXprocess group named detector_reference_frame1, +# detector_reference_frame2, detector_reference_frame3, and so on and so forth +# and adds inside that NXprocess and use the depends_on field. + +# What is considered best practice in an application definition with multiple +# NXentry instances? In this case each NXentry instance should have an own +# NXspecimen instance and thus the NXem_conventions instance should be place +# inside that NXentry. This enables to group multiple experiments on multiple +# samples together without setting a constraint that in all these instances +# the conventions have to be the same. + +# However, best practice is the conventions should be expressed explicitly +# and they should whenever possible be as simple as possible and as few +# as possible to support users with understanding the content of the application +# definition. +type: group +NXem_conventions(NXobject): + # mandatory information about used or + # assumed reference frame and rotation conventions + rotation_conventions(NXobject): + doc: | + Mathematical conventions and materials-science-specific conventions + required for interpreting every collection of orientation data. + rotation_handedness(NX_CHAR): + doc: | + Convention how a positive rotation angle is defined when viewing + from the end of the rotation unit vector towards its origin, + i.e. in accordance with convention 2 of + DOI: 10.1088/0965-0393/23/8/083501. + Counter_clockwise is equivalent to a right-handed choice. + Clockwise is equivalent to a left-handed choice. + enumeration: [undefined, counter_clockwise, clockwise] + rotation_convention(NX_CHAR): + doc: | + How are rotations interpreted into an orientation + according to convention 3 of + DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, passive, active] + euler_angle_convention(NX_CHAR): + doc: | + How are Euler angles interpreted given that there are several + choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of + DOI: 10.1088/0965-0393/23/8/083501. + The most frequently used convention is ZXZ which is based on + the work of H.-J. Bunge but other conventions are possible. + enumeration: [undefined, zxz] + axis_angle_convention(NX_CHAR): + doc: | + To which angular range is the rotation angle argument of an + axis-angle pair parameterization constrained according to + convention 5 of DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, rotation_angle_on_interval_zero_to_pi] + sign_convention(NX_CHAR): + doc: | + Which sign convention is followed when converting orientations + between different parameterizations/representations according + to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, p_plus_one, p_minus_one] + processing_reference_frame(NXcoordinate_system): + doc: | + Details about eventually relevant named directions that may + give reasons for anisotropies. The classical example is cold-rolling + where one has to specify which directions (rolling, transverse, and normal) + align how with the direction of the base vectors of the sample_reference_frame. + type(NX_CHAR): + doc: | + Type of coordinate system and reference frame according to + convention 1 of DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of coordinate system. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Location of the origin of the processing_reference_frame. + This specifies the location Xp = 0, Yp = 0, Zp = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] + x_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. rolling direction. + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing x-axis base vector of + the processing_reference_frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. + enumeration: [undefined, north, east, south, west, in, out] + y_alias(NX_CHAR): + doc: | + Name or alias assigned to the y-axis base vector, + e.g. transverse direction. + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing y-axis base vector of + the processing_reference_frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_alias(NX_CHAR): + doc: | + Name or alias assigned to the z-axis base vector, + e.g. normal direction. + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing z-axis base vector of + the processing_reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + sample_reference_frame(NXcoordinate_system): + doc: | + Details about the sample/specimen reference frame. + type(NX_CHAR): + doc: | + Type of coordinate system and reference frame according to + convention 1 of DOI: 10.1088/0965-0393/23/8/083501. + The reference frame for the sample surface reference is used for + identifying positions on a (virtual) image which is formed by + information collected from an electron beam scanning the + sample surface. We assume the configuration is inspected by + looking towards the sample surface from a position that is + located behind the detector. + Reference DOI: 10.1016/j.matchar.2016.04.008 + The sample surface reference frame has coordinates Xs, Ys, Zs. + In three dimensions these coordinates are not necessarily + located on the surface of the sample as there are multiple + faces/sides of the sample. Most frequently though the coordinate + system here is used to define the surface which the electron + beam scans. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of the coordinate system if it is a Cartesian. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Location of the origin of the sample surface reference frame. + This specifies the location Xs = 0, Ys = 0, Zs = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] + x_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. longest edge. + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing x-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + enumeration: [undefined, north, east, south, west, in, out] + y_alias(NX_CHAR): + doc: | + Name or alias assigned to the y-axis base vector, + e.g. long edge. + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing y-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_alias(NX_CHAR): + doc: | + Name or alias assigned to the z-axis base vector, + e.g. shortest edge. + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing z-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + detector_reference_frameID(NXcoordinate_system): + doc: | + Details about the detector reference frame for a specific detector. + \@depends_on(NX_CHAR): + doc: | + Reference to the specifically named :ref:`NXdetector` instance + for which these conventions in this :ref:`NXprocess` group apply + (e.g. /entry1/instrument/detector1). + type(NX_CHAR): + doc: | + Type of coordinate system/reference frame used for + identifying positions in detector space Xd, Yd, Zd, + according to DOI: 10.1016/j.matchar.2016.04.008. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of the coordinate system if it is a Cartesian. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Where is the origin of the detector space reference + frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] + x_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. longest edge as some landmark on the detector. + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing x-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + enumeration: [undefined, north, east, south, west, in, out] + y_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. long edge as some landmark on the detector. + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing y-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. short edge as some landmark on the detector. + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing z-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + # conventions specific for EBSD + (NXem_conventions_ebsd): \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml b/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml new file mode 100644 index 000000000..1ec180e23 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml @@ -0,0 +1,125 @@ +category: base +# symbols: +doc: | + Base class for method-specific conventions EBSD. + + This base class is expected to be used with :ref:`NXem_conventions`. + + This is the main issue which currently is not in all cases documented + and thus limits the interoperability and value of collected EBSD data. + Not communicating EBSD data with such contextual pieces of information + and the use of file formats which do not store this information is the + key unsolved problem. +type: group +NXem_conventions_ebsd(NXem_conventions): + gnomonic_projection_reference_frame(NXcoordinate_system): + doc: | + Details about the gnomonic projection reference frame. + type(NX_CHAR): + doc: | + Type of coordinate system/reference frame used for identifying + positions in the gnomonic projection space Xg, Yg, Zg + according to DOI: 10.1016/j.matchar.2016.04.008. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of coordinate system. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Is the origin of the gnomonic coordinate system located + where we assume the location of the pattern centre. + This is the location Xg = 0, Yg = 0, Zg = 0 according to + reference DOI: 10.1016/j.matchar.2016.04.008. + enumeration: [undefined, in_the_pattern_centre] + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing "gnomomic" x-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + enumeration: [undefined, north, east, south, west, in, out] + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing "gnomomic" y-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing "gnomomic" z-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + pattern_centre(NXprocess): + doc: | + Details about the definition of the pattern centre + as a special point in the gnomonic projection reference frame. + x_boundary_convention(NX_CHAR): + doc: | + From which border of the EBSP (in the detector reference frame) + is the pattern centre's x-position (PCx) measured? + Keywords assume the region-of-interest is defined by + a rectangle. We observe this rectangle and inspect the + direction of the outer-unit normals to the edges of + this rectangle. + enumeration: [undefined, top, right, bottom, left] + x_normalization_direction(NX_CHAR): + doc: | + In which direction are positive values for PCx measured from + the specified boundary. Keep in mind that the gnomonic space + is in virtually all cases embedded in the detector space. + Specifically, the XgYg plane is defined such that it is + embedded/laying inside the XdYd plane (of the detector + reference frame). + When the normalization direction is the same as e.g. the + detector x-axis direction, we state that we effectively + normalize in fractions of the width of the detector. + + The issue with terms like width and height is that these + degenerate if the detector region-of-interest is square-shaped. + This is why we should better avoid talking about width and height but + state how we would measure distances practically with a ruler and + how we then measure positive distances. + enumeration: [undefined, north, east, south, west] + y_boundary_convention(NX_CHAR): + doc: | + From which border of the EBSP (in the detector reference + frame) is the pattern centre's y-position (PCy) measured? + For further details inspect the help button of + xaxis_boundary_convention. + enumeration: [undefined, top, right, bottom, left] + y_normalization_direction(NX_CHAR): + doc: | + In which direction are positive values for PCy measured from + the specified boundary. + For further details inspect the help button of + xaxis_normalization_direction. + enumeration: [undefined, north, east, south, west] + + # distance_convention: + # doc: | + # How is the third of the three pattern centre parameter values, + # the (distance) parameter DD, normalized. Which convention + # is followed. We are aware that specifying one of the options here + # also implicitly comes with conventions for some of the parameter + # requested in this ELN. For now we would rather like to ask + # the users though to be specific also to learn how such an ELN + # will be used in practice. + # enumeration: [undefined, Bruker, JEOL, FEI, Oxford] diff --git a/contributed_definitions/nyaml/NXem_eds.yaml b/contributed_definitions/nyaml/NXem_eds.yaml new file mode 100644 index 000000000..9a5a97fcd --- /dev/null +++ b/contributed_definitions/nyaml/NXem_eds.yaml @@ -0,0 +1,80 @@ +category: base +doc: | + Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). + + `IUPAC instead of Siegbahn notation `_ should be used. + +# NEW ISSUE: use computational geometry to offer arbitrary scan pattern +# NEW ISSUE: make the binning flexible per scan point +symbols: + # n_p: Number of scan points + n_y: | + Number of pixel along the y direction, the slow direction + n_x: | + Number of pixel along the x direction, the fast direction + n_photon_energy: | + Number of X-ray photon energy (bins), the fastest direction. + n_elements: | + Number of identified elements + n_peaks: | + Number of peaks detected +type: group +NXem_eds(NXem_method): + # NXprocess is composed from NXem_method base class + # SPECTRUM_SET(NXspectrum_set) is composed from NXem_method base class + # for post-processing of/with the above-defined data entries + # including feedback from Christoph Pauly (from MX Uni Saarland, NFDI-MatWerk), + # Sabine Bergmann and Sebastian Brückner (both from FAIRmat, IKZ), + # and Adrien Teutrie, Cecile Hebert (EPFL) + indexing(NXprocess): + doc: | + Details about computational steps how peaks were indexed as elements. + (NXprogram): + doc: | + The program with which the indexing was performed. + PEAK(NXpeak): + doc: | + Name and location of each X-ray line which was indexed as a known ion. + For each ion, an NXion instance should be created which specifies + the origin of the signal. For each ion also the relevant IUPAC notation + X-ray lines should be specified. + (NXion): + energy_range(NX_NUMBER): + doc: | + Associated lower :math:`[e_{min}, e_{max}]` bounds of the + energy which is assumed associated with this peak. + unit: NX_ENERGY + dim: (2,) + energy(NX_NUMBER): + doc: | + Theoretical energy of the line according to IUPAC. + unit: NX_ENERGY + iupac_line_names(NX_CHAR): + doc: | + IUPAC notation identifier of the line which the peak represents. + + This can be a list of IUPAC notations for (the seldom) case that + multiple lines are grouped with the same peak. + dim: (i,) + element_names(NX_CHAR): + doc: | + List of the names of identified elements. + dim: (n_elements,) + IMAGE_R_SET(NXimage_r_set): + doc: | + Individual element-specific EDS/EDX/EDXS/SXES mapping + + A composition map is an image whose intensities for each pixel are the + accumulated X-ray quanta *under the curve(s)* of a set of peaks. + + These element-specific EDS maps are NXimage_r_set instances + and need to be named with the name of the element from the + element_names field. + (NXprocess): + peaks(NX_CHAR): + doc: | + A list of NXpeak instance names whose X-ray quanta + where accumulated for each pixel which yields an element-specific + EDS map. + dim: (n_peaks,) + # everything else is composed from NXimage_r_set diff --git a/contributed_definitions/nyaml/NXem_method.yaml b/contributed_definitions/nyaml/NXem_method.yaml new file mode 100644 index 000000000..afe91de97 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_method.yaml @@ -0,0 +1,21 @@ +category: base +doc: | + Base class to describe specific analysis methods in electron microscopy. + + This base class represent a template how specialized, deep, and method-specific + base classes can be defined with which an (NXem) application + definition gets equipped with specific groups to document method-specific + processing steps and report analyzed quantities. + + The template base class name :ref:`NXem_method` needs to be changed for each + method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. +# :ref:`NXem_se`, :ref:`NXem_bse`. +type: group +NXem_method(NXobject): + (NXprocess): + doc: | + Details about processing steps. + sequence_index(NX_INT): + IMAGE_R_SET(NXimage_r_set): + IMAGE_C_SET(NXimage_c_set): + SPECTRUM_SET(NXspectrum_set): diff --git a/contributed_definitions/nyaml/NXem_sim.yaml b/contributed_definitions/nyaml/NXem_sim.yaml deleted file mode 100644 index 38492d66e..000000000 --- a/contributed_definitions/nyaml/NXem_sim.yaml +++ /dev/null @@ -1,33 +0,0 @@ -category: base -doc: | - Base class for simulating electron microscopy relevant beam-matter interaction. - - The concept behind this base class is to keep it as generic as possible - that simulations of electron/ion beam interaction with matter can be - represented. This base class is envisioned as the twin of the :ref:`NXem_msr` - base class. - - It is an attempt to test the idea if at some point one might even use the - same base class template to describe measurements and computer simulations - of electron microscopy. This idea is attractive because the only practical - difference between a description of a measurement with a microscope and a - computer simulation is that the latter is typically a substantially simplified - representation of the real microscope surplus the focus of the research - in such cases on specific questions. - - Such simplification can be with respect to the optical setup, typically the - ignoring of the fact that the electron beam is produced by a complex setup - of lenses while in simulations often single Einzel lenses are considered. - Dynamics of the environment like temperature fluctuation in a lab, vibrations, - users, and multiple detectors are typically either ignored or reduced in - complexity and number and coming with idealizations to keep the simulations - focused on the specific reason questions and efficiently numerically executable. -# abTEM and other simulation packages, TEMgym, etc. -type: group -NXem_sim(NXem_method): - simulation(NXprocess): - doc: | - Details about the simulation. - # sequence_index(N): - (NXprogram): - (NXcg_geodesic_mesh): diff --git a/contributed_definitions/nyaml/NXimage_c_set.yaml b/contributed_definitions/nyaml/NXimage_c_set.yaml new file mode 100644 index 000000000..8dcd85706 --- /dev/null +++ b/contributed_definitions/nyaml/NXimage_c_set.yaml @@ -0,0 +1,140 @@ +category: base +doc: | + Specialized base class container for reporting a set of images in reciprocal space. + + In practice, complex numbers are encoded via some formatted pair of real values. + Typically, fast Algorithms for computing Fourier Transformations (FFT) are + used to encode images in reciprocal (frequency) space. FFT libraries are used + for implementing the key functionalities of these mathematical operations. + + Different libraries use different representations and encoding of the + image computed. Details can be found in the respective sections of the + typical FFT libraries: + + * `FFTW by M. Frigo and S. G. Johnson `_ + * `Intel MKL by the Intel Co. `_ + * `cuFFT by the NVidia Co. `_ + + Users are strongly advised to inspect carefully which specific conventions + their library uses to be able to store and modify the implementation of their + code so that the serialized representations as it is detailed + here for NeXus matches with their intention. + + One- and two-dimensional FFTs should use the stack(NXdata) instances. + Three-dimensional FFTs should use the hyperstack(NXdata) instances. +symbols: + n_images: | + Number of images in the (hyper)stack. + n_k: | + Number of pixel per image in the slowest direction. + n_j: | + Number of pixel per image in the slow direction. + n_i: | + Number of pixel per image in the fast direction. +type: group +NXimage_c_set(NXimage_set): + # details about the FFT library used could for instance be stored in the + # NXprocess group which the NXimage_c_set base class can borrow from its + # NXimage_set parent base class + # process information are composable from the NXimage_set base class + stack(NXdata): + doc: | + Image stack. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_images, n_j, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_images, n_j, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_images, n_j, n_i) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + # axis_k(NX_NUMBER): + # doc: | + # Pixel coordinate center along k direction. + # unit: NX_ANY # NX_RECIPROCAL_LENGTH + # dim: (n_k,) + # \@long_name(NX_CHAR): + # doc: | + # Coordinate along j direction. + axis_j(NX_NUMBER): + doc: | + Pixel coordinate center along j direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_j,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. + + hyperstack(NXdata): + doc: | + Image hyperstack. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_images, n_k, n_j, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_images, n_k, n_j, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_images, n_k, n_j, n_i) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_k(NX_NUMBER): + doc: | + Pixel coordinate center along k direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_k,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_j(NX_NUMBER): + doc: | + Pixel coordinate center along j direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_j,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set.yaml b/contributed_definitions/nyaml/NXimage_r_set.yaml new file mode 100644 index 000000000..f0437e6e6 --- /dev/null +++ b/contributed_definitions/nyaml/NXimage_r_set.yaml @@ -0,0 +1,45 @@ +category: base +doc: | + Specialized base class container for reporting a set of images in real space. +symbols: + n_images: | + Number of images in the stack. + n_y: | + Number of pixel per image in the slow direction. + n_x: | + Number of pixel per image in the fast direction. +type: group +NXimage_r_set(NXimage_set): + # process information are composable from the NXimage_set base class + stack(NXdata): + doc: | + Image (stack). + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_images, n_y, n_x) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_y(NX_NUMBER): + doc: | + Pixel coordinate center along y direction. + unit: NX_LENGTH + dim: (n_y,) + \@long_name(NX_CHAR): + doc: | + Coordinate along y direction. + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml new file mode 100644 index 000000000..79ca31b16 --- /dev/null +++ b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml @@ -0,0 +1,123 @@ +category: base +doc: | + Base class specialized for reporting a cuboidal stack of diffraction pattern. + + Diffraction pattern, whether they were simulated or measured are the raw data + for computational workflows to characterize the phase and orientation + of crystalline regions in matter. + + Steps of post-processing the diffraction patterns should be documented using + method-specific specialized base classes. All eventual post-processing of + resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. + + To implement an example how this base class can be used we focused in FAIRmat + on Kikuchi diffraction pattern here specifically the research community + of Electron Backscatter Diffraction (EBSD). + + For this reason, this base class and related :ref:`NXem_base` classes extend the + work of `M. A. Jackson et al. `_ + (one of the developers of DREAM.3D) and the H5OINA public file format developed by + `P. Pinard et al. `_ with Oxford Instruments. + + Kikuchi pattern are typically collected with FIB/SEM microscopes, + for two- and three-dimensional orientation microscopy. + + For a detailed overview of these techniques see e.g. + + * `M. A. Groeber et al. `_ + * `A. J. Schwartz et al. `_ + * `P. A. Rottman et al. `_ + + Serial-sectioning demands a recurrent sequence of ion milling and measuring. + This suggests that each serial section is at least an own NXevent_data_em + instance. The three-dimensional characterization as such demands a computational + step where the maps for each serial section get cleaned, aligned, and registered + into an image stack. This image stack represents a digital model of the + inspected microstructural volume. Often this volume is called a (representative) + volume element (RVE). Several software packages exists for performing + these post-processing tasks. + + This example may inspire users of other types of diffraction methods. +symbols: + n_sc: | + Number of scanned points. Scan point may have none, one, or more pattern. + n_p: | + Number of diffraction pattern. + n_y: | + Number of pixel per pattern in the slow direction. + n_x: | + Number of pixel per pattern in the fast direction. +type: group +NXimage_r_set_diff(NXimage_r_set): + pattern_type(NX_CHAR): + doc: | + Category which type of diffraction pattern is reported. + enumeration: [kikuchi] + stack(NXdata): + doc: | + Collected diffraction pattern as an image stack. As raw and closest to the + first retrievable measured data as possible, i.e. do not use this + container to store already averaged, filtered or whatever post-processed + pattern unless these are generated unmodifiably in such manner by the + instrument given the way how the instrument and control software + was configured for your microscope session. + scan_point_identifier(NX_INT): + doc: | + Array which resolves the scan point to which each pattern belongs. + + Scan points are evaluated in sequence starting from scan point zero + until scan point n_sc - 1. Evaluating the cumulated of this array + decodes which pattern in intensity belongs to which scan point. + + Take an example with three scan points: The first scan point has one + pattern, the second has three pattern, the last scan point has no + pattern. In this case the scan_point_identifier are 0, 1, 1, 1. + The length of the scan_point_identifier array is four because four + pattern were measured in total. + + In most cases usually one pattern is averaged by the detector for + some amount of time and then reported as one pattern. + unit: NX_UNITLESS + dim: (n_p,) + intensity(NX_NUMBER): + doc: | + Intensity of the diffraction pattern. + unit: NX_UNITLESS + dim: (n_p, n_y, n_x) + # n_p fast 2, n_y faster 1, n_x fastest 0 + # in axes fast to fastest + # while for _indices fastest to fast + \@long_name(NX_CHAR): + doc: | + Pattern intensity + # \@signal: intensity + # \@axes: [pattern_identifier, ypos, xpos] + # \@xpos_indices: 0 + # \@ypos_indices: 1 + # \@pattern_identifier_indices: 2 + pattern_identifier(NX_INT): + doc: | + Pattern are enumerated starting from 0 to n_p - 1. + unit: NX_UNITLESS + dim: (n_p,) + \@long_name(NX_CHAR): + doc: | + Pattern identifier + # the following fields are taken from the NXimage_r_set base class + # axis_y(R): + # axis_x(R): + +# If we envision a (knowledge) graph for EBSD it consists of individual sub-graphs +# which convey information about the specimen preparation, the measurement of +# the specimen in the electron microscope, the indexing of the collected +# Kikuchi pattern stack, eventual post-processing of the indexed orientation +# images via similarity grouping algorithms to yield (grains, texture). +# Conceptually, these post-processing steps are most frequently serving +# the idea how can one reconstruct so-called microstructural features +# (grains, phases, interfaces) to infer material properties. +# In practice this calls for workflows which quantify correlations between +# the spatial arrangement of the microstructural features, the individual +# (thermodynamic, chemo-mechanical) properties of the features with the +# properties of materials at a coarser scale. +# With NXem and related NXms base classes we propose a covering +# and general solution how to handle such (meta)data with NeXus. From 16d9640fee8351932ad651dd7bac4486e1153a57 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 13 Dec 2023 16:38:08 +0100 Subject: [PATCH 084/136] Refactoring storage of images and spectra # Conflicts: # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXimage_set.nxdl.xml # contributed_definitions/NXspectrum_set.nxdl.xml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXimage_set.yaml # contributed_definitions/nyaml/NXspectrum_set.yaml # dev_tools/tests/test_nxdl_utils.py --- contributed_definitions/NXem_adf.nxdl.xml | 2 +- contributed_definitions/NXem_eds.nxdl.xml | 81 ++++-- contributed_definitions/NXem_eels.nxdl.xml | 13 +- .../NXimage_c_set.nxdl.xml | 250 +++++++++++++++++- .../NXimage_r_set.nxdl.xml | 237 ++++++++++++++++- contributed_definitions/nyaml/NXem_adf.yaml | 2 +- contributed_definitions/nyaml/NXem_eds.yaml | 62 ++++- contributed_definitions/nyaml/NXem_eels.yaml | 19 +- .../nyaml/NXimage_c_set.yaml | 168 ++++++++++-- .../nyaml/NXimage_r_set.yaml | 147 +++++++++- 10 files changed, 901 insertions(+), 80 deletions(-) diff --git a/contributed_definitions/NXem_adf.nxdl.xml b/contributed_definitions/NXem_adf.nxdl.xml index 64534699c..92e784ee3 100644 --- a/contributed_definitions/NXem_adf.nxdl.xml +++ b/contributed_definitions/NXem_adf.nxdl.xml @@ -50,7 +50,7 @@ For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. - + Annulus inner (first value) and outer (second value) half angle. diff --git a/contributed_definitions/NXem_eds.nxdl.xml b/contributed_definitions/NXem_eds.nxdl.xml index 735bfe897..8550cbe81 100644 --- a/contributed_definitions/NXem_eds.nxdl.xml +++ b/contributed_definitions/NXem_eds.nxdl.xml @@ -25,17 +25,10 @@ - - - - Number of pixel along the y direction, the slow direction - - - - - Number of pixel along the x direction, the fast direction - - + Number of X-ray photon energy (bins), the fastest direction. @@ -53,12 +46,19 @@ NEW ISSUE: make the binning flexible per scan point--> - Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). + Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDXS). `IUPAC instead of Siegbahn notation <https://doi.org/10.1002/xrs.1300200308>`_ should be used. + + X-ray spectroscopy is a surface-sensitive technique. Therefore, three-dimensional elemental + characterzation requires typically a sequence of characterization and preparation of the + surface to expose a new surface layer that can be characterized in the next acquisition. + In effect, the resulting three-dimensional elemental information mappings are truely the + result of a correlation and post-processing of several measurements which is the field + of correlative tomographic usage of electron microscopy. - The program with which the indexing was performed. + + + Accumulated intensity over all pixels of the region-of-interest. + + + + Accumulated counts + + + + + + + Counts + + + + + + Energy axis + + + + + + + Energy + + + + Name and location of each X-ray line which was indexed as a known ion. @@ -109,13 +140,18 @@ and Adrien Teutrie, Cecile Hebert (EPFL)--> - List of the names of identified elements. + Comma-separated list of names of identified elements. All members of + the list have to be valid chemical_symbols from the periodic table. + + This field can be used when creating instances of NXpeak is not desired. + However, a collection of instances of NXpeak with individual NXion specified + enables also to distinguish isotopic information. - + Individual element-specific EDS/EDX/EDXS/SXES mapping @@ -125,6 +161,12 @@ and Adrien Teutrie, Cecile Hebert (EPFL)--> These element-specific EDS maps are NXimage_r_set instances and need to be named with the name of the element from the element_names field. + + We often observe that signal contributions from several peaks + are summarized and shown together, e.g. the combined signal + under the curve of carbon and oxygen. + + In this case specify the processing details using peaks and weights. @@ -137,6 +179,13 @@ and Adrien Teutrie, Cecile Hebert (EPFL)--> + + + A list of weights by how much the intensity of each peak + under peaks was factorized to display the joint intensity + of the image. + + diff --git a/contributed_definitions/NXem_eels.nxdl.xml b/contributed_definitions/NXem_eels.nxdl.xml index c355f6fd6..0b8b756bf 100644 --- a/contributed_definitions/NXem_eels.nxdl.xml +++ b/contributed_definitions/NXem_eels.nxdl.xml @@ -32,19 +32,14 @@ Base class method-specific for Electron Energy Loss Spectroscopy (EELS). - - + NXspectrum_set_em specialized for EELS. - - + + diff --git a/contributed_definitions/NXimage_c_set.nxdl.xml b/contributed_definitions/NXimage_c_set.nxdl.xml index 64c945c99..ea711bbb8 100644 --- a/contributed_definitions/NXimage_c_set.nxdl.xml +++ b/contributed_definitions/NXimage_c_set.nxdl.xml @@ -72,9 +72,241 @@ NXprocess group which the NXimage_c_set base class can borrow from its NXimage_set parent base class process information are composable from the NXimage_set base class--> - + - Image stack. + One-dimensional image. + + + + Image intensity of the real part. + + + + + + + + Image intensity of the imaginary part. + + + + + + + + Magnitude of the image intensity. + + + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + + + Two-dimensional image. + + + + Image intensity of the real part. + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + Pixel coordinate center along j direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + + + Three-dimensional image. + + + + Image intensity of the real part. + + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + + Pixel coordinate center along k direction. + + + + + + + Coordinate along k direction. + + + + + + Pixel coordinate center along j direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + + + Collection of one-dimensional images. + + + + Image intensity of the real part. + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + + + Collection of two-dimensional images. @@ -119,14 +351,6 @@ process information are composable from the NXimage_set base class--> - Pixel coordinate center along j direction. @@ -154,9 +378,9 @@ process information are composable from the NXimage_set base class--> - + - Image hyperstack. + Collection of three-dimensional images. @@ -213,7 +437,7 @@ process information are composable from the NXimage_set base class--> - Coordinate along j direction. + Coordinate along k direction. diff --git a/contributed_definitions/NXimage_r_set.nxdl.xml b/contributed_definitions/NXimage_r_set.nxdl.xml index 3ef371809..b57afc774 100644 --- a/contributed_definitions/NXimage_r_set.nxdl.xml +++ b/contributed_definitions/NXimage_r_set.nxdl.xml @@ -28,6 +28,11 @@ Number of images in the stack. + + + Number of pixel per image in the slowest direction. + + Number of pixel per image in the slow direction. @@ -43,9 +48,169 @@ Specialized base class container for reporting a set of images in real space. - + + + One-dimensional image. + + + + Image intensity values. + + + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + + + + Two-dimensional image. + + + + Image intensity values. + + + + + + + + + Pixel coordinate center along y direction. + + + + + + + Coordinate along y direction. + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + + + + Three-dimensional image. + + + + Image intensity values. + + + + + + + + + + Pixel coordinate center along z direction. + + + + + + + Coordinate along z direction. + + + + + + Pixel coordinate center along y direction. + + + + + + + Coordinate along y direction. + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + + - Image (stack). + Collection of one-dimensional images. + + + + Image intensity values. + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + + + + Collection of two-dimensional images. @@ -97,4 +262,72 @@ + + + Collection of three-dimensional images. + + + + Image intensity values. + + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along z direction. + + + + + + + Coordinate along z direction. + + + + + + Pixel coordinate center along y direction. + + + + + + + Coordinate along y direction. + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + diff --git a/contributed_definitions/nyaml/NXem_adf.yaml b/contributed_definitions/nyaml/NXem_adf.yaml index b7011639e..02a21e52c 100644 --- a/contributed_definitions/nyaml/NXem_adf.yaml +++ b/contributed_definitions/nyaml/NXem_adf.yaml @@ -18,7 +18,7 @@ symbols: Number of pixel per image in the fast direction. type: group NXem_adf(NXem_method): - IMAGE_R_SET(NXimage_r_set): + (NXimage_r_set): half_angle_interval(NX_NUMBER): doc: | Annulus inner (first value) and outer (second value) half angle. diff --git a/contributed_definitions/nyaml/NXem_eds.yaml b/contributed_definitions/nyaml/NXem_eds.yaml index 9a5a97fcd..06148a018 100644 --- a/contributed_definitions/nyaml/NXem_eds.yaml +++ b/contributed_definitions/nyaml/NXem_eds.yaml @@ -1,17 +1,22 @@ category: base doc: | - Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). + Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDXS). `IUPAC instead of Siegbahn notation `_ should be used. - + + X-ray spectroscopy is a surface-sensitive technique. Therefore, three-dimensional elemental + characterzation requires typically a sequence of characterization and preparation of the + surface to expose a new surface layer that can be characterized in the next acquisition. + In effect, the resulting three-dimensional elemental information mappings are truely the + result of a correlation and post-processing of several measurements which is the field + of correlative tomographic usage of electron microscopy. # NEW ISSUE: use computational geometry to offer arbitrary scan pattern # NEW ISSUE: make the binning flexible per scan point symbols: # n_p: Number of scan points - n_y: | - Number of pixel along the y direction, the slow direction - n_x: | - Number of pixel along the x direction, the fast direction + # n_z: Number of pixel along the z direction, the slowest direction + # n_y: Number of pixel along the y direction, the slow direction + # n_x: Number of pixel along the x direction, the fast direction n_photon_energy: | Number of X-ray photon energy (bins), the fastest direction. n_elements: | @@ -20,8 +25,8 @@ symbols: Number of peaks detected type: group NXem_eds(NXem_method): - # NXprocess is composed from NXem_method base class - # SPECTRUM_SET(NXspectrum_set) is composed from NXem_method base class + # NXprocess is composed from NXem_method base class instances where the spectra + # are stored as instances of (NXspectrum_set) is composed from NXem_method base class # for post-processing of/with the above-defined data entries # including feedback from Christoph Pauly (from MX Uni Saarland, NFDI-MatWerk), # Sabine Bergmann and Sebastian Brückner (both from FAIRmat, IKZ), @@ -32,6 +37,25 @@ NXem_eds(NXem_method): (NXprogram): doc: | The program with which the indexing was performed. + summary(NXdata): + doc: | + Accumulated intensity over all pixels of the region-of-interest. + intensity(NX_NUMBER): + doc: | + Accumulated counts + unit: NX_UNITLESS + dim: (n_photon_energy,) + \@long_name(NX_CHAR): + doc: | + Counts + axis_energy(NX_NUMBER): + doc: | + Energy axis + unit: NX_ENERGY + dim: (n_photon_energy,) + \@long_name(NX_CHAR): + doc: | + Energy PEAK(NXpeak): doc: | Name and location of each X-ray line which was indexed as a known ion. @@ -58,9 +82,14 @@ NXem_eds(NXem_method): dim: (i,) element_names(NX_CHAR): doc: | - List of the names of identified elements. + Comma-separated list of names of identified elements. All members of + the list have to be valid chemical_symbols from the periodic table. + + This field can be used when creating instances of NXpeak is not desired. + However, a collection of instances of NXpeak with individual NXion specified + enables also to distinguish isotopic information. dim: (n_elements,) - IMAGE_R_SET(NXimage_r_set): + (NXimage_r_set): doc: | Individual element-specific EDS/EDX/EDXS/SXES mapping @@ -70,6 +99,13 @@ NXem_eds(NXem_method): These element-specific EDS maps are NXimage_r_set instances and need to be named with the name of the element from the element_names field. + + We often observe that signal contributions from several peaks + are summarized and shown together, e.g. the combined signal + under the curve of carbon and oxygen. + + In this case specify the processing details using peaks and weights. + (NXprocess): peaks(NX_CHAR): doc: | @@ -77,4 +113,10 @@ NXem_eds(NXem_method): where accumulated for each pixel which yields an element-specific EDS map. dim: (n_peaks,) + weights(NX_NUMBER): + doc: | + A list of weights by how much the intensity of each peak + under peaks was factorized to display the joint intensity + of the image. + unit: NX_UNITLESS # everything else is composed from NXimage_r_set diff --git a/contributed_definitions/nyaml/NXem_eels.yaml b/contributed_definitions/nyaml/NXem_eels.yaml index 4e5c69fe4..89b9109bc 100644 --- a/contributed_definitions/nyaml/NXem_eels.yaml +++ b/contributed_definitions/nyaml/NXem_eels.yaml @@ -6,24 +6,27 @@ symbols: Number of electron energy loss bins. type: group NXem_eels(NXem_method): - # NXem_method can offers to keep a SPECTRUM_SET # NXem_method also has an NXprocess which in this base class can be # specialized to include EELS-specific post-processing - SPECTRUM_SET(NXspectrum_set): + (NXspectrum_set): doc: | NXspectrum_set_em specialized for EELS. - stack(NXdata): - # \@signal: data_counts - # \@axes: [axis_y, axis_x, axis_energy_loss] - # \@energy_loss_indices: 2 - # \@axis_x_indices: 1 - # \@axis_y_indices: 0 + # \@signal:, \@axes: \@energy_loss_indices \@axis_x_indices: + stack_oned(NXdata): + axis_energy_loss(NX_NUMBER): + unit: NX_ENERGY + dim: (n_energy_loss,) + \@long_name(NX_CHAR): + doc: | + Energy loss. + stack_oned(NXdata): axis_energy_loss(NX_NUMBER): unit: NX_ENERGY dim: (n_energy_loss,) \@long_name(NX_CHAR): doc: | Energy loss. + summary(NXdata): # \@signal: data_counts # \@axes: [axis_energy_loss] diff --git a/contributed_definitions/nyaml/NXimage_c_set.yaml b/contributed_definitions/nyaml/NXimage_c_set.yaml index 8dcd85706..303017ab1 100644 --- a/contributed_definitions/nyaml/NXimage_c_set.yaml +++ b/contributed_definitions/nyaml/NXimage_c_set.yaml @@ -37,9 +37,149 @@ NXimage_c_set(NXimage_set): # NXprocess group which the NXimage_c_set base class can borrow from its # NXimage_set parent base class # process information are composable from the NXimage_set base class - stack(NXdata): + image_oned(NXdata): doc: | - Image stack. + One-dimensional image. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_i,) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_i,) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_i) + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. + + image_twod(NXdata): + doc: | + Two-dimensional image. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_j, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_j, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_j, n_i) + axis_j(NX_NUMBER): + doc: | + Pixel coordinate center along j direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_j,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. + + image_threed(NXdata): + doc: | + Three-dimensional image. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_k, n_j, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_k, n_j, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_k, n_j, n_i) + axis_k(NX_NUMBER): + doc: | + Pixel coordinate center along k direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_k,) + \@long_name(NX_CHAR): + doc: | + Coordinate along k direction. + axis_j(NX_NUMBER): + doc: | + Pixel coordinate center along j direction. + unit: NX_ANY + dim: (n_j,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. + + stack_oned(NXdata): + doc: | + Collection of one-dimensional images. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_images, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_images, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_images, n_i) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. + + stack_twod(NXdata): + doc: | + Collection of two-dimensional images. real(NX_NUMBER): doc: | Image intensity of the real part. @@ -63,18 +203,10 @@ NXimage_c_set(NXimage_set): \@long_name(NX_CHAR): doc: | Image identifier. - # axis_k(NX_NUMBER): - # doc: | - # Pixel coordinate center along k direction. - # unit: NX_ANY # NX_RECIPROCAL_LENGTH - # dim: (n_k,) - # \@long_name(NX_CHAR): - # doc: | - # Coordinate along j direction. axis_j(NX_NUMBER): doc: | Pixel coordinate center along j direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH + unit: NX_ANY dim: (n_j,) \@long_name(NX_CHAR): doc: | @@ -82,15 +214,15 @@ NXimage_c_set(NXimage_set): axis_i(NX_NUMBER): doc: | Pixel coordinate center along i direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH + unit: NX_ANY dim: (n_i,) \@long_name(NX_CHAR): doc: | Coordinate along i direction. - hyperstack(NXdata): + stack_threed(NXdata): doc: | - Image hyperstack. + Collection of three-dimensional images. real(NX_NUMBER): doc: | Image intensity of the real part. @@ -117,15 +249,15 @@ NXimage_c_set(NXimage_set): axis_k(NX_NUMBER): doc: | Pixel coordinate center along k direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH + unit: NX_ANY dim: (n_k,) \@long_name(NX_CHAR): doc: | - Coordinate along j direction. + Coordinate along k direction. axis_j(NX_NUMBER): doc: | Pixel coordinate center along j direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH + unit: NX_ANY dim: (n_j,) \@long_name(NX_CHAR): doc: | @@ -133,7 +265,7 @@ NXimage_c_set(NXimage_set): axis_i(NX_NUMBER): doc: | Pixel coordinate center along i direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH + unit: NX_ANY dim: (n_i,) \@long_name(NX_CHAR): doc: | diff --git a/contributed_definitions/nyaml/NXimage_r_set.yaml b/contributed_definitions/nyaml/NXimage_r_set.yaml index f0437e6e6..5c63988c6 100644 --- a/contributed_definitions/nyaml/NXimage_r_set.yaml +++ b/contributed_definitions/nyaml/NXimage_r_set.yaml @@ -4,6 +4,8 @@ doc: | symbols: n_images: | Number of images in the stack. + n_z: | + Number of pixel per image in the slowest direction. n_y: | Number of pixel per image in the slow direction. n_x: | @@ -11,9 +13,109 @@ symbols: type: group NXimage_r_set(NXimage_set): # process information are composable from the NXimage_set base class - stack(NXdata): + image_oned(NXdata): doc: | - Image (stack). + One-dimensional image. + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_x,) + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. + + image_twod(NXdata): + doc: | + Two-dimensional image. + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_y, n_x) + axis_y(NX_NUMBER): + doc: | + Pixel coordinate center along y direction. + unit: NX_LENGTH + dim: (n_y,) + \@long_name(NX_CHAR): + doc: | + Coordinate along y direction. + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. + + image_threed(NXdata): + doc: | + Three-dimensional image. + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_z, n_y, n_x) + axis_z(NX_NUMBER): + doc: | + Pixel coordinate center along z direction. + unit: NX_LENGTH + dim: (n_z,) + \@long_name(NX_CHAR): + doc: | + Coordinate along z direction. + axis_y(NX_NUMBER): + doc: | + Pixel coordinate center along y direction. + unit: NX_LENGTH + dim: (n_y,) + \@long_name(NX_CHAR): + doc: | + Coordinate along y direction. + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. + + stack_oned(NXdata): + doc: | + Collection of one-dimensional images. + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_images, n_x) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. + + stack_twod(NXdata): + doc: | + Collection of two-dimensional images. intensity(NX_NUMBER): doc: | Image intensity values. @@ -43,3 +145,44 @@ NXimage_r_set(NXimage_set): \@long_name(NX_CHAR): doc: | Coordinate along x direction. + + stack_threed(NXdata): + doc: | + Collection of three-dimensional images. + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_images, n_z, n_y, n_x) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_z(NX_NUMBER): + doc: | + Pixel coordinate center along z direction. + unit: NX_LENGTH + dim: (n_z,) + \@long_name(NX_CHAR): + doc: | + Coordinate along z direction. + axis_y(NX_NUMBER): + doc: | + Pixel coordinate center along y direction. + unit: NX_LENGTH + dim: (n_y,) + \@long_name(NX_CHAR): + doc: | + Coordinate along y direction. + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. From d1523eca40bb83b92c6d38977851afd0a4a8271d Mon Sep 17 00:00:00 2001 From: domna Date: Wed, 3 Jan 2024 16:07:41 +0100 Subject: [PATCH 085/136] Multiline docstrings for enumerations are now supported --- dev_tools/docs/nxdl.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/dev_tools/docs/nxdl.py b/dev_tools/docs/nxdl.py index 8c9d548be..eee7edfcc 100644 --- a/dev_tools/docs/nxdl.py +++ b/dev_tools/docs/nxdl.py @@ -310,12 +310,36 @@ def _get_doc_blocks(ns, node): out_blocks.append("\n".join(out_lines)) return out_blocks + def _handle_multiline_docstring(self, blocks): + links = [] + docstring = "" + expanded_blocks = [] + for block in blocks: + expanded_blocks += block.split('\n') + + for block in expanded_blocks: + if not block: + continue + + link_match = re.search(r"\.\. _([^:]+):(.*)", block) + if link_match is not None: + links.append((link_match.group(1), link_match.group(2).strip())) + else: + docstring += " " + re.sub(r"\n", " ", block.strip()) + + for (name, target) in links: + docstring = docstring.replace( + f"`{name}`_", f"`{name} <{target}>`_" + ) + + return docstring + def _get_doc_line(self, ns, node): blocks = self._get_doc_blocks(ns, node) if len(blocks) == 0: return "" if len(blocks) > 1: - raise Exception(f"Unexpected multi-paragraph doc [{'|'.join(blocks)}]") + return self._handle_multiline_docstring(blocks) return re.sub(r"\n", " ", blocks[0]) def _get_minOccurs(self, node): From 17b9c63a0506e9dcd23ad2a3149136ee2d3a0ed4 Mon Sep 17 00:00:00 2001 From: domna Date: Wed, 3 Jan 2024 16:36:10 +0100 Subject: [PATCH 086/136] Black reformatted --- dev_tools/docs/nxdl.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dev_tools/docs/nxdl.py b/dev_tools/docs/nxdl.py index eee7edfcc..31015016a 100644 --- a/dev_tools/docs/nxdl.py +++ b/dev_tools/docs/nxdl.py @@ -315,7 +315,7 @@ def _handle_multiline_docstring(self, blocks): docstring = "" expanded_blocks = [] for block in blocks: - expanded_blocks += block.split('\n') + expanded_blocks += block.split("\n") for block in expanded_blocks: if not block: @@ -327,10 +327,8 @@ def _handle_multiline_docstring(self, blocks): else: docstring += " " + re.sub(r"\n", " ", block.strip()) - for (name, target) in links: - docstring = docstring.replace( - f"`{name}`_", f"`{name} <{target}>`_" - ) + for name, target in links: + docstring = docstring.replace(f"`{name}`_", f"`{name} <{target}>`_") return docstring From a6947ca2eca906802ed1c812ffea2700cffe955c Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Tue, 30 Jan 2024 11:23:58 +0100 Subject: [PATCH 087/136] Fix URLs and formats with black>24 (#152) * Updates URLs * Update ci/cd to deploy on tags * Updates url and reverst ci/cd changes * Reformat according to black>24 * Update black version in requirements # Conflicts: # dev_tools/tests/test_nxdl_utils.py # manual/source/conf.py --- dev_tools/globals/urls.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev_tools/globals/urls.py b/dev_tools/globals/urls.py index 729b7d102..2929070cc 100644 --- a/dev_tools/globals/urls.py +++ b/dev_tools/globals/urls.py @@ -1,2 +1,2 @@ -REPO_URL = "https://github.com/nexusformat/definitions/blob/main" +REPO_URL = "https://github.com/FAIRmat-NFDI/nexus_definitions/tree/fairmat" MANUAL_URL = "https://manual.nexusformat.org" diff --git a/requirements.txt b/requirements.txt index ba1f751d3..74c736824 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,6 @@ sphinx-toolbox pytest # Code style and auto-formatting -black>=22.3 +black>=24.1.1 flake8>=4 isort>=5.10 From 7d9de8405a708d77063b62369e352335347a700a Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Mon, 25 Mar 2024 19:10:17 +0100 Subject: [PATCH 088/136] support UPPER anywhere; fix get_hdf_info_parent and get_xml_root --- dev_tools/utils/nxdl_utils.py | 69 ++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index ebb7ce62a..885cfe397 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -3,6 +3,7 @@ """ import os +import re import textwrap from functools import lru_cache from glob import glob @@ -58,7 +59,7 @@ def get_app_defs_names(): def get_xml_root(file_path): """Reducing I/O time by caching technique""" - return ET.parse(file_path).getroot() + return ET.parse(str(file_path)).getroot() def get_hdf_root(hdf_node): @@ -92,7 +93,13 @@ def get_hdf_info_parent(hdf_info): """Get the hdf_info for the parent of an hdf_node in an hdf_info""" if "hdf_path" not in hdf_info: return {"hdf_node": hdf_info["hdf_node"].parent} - node = get_hdf_parent(hdf_info) + node = ( + get_hdf_root(hdf_info["hdf_node"]) + if "hdf_root" not in hdf_info + else hdf_info["hdf_root"] + ) + for child_name in hdf_info["hdf_path"].split("/")[1:-1]: + node = node[child_name] return {"hdf_node": node, "hdf_path": get_parent_path(hdf_info["hdf_path"])} @@ -104,32 +111,41 @@ def get_nx_class(nxdl_elem): def get_nx_namefit(hdf_name, name, name_any=False): - """Checks if an HDF5 node name corresponds to a child of the NXDL element - uppercase letters in front can be replaced by arbitrary name, but - uppercase to lowercase match is preferred, - so such match is counted as a measure of the fit""" + """ + Checks if an HDF5 node name corresponds to a child of the NXDL element. + A group of uppercase letters anywhere can be replaced by an arbitrary name. + + Args: + hdf_name (str): The hdf_name, containing uppercase parts. + name (str): The string to match against hdf_name. + name_any (bool, optional): + Accept any name and just return the matching characters. + Defaults to False. + + Returns: + int: + -1 if no match is found or the number of matching + characters (case insensitive) between for all uppercase groups. + """ if name == hdf_name: return len(name) * 2 - # count leading capitals - counting = 0 - while counting < len(name) and name[counting].isupper(): - counting += 1 - if ( - name_any - or counting == len(name) - or (counting > 0 and hdf_name.endswith(name[counting:])) - ): # if potential fit - # count the matching chars - fit = 0 - for i in range(min(counting, len(hdf_name))): - if hdf_name[i].upper() == name[i]: + + uppercase_parts = re.findall("[A-Z]+(?:_[A-Z]+)*", name) + + for up in uppercase_parts: + name = name.replace(up, r"([a-zA-Z0-9_]+)") + + name_match = re.search(rf"^{name}$", hdf_name) + if name_match is None: + return 0 if name_any else -1 + + fit = 0 + for up, low in zip(uppercase_parts, name_match.groups()): + for i in range(min(len(up), len(low))): + if up[i].lower() == low[i]: fit += 1 - else: - break - if fit == min(counting, len(hdf_name)): # accept only full fits as better fits - return fit - return 0 - return -1 # no fit + + return fit def get_nx_classes(): @@ -821,6 +837,9 @@ def get_node_at_nxdl_path( we are looking for or the root elem from a previously loaded NXDL file and finds the corresponding XML element with the needed attributes.""" try: + if nxdl_path.count("/") == 1 and not nxdl_path.upper().startswith("/ENTRY"): + elem = None + nx_name = "NXroot" (class_path, nxdlpath, elist) = get_inherited_nodes(nxdl_path, nx_name, elem) except ValueError as value_error: if exc: From c10f84c40050b03fe8c128e3b3ff09efbd98ea61 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Mon, 25 Mar 2024 20:05:55 +0100 Subject: [PATCH 089/136] revert unnecessary change in get_xml_root --- dev_tools/utils/nxdl_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 885cfe397..a966b52a7 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -59,7 +59,7 @@ def get_app_defs_names(): def get_xml_root(file_path): """Reducing I/O time by caching technique""" - return ET.parse(str(file_path)).getroot() + return ET.parse(file_path).getroot() def get_hdf_root(hdf_node): From c59ffa3138a411e8eb8a4f8b69cefb14bed3272e Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Wed, 17 Apr 2024 08:31:37 +0200 Subject: [PATCH 090/136] Fixes glob retrieval in get_app_defs_names (#215) --- dev_tools/utils/nxdl_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index a966b52a7..783bac2d1 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -46,8 +46,8 @@ def get_app_defs_names(): Path(nexus_def_path) / "contributed_definitions" / "*.nxdl.xml" ) - files = sorted(glob(app_def_path_glob)) - for nexus_file in sorted(contrib_def_path_glob): + files = sorted(glob(str(app_def_path_glob))) + for nexus_file in sorted(glob(str(contrib_def_path_glob))): root = get_xml_root(nexus_file) if root.attrib["category"] == "application": files.append(nexus_file) From 941d1d8e863e80e3dc3a56ebcc99167294201a9a Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Thu, 18 Apr 2024 09:45:38 +0200 Subject: [PATCH 091/136] Improve nexus namefitting + add tests (#213) * Allow whitespace in namefitting * Adds tests for namefitting * Adds test for namefitting precedence * Add additional test for namefitting precedence * Black reformatting * Use sequence matcher * isort * Remove similiarity match function * Fix namefit function * Use NIAC regex * Fix number in the beginning in namefitting * Format with black * Update namefitting with new algorithm * Improve regex # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 64 ++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 783bac2d1..ce32ad3ac 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -1,6 +1,5 @@ # pylint: disable=too-many-lines -"""Parse NeXus definition files -""" +"""Parse NeXus definition files""" import os import re @@ -110,42 +109,69 @@ def get_nx_class(nxdl_elem): return nxdl_elem.attrib.get("type", "NX_CHAR") -def get_nx_namefit(hdf_name, name, name_any=False): +def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False) -> int: """ Checks if an HDF5 node name corresponds to a child of the NXDL element. - A group of uppercase letters anywhere can be replaced by an arbitrary name. + A group of uppercase letters anywhere in the name is treated as freely choosable + part of this name. + If a match is found this function returns twice the length for an exact match, + otherwise the number of matching characters (case insensitive) or zero, if + `name_any` is set to True, is returned. + All uppercase groups are considered independently. + Lowercase matches are independent of uppercase group lengths, e.g., + an hdf_name `get_nx_namefit("my_fancy_yet_long_name", "my_SOME_name")` would + return a score of 8 for the lowercase matches `my_..._name`. + All characters in `[a-zA-Z0-9_.]` are considered for matching to an uppercase letter. + If you use any other letter in the name, it will not match and return -1. + Periods at the beginning or end of the hdf_name are not allowed, only exact + matches will be considered. + + Examples: + + * `get_nx_namefit("test_name", "TEST_name")` returns 9 + * `get_nx_namefit("te_name", "TEST_name")` returns 7 + * `get_nx_namefit("my_other_name", "TEST_name")` returns 5 + * `get_nx_namefit("test_name", "test_name")` returns 18 + * `get_nx_namefit("test_other", "test_name")` returns -1 Args: - hdf_name (str): The hdf_name, containing uppercase parts. - name (str): The string to match against hdf_name. + hdf_name (str): The hdf_name, containing the name of the HDF5 node. + name (str): The concept name to match against. name_any (bool, optional): - Accept any name and just return the matching characters. + Accept any name and return either 0 (match) or -1 (no match). Defaults to False. Returns: - int: - -1 if no match is found or the number of matching - characters (case insensitive) between for all uppercase groups. + int: -1 if no match is found or the number of matching + characters (case insensitive). """ + path_regex = r"([a-zA-Z0-9_.]+)" + if name == hdf_name: return len(name) * 2 + if hdf_name.startswith(".") or hdf_name.endswith("."): + # Don't match anything with a dot at the beginning or end + return -1 - uppercase_parts = re.findall("[A-Z]+(?:_[A-Z]+)*", name) + uppercase_parts = re.findall(r"[A-Z]+(?:_[A-Z]+)*", name) + regex_name = name + uppercase_count = 0 for up in uppercase_parts: - name = name.replace(up, r"([a-zA-Z0-9_]+)") + uppercase_count += len(up) + regex_name = regex_name.replace(up, path_regex) - name_match = re.search(rf"^{name}$", hdf_name) + name_match = re.search(rf"^{regex_name}$", hdf_name) if name_match is None: return 0 if name_any else -1 - fit = 0 - for up, low in zip(uppercase_parts, name_match.groups()): - for i in range(min(len(up), len(low))): - if up[i].lower() == low[i]: - fit += 1 + match_count = 0 + for uppercase, match in zip(uppercase_parts, name_match.groups()): + for s1, s2 in zip(uppercase.upper(), match.upper()): + if s1 == s2: + match_count += 1 - return fit + return len(name) + match_count - uppercase_count def get_nx_classes(): From 8fe651de850d55ffb3d7c26435abd72a82b7bfc2 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Thu, 18 Apr 2024 18:22:12 +0200 Subject: [PATCH 092/136] Change `get_enums` to return a list (#218) * Change `get_enums` to return a list * Update get_enums to return whether an enum was found * Fix use of get_enums function * isorting * Use None instead of true/false tuple * Update docstring --- dev_tools/utils/nxdl_utils.py | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index ce32ad3ac..8d73e9991 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -7,6 +7,8 @@ from functools import lru_cache from glob import glob from pathlib import Path +from typing import List +from typing import Optional import lxml.etree as ET from lxml.etree import ParseError as xmlER @@ -595,13 +597,15 @@ def get_doc(node, ntype, nxhtml, nxpath): doc_field = node.find("doc") if doc_field is not None: doc = doc_field.text - (index, enums) = get_enums(node) # enums - if index: + enums = get_enums(node) # enums + if enums is not None: enum_str = ( "\n " - + ("Possible values:" if enums.count(",") else "Obligatory value:") + + ("Possible values:" if len(enums) > 1 else "Obligatory value:") + "\n " - + enums + + "[" + + ",".join(enums) + + "]" + "\n" ) else: @@ -631,20 +635,26 @@ def get_namespace(element): return element.tag[element.tag.index("{") : element.tag.rindex("}") + 1] -def get_enums(node): - """Makes list of enumerations, if node contains any. - Returns comma separated STRING of enumeration values, if there are enum tag, - otherwise empty string.""" - # collect item values from enumeration tag, if any +def get_enums(node: ET._Element) -> Optional[List[str]]: + """ + Makes list of enumerations, if node contains any. + + Args: + node (ET._Element): The node to check for enumerations. + + Returns: + Optional[List[str]]: + Returns a list of the enumeration values if an enumeration was found. + If no enumeration was found it returns None. + """ namespace = get_namespace(node) enums = [] for enumeration in node.findall(f"{namespace}enumeration"): for item in enumeration.findall(f"{namespace}item"): enums.append(item.attrib["value"]) - enums = ",".join(enums) - if enums != "": - return (True, "[" + enums + "]") - return (False, "") # if there is no enumeration tag, returns empty string + if enums: + return enums + return None def add_base_classes(elist, nx_name=None, elem: ET.Element = None): From ba60d4ab161094db9e6357e55965e5596d644ce9 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Tue, 30 Apr 2024 11:11:36 +0200 Subject: [PATCH 093/136] Make attr logging an f-string (#221) * Make attr logging an f-string * Linting * isorting --- dev_tools/utils/nxdl_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 8d73e9991..73dba7ac9 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -445,7 +445,7 @@ def get_required_string(nxdl_elem): def write_doc_string(logger, doc, attr): """Simple function that prints a line in the logger if doc exists""" if doc: - logger.debug("@%s [NX_CHAR]", attr) + logger.debug(f"@{attr} [NX_CHAR]") return logger, doc, attr From 34c05ceb68faa42818ea4cbba6a83a1ce094d720 Mon Sep 17 00:00:00 2001 From: domna Date: Thu, 9 May 2024 23:14:40 +0200 Subject: [PATCH 094/136] Add edge cases to namefit documentation # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 73dba7ac9..7f1bc3c97 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -135,6 +135,8 @@ def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False) -> int: * `get_nx_namefit("my_other_name", "TEST_name")` returns 5 * `get_nx_namefit("test_name", "test_name")` returns 18 * `get_nx_namefit("test_other", "test_name")` returns -1 + * `get_nx_namefit("something", "XXXX")` returns 0 + * `get_nx_namefit("something", "OTHER")` returns 1 Args: hdf_name (str): The hdf_name, containing the name of the HDF5 node. From ab01ad14991f4cd80e4f178e70ba90b70bbaac76 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Mon, 13 May 2024 16:14:50 +0200 Subject: [PATCH 095/136] Fix that attributes are found as fields (#222) * Remove dead/wrong code * Format with black * isorting --- dev_tools/utils/nxdl_utils.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 7f1bc3c97..c62206bfc 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -346,18 +346,6 @@ def get_own_nxdl_child( name - nxdl name class_type - nxdl type or hdf classname (for groups, it is obligatory) hdf_name - hdf name""" - for child in nxdl_elem: - if not isinstance(child.tag, str): - continue - if child.attrib.get("name") == name: - return set_nxdlpath(child, nxdl_elem) - for child in nxdl_elem: - if not isinstance(child.tag, str): - continue - if child.attrib.get("name") == name: - child.set("nxdlbase", nxdl_elem.get("nxdlbase")) - return child - for child in nxdl_elem: if not isinstance(child.tag, str): continue From 86ec14c730b5187cdac8423545135bbaa5e31651 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 26 Jun 2024 11:47:49 +0200 Subject: [PATCH 096/136] Added connections to EMglossary, fixed deprecated call to utcnow # Conflicts: # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXlens_em.nxdl.xml # contributed_definitions/NXoptical_system_em.nxdl.xml # contributed_definitions/NXscanbox_em.nxdl.xml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXlens_em.yaml # contributed_definitions/nyaml/NXoptical_system_em.yaml # contributed_definitions/nyaml/NXscanbox_em.yaml --- dev_tools/docs/anchor_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/docs/anchor_list.py b/dev_tools/docs/anchor_list.py index df668ead0..a84ddd290 100644 --- a/dev_tools/docs/anchor_list.py +++ b/dev_tools/docs/anchor_list.py @@ -114,7 +114,7 @@ def write(self): return contents = dict( _metadata=dict( - datetime=datetime.datetime.utcnow().isoformat(), + datetime=datetime.datetime.now(datetime.UTC).isoformat(), title="NeXus NXDL vocabulary.", subtitle="Anchors for all NeXus fields, groups, " "attributes, and links.", From 4d168c75dc017964ea45ffacbb0254860897e9a5 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 27 Jun 2024 13:24:21 +0200 Subject: [PATCH 097/136] Reverted code modernization that does not work in python=3.9 but that should be used for python>=3.12 --- dev_tools/docs/anchor_list.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev_tools/docs/anchor_list.py b/dev_tools/docs/anchor_list.py index a84ddd290..1b411041d 100644 --- a/dev_tools/docs/anchor_list.py +++ b/dev_tools/docs/anchor_list.py @@ -114,7 +114,11 @@ def write(self): return contents = dict( _metadata=dict( - datetime=datetime.datetime.now(datetime.UTC).isoformat(), + # datetime=datetime.datetime.now(datetime.UTC).isoformat(), + # the next line is the py3.9 supported way of getting the datetime + # this will become deprecated however in py3.12 for which the + # line above-mentioned is a fix, which however does not work in py3.9 + datetime=datetime.datetime.utcnow().isoformat(), title="NeXus NXDL vocabulary.", subtitle="Anchors for all NeXus fields, groups, " "attributes, and links.", From 3789e456bfce59a2872c87c0c25a7971e8ca87c6 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 27 Jun 2024 18:38:21 +0200 Subject: [PATCH 098/136] Fused NXimage_r_set, NXimage_c_set, NXimage_r_set_diff into a single more meaty base class NXimage_set, the partner in crime for NXspectrum_set # Conflicts: # contributed_definitions/NXapm.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXem_eds.nxdl.xml # contributed_definitions/NXem_img.nxdl.xml # contributed_definitions/NXem_method.nxdl.xml # contributed_definitions/NXem_sim.nxdl.xml # contributed_definitions/NXimage_c_set.nxdl.xml # contributed_definitions/NXimage_r_set.nxdl.xml # contributed_definitions/NXimage_r_set_diff.nxdl.xml # contributed_definitions/NXimage_set.nxdl.xml # contributed_definitions/NXspectrum_set.nxdl.xml # contributed_definitions/nyaml/NXapm.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXem_eds.yaml # contributed_definitions/nyaml/NXem_img.yaml # contributed_definitions/nyaml/NXem_method.yaml # contributed_definitions/nyaml/NXem_sim.yaml # contributed_definitions/nyaml/NXevent_data_em.yaml # contributed_definitions/nyaml/NXimage_r_set_diff.yaml # contributed_definitions/nyaml/NXimage_set.yaml # contributed_definitions/nyaml/NXspectrum_set.yaml # dev_tools/tests/test_nxdl_utils.py # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXem_adf.nxdl.xml | 21 +- contributed_definitions/NXem_eds.nxdl.xml | 193 ------- contributed_definitions/NXem_method.nxdl.xml | 47 -- .../NXimage_c_set.nxdl.xml | 471 ------------------ .../NXimage_r_set.nxdl.xml | 333 ------------- .../NXimage_r_set_diff.nxdl.xml | 179 ------- contributed_definitions/nyaml/NXem_adf.yaml | 11 +- contributed_definitions/nyaml/NXem_eds.yaml | 122 ----- .../nyaml/NXem_method.yaml | 21 - .../nyaml/NXimage_c_set.yaml | 272 ---------- .../nyaml/NXimage_r_set.yaml | 188 ------- .../nyaml/NXimage_r_set_diff.yaml | 123 ----- 12 files changed, 2 insertions(+), 1979 deletions(-) delete mode 100644 contributed_definitions/NXem_eds.nxdl.xml delete mode 100644 contributed_definitions/NXem_method.nxdl.xml delete mode 100644 contributed_definitions/NXimage_c_set.nxdl.xml delete mode 100644 contributed_definitions/NXimage_r_set.nxdl.xml delete mode 100644 contributed_definitions/NXimage_r_set_diff.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXem_eds.yaml delete mode 100644 contributed_definitions/nyaml/NXem_method.yaml delete mode 100644 contributed_definitions/nyaml/NXimage_c_set.yaml delete mode 100644 contributed_definitions/nyaml/NXimage_r_set.yaml delete mode 100644 contributed_definitions/nyaml/NXimage_r_set_diff.yaml diff --git a/contributed_definitions/NXem_adf.nxdl.xml b/contributed_definitions/NXem_adf.nxdl.xml index 92e784ee3..7e9902988 100644 --- a/contributed_definitions/NXem_adf.nxdl.xml +++ b/contributed_definitions/NXem_adf.nxdl.xml @@ -22,23 +22,6 @@ # For further information, see http://www.nexusformat.org --> - - - - Number of images in the stack. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - Base class method-specific for annular dark field imaging. @@ -50,7 +33,7 @@ For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. - + Annulus inner (first value) and outer (second value) half angle. @@ -60,6 +43,4 @@ - diff --git a/contributed_definitions/NXem_eds.nxdl.xml b/contributed_definitions/NXem_eds.nxdl.xml deleted file mode 100644 index 8550cbe81..000000000 --- a/contributed_definitions/NXem_eds.nxdl.xml +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - Number of X-ray photon energy (bins), the fastest direction. - - - - - Number of identified elements - - - - - Number of peaks detected - - - - - Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDXS). - - `IUPAC instead of Siegbahn notation <https://doi.org/10.1002/xrs.1300200308>`_ should be used. - - X-ray spectroscopy is a surface-sensitive technique. Therefore, three-dimensional elemental - characterzation requires typically a sequence of characterization and preparation of the - surface to expose a new surface layer that can be characterized in the next acquisition. - In effect, the resulting three-dimensional elemental information mappings are truely the - result of a correlation and post-processing of several measurements which is the field - of correlative tomographic usage of electron microscopy. - - - - - Details about computational steps how peaks were indexed as elements. - - - - The program with which the indexing was performed. - - - - - Accumulated intensity over all pixels of the region-of-interest. - - - - Accumulated counts - - - - - - - Counts - - - - - - Energy axis - - - - - - - Energy - - - - - - - Name and location of each X-ray line which was indexed as a known ion. - For each ion, an NXion instance should be created which specifies - the origin of the signal. For each ion also the relevant IUPAC notation - X-ray lines should be specified. - - - - - Associated lower :math:`[e_{min}, e_{max}]` bounds of the - energy which is assumed associated with this peak. - - - - - - - - Theoretical energy of the line according to IUPAC. - - - - - IUPAC notation identifier of the line which the peak represents. - - This can be a list of IUPAC notations for (the seldom) case that - multiple lines are grouped with the same peak. - - - - - - - - - - Comma-separated list of names of identified elements. All members of - the list have to be valid chemical_symbols from the periodic table. - - This field can be used when creating instances of NXpeak is not desired. - However, a collection of instances of NXpeak with individual NXion specified - enables also to distinguish isotopic information. - - - - - - - - Individual element-specific EDS/EDX/EDXS/SXES mapping - - A composition map is an image whose intensities for each pixel are the - accumulated X-ray quanta *under the curve(s)* of a set of peaks. - - These element-specific EDS maps are NXimage_r_set instances - and need to be named with the name of the element from the - element_names field. - - We often observe that signal contributions from several peaks - are summarized and shown together, e.g. the combined signal - under the curve of carbon and oxygen. - - In this case specify the processing details using peaks and weights. - - - - - A list of NXpeak instance names whose X-ray quanta - where accumulated for each pixel which yields an element-specific - EDS map. - - - - - - - - A list of weights by how much the intensity of each peak - under peaks was factorized to display the joint intensity - of the image. - - - - - - - diff --git a/contributed_definitions/NXem_method.nxdl.xml b/contributed_definitions/NXem_method.nxdl.xml deleted file mode 100644 index 086d4833d..000000000 --- a/contributed_definitions/NXem_method.nxdl.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - Base class to describe specific analysis methods in electron microscopy. - - This base class represent a template how specialized, deep, and method-specific - base classes can be defined with which an (NXem) application - definition gets equipped with specific groups to document method-specific - processing steps and report analyzed quantities. - - The template base class name :ref:`NXem_method` needs to be changed for each - method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. - - - - Details about processing steps. - - - - - - - diff --git a/contributed_definitions/NXimage_c_set.nxdl.xml b/contributed_definitions/NXimage_c_set.nxdl.xml deleted file mode 100644 index ea711bbb8..000000000 --- a/contributed_definitions/NXimage_c_set.nxdl.xml +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - Number of images in the (hyper)stack. - - - - - Number of pixel per image in the slowest direction. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - - - Specialized base class container for reporting a set of images in reciprocal space. - - In practice, complex numbers are encoded via some formatted pair of real values. - Typically, fast Algorithms for computing Fourier Transformations (FFT) are - used to encode images in reciprocal (frequency) space. FFT libraries are used - for implementing the key functionalities of these mathematical operations. - - Different libraries use different representations and encoding of the - image computed. Details can be found in the respective sections of the - typical FFT libraries: - - * `FFTW by M. Frigo and S. G. Johnson <https://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial>`_ - * `Intel MKL by the Intel Co. <https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2023-0/fourier-transform-functions.html>`_ - * `cuFFT by the NVidia Co. <https://docs.nvidia.com/cuda/cufft/index.html>`_ - - Users are strongly advised to inspect carefully which specific conventions - their library uses to be able to store and modify the implementation of their - code so that the serialized representations as it is detailed - here for NeXus matches with their intention. - - One- and two-dimensional FFTs should use the stack(NXdata) instances. - Three-dimensional FFTs should use the hyperstack(NXdata) instances. - - - - - One-dimensional image. - - - - Image intensity of the real part. - - - - - - - - Image intensity of the imaginary part. - - - - - - - - Magnitude of the image intensity. - - - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - - - Two-dimensional image. - - - - Image intensity of the real part. - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - Pixel coordinate center along j direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - - - Three-dimensional image. - - - - Image intensity of the real part. - - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - - Pixel coordinate center along k direction. - - - - - - - Coordinate along k direction. - - - - - - Pixel coordinate center along j direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - - - Collection of one-dimensional images. - - - - Image intensity of the real part. - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - - - Collection of two-dimensional images. - - - - Image intensity of the real part. - - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along j direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - - - Collection of three-dimensional images. - - - - Image intensity of the real part. - - - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along k direction. - - - - - - - Coordinate along k direction. - - - - - - Pixel coordinate center along j direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - diff --git a/contributed_definitions/NXimage_r_set.nxdl.xml b/contributed_definitions/NXimage_r_set.nxdl.xml deleted file mode 100644 index b57afc774..000000000 --- a/contributed_definitions/NXimage_r_set.nxdl.xml +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - Number of images in the stack. - - - - - Number of pixel per image in the slowest direction. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - - - Specialized base class container for reporting a set of images in real space. - - - - - One-dimensional image. - - - - Image intensity values. - - - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - - - Two-dimensional image. - - - - Image intensity values. - - - - - - - - - Pixel coordinate center along y direction. - - - - - - - Coordinate along y direction. - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - - - Three-dimensional image. - - - - Image intensity values. - - - - - - - - - - Pixel coordinate center along z direction. - - - - - - - Coordinate along z direction. - - - - - - Pixel coordinate center along y direction. - - - - - - - Coordinate along y direction. - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - - - Collection of one-dimensional images. - - - - Image intensity values. - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - - - Collection of two-dimensional images. - - - - Image intensity values. - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along y direction. - - - - - - - Coordinate along y direction. - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - - - Collection of three-dimensional images. - - - - Image intensity values. - - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along z direction. - - - - - - - Coordinate along z direction. - - - - - - Pixel coordinate center along y direction. - - - - - - - Coordinate along y direction. - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - diff --git a/contributed_definitions/NXimage_r_set_diff.nxdl.xml b/contributed_definitions/NXimage_r_set_diff.nxdl.xml deleted file mode 100644 index c9ff02c0d..000000000 --- a/contributed_definitions/NXimage_r_set_diff.nxdl.xml +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - Number of scanned points. Scan point may have none, one, or more pattern. - - - - - Number of diffraction pattern. - - - - - Number of pixel per pattern in the slow direction. - - - - - Number of pixel per pattern in the fast direction. - - - - - Base class specialized for reporting a cuboidal stack of diffraction pattern. - - Diffraction pattern, whether they were simulated or measured are the raw data - for computational workflows to characterize the phase and orientation - of crystalline regions in matter. - - Steps of post-processing the diffraction patterns should be documented using - method-specific specialized base classes. All eventual post-processing of - resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. - - To implement an example how this base class can be used we focused in FAIRmat - on Kikuchi diffraction pattern here specifically the research community - of Electron Backscatter Diffraction (EBSD). - - For this reason, this base class and related :ref:`NXem_base` classes extend the - work of `M. A. Jackson et al. <https://doi.org/10.1186/2193-9772-3-4>`_ - (one of the developers of DREAM.3D) and the H5OINA public file format developed by - `P. Pinard et al. <https://doi.org/10.1017/S1431927621006103>`_ with Oxford Instruments. - - Kikuchi pattern are typically collected with FIB/SEM microscopes, - for two- and three-dimensional orientation microscopy. - - For a detailed overview of these techniques see e.g. - - * `M. A. Groeber et al. <https://doi.org/10.1186/2193-9772-3-5>`_ - * `A. J. Schwartz et al. <https://doi.org/10.1007/978-1-4757-3205-4>`_ - * `P. A. Rottman et al. <https://doi.org/10.1016/j.mattod.2021.05.003>`_ - - Serial-sectioning demands a recurrent sequence of ion milling and measuring. - This suggests that each serial section is at least an own NXevent_data_em - instance. The three-dimensional characterization as such demands a computational - step where the maps for each serial section get cleaned, aligned, and registered - into an image stack. This image stack represents a digital model of the - inspected microstructural volume. Often this volume is called a (representative) - volume element (RVE). Several software packages exists for performing - these post-processing tasks. - - This example may inspire users of other types of diffraction methods. - - - - Category which type of diffraction pattern is reported. - - - - - - - - Collected diffraction pattern as an image stack. As raw and closest to the - first retrievable measured data as possible, i.e. do not use this - container to store already averaged, filtered or whatever post-processed - pattern unless these are generated unmodifiably in such manner by the - instrument given the way how the instrument and control software - was configured for your microscope session. - - - - Array which resolves the scan point to which each pattern belongs. - - Scan points are evaluated in sequence starting from scan point zero - until scan point n_sc - 1. Evaluating the cumulated of this array - decodes which pattern in intensity belongs to which scan point. - - Take an example with three scan points: The first scan point has one - pattern, the second has three pattern, the last scan point has no - pattern. In this case the scan_point_identifier are 0, 1, 1, 1. - The length of the scan_point_identifier array is four because four - pattern were measured in total. - - In most cases usually one pattern is averaged by the detector for - some amount of time and then reported as one pattern. - - - - - - - - Intensity of the diffraction pattern. - - - - - - - - - - Pattern intensity - - - - - - - Pattern are enumerated starting from 0 to n_p - 1. - - - - - - - Pattern identifier - - - - - - - diff --git a/contributed_definitions/nyaml/NXem_adf.yaml b/contributed_definitions/nyaml/NXem_adf.yaml index 02a21e52c..c64af34d4 100644 --- a/contributed_definitions/nyaml/NXem_adf.yaml +++ b/contributed_definitions/nyaml/NXem_adf.yaml @@ -9,20 +9,11 @@ doc: | For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. -symbols: - n_images: | - Number of images in the stack. - n_y: | - Number of pixel per image in the slow direction. - n_x: | - Number of pixel per image in the fast direction. type: group NXem_adf(NXem_method): - (NXimage_r_set): + (NXimage_set): half_angle_interval(NX_NUMBER): doc: | Annulus inner (first value) and outer (second value) half angle. unit: NX_ANGLE dim: (2,) - # all information about annular dark field images is composed from - # the NXimage_r_set_em base class diff --git a/contributed_definitions/nyaml/NXem_eds.yaml b/contributed_definitions/nyaml/NXem_eds.yaml deleted file mode 100644 index 06148a018..000000000 --- a/contributed_definitions/nyaml/NXem_eds.yaml +++ /dev/null @@ -1,122 +0,0 @@ -category: base -doc: | - Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDXS). - - `IUPAC instead of Siegbahn notation `_ should be used. - - X-ray spectroscopy is a surface-sensitive technique. Therefore, three-dimensional elemental - characterzation requires typically a sequence of characterization and preparation of the - surface to expose a new surface layer that can be characterized in the next acquisition. - In effect, the resulting three-dimensional elemental information mappings are truely the - result of a correlation and post-processing of several measurements which is the field - of correlative tomographic usage of electron microscopy. -# NEW ISSUE: use computational geometry to offer arbitrary scan pattern -# NEW ISSUE: make the binning flexible per scan point -symbols: - # n_p: Number of scan points - # n_z: Number of pixel along the z direction, the slowest direction - # n_y: Number of pixel along the y direction, the slow direction - # n_x: Number of pixel along the x direction, the fast direction - n_photon_energy: | - Number of X-ray photon energy (bins), the fastest direction. - n_elements: | - Number of identified elements - n_peaks: | - Number of peaks detected -type: group -NXem_eds(NXem_method): - # NXprocess is composed from NXem_method base class instances where the spectra - # are stored as instances of (NXspectrum_set) is composed from NXem_method base class - # for post-processing of/with the above-defined data entries - # including feedback from Christoph Pauly (from MX Uni Saarland, NFDI-MatWerk), - # Sabine Bergmann and Sebastian Brückner (both from FAIRmat, IKZ), - # and Adrien Teutrie, Cecile Hebert (EPFL) - indexing(NXprocess): - doc: | - Details about computational steps how peaks were indexed as elements. - (NXprogram): - doc: | - The program with which the indexing was performed. - summary(NXdata): - doc: | - Accumulated intensity over all pixels of the region-of-interest. - intensity(NX_NUMBER): - doc: | - Accumulated counts - unit: NX_UNITLESS - dim: (n_photon_energy,) - \@long_name(NX_CHAR): - doc: | - Counts - axis_energy(NX_NUMBER): - doc: | - Energy axis - unit: NX_ENERGY - dim: (n_photon_energy,) - \@long_name(NX_CHAR): - doc: | - Energy - PEAK(NXpeak): - doc: | - Name and location of each X-ray line which was indexed as a known ion. - For each ion, an NXion instance should be created which specifies - the origin of the signal. For each ion also the relevant IUPAC notation - X-ray lines should be specified. - (NXion): - energy_range(NX_NUMBER): - doc: | - Associated lower :math:`[e_{min}, e_{max}]` bounds of the - energy which is assumed associated with this peak. - unit: NX_ENERGY - dim: (2,) - energy(NX_NUMBER): - doc: | - Theoretical energy of the line according to IUPAC. - unit: NX_ENERGY - iupac_line_names(NX_CHAR): - doc: | - IUPAC notation identifier of the line which the peak represents. - - This can be a list of IUPAC notations for (the seldom) case that - multiple lines are grouped with the same peak. - dim: (i,) - element_names(NX_CHAR): - doc: | - Comma-separated list of names of identified elements. All members of - the list have to be valid chemical_symbols from the periodic table. - - This field can be used when creating instances of NXpeak is not desired. - However, a collection of instances of NXpeak with individual NXion specified - enables also to distinguish isotopic information. - dim: (n_elements,) - (NXimage_r_set): - doc: | - Individual element-specific EDS/EDX/EDXS/SXES mapping - - A composition map is an image whose intensities for each pixel are the - accumulated X-ray quanta *under the curve(s)* of a set of peaks. - - These element-specific EDS maps are NXimage_r_set instances - and need to be named with the name of the element from the - element_names field. - - We often observe that signal contributions from several peaks - are summarized and shown together, e.g. the combined signal - under the curve of carbon and oxygen. - - In this case specify the processing details using peaks and weights. - - (NXprocess): - peaks(NX_CHAR): - doc: | - A list of NXpeak instance names whose X-ray quanta - where accumulated for each pixel which yields an element-specific - EDS map. - dim: (n_peaks,) - weights(NX_NUMBER): - doc: | - A list of weights by how much the intensity of each peak - under peaks was factorized to display the joint intensity - of the image. - unit: NX_UNITLESS - # everything else is composed from NXimage_r_set diff --git a/contributed_definitions/nyaml/NXem_method.yaml b/contributed_definitions/nyaml/NXem_method.yaml deleted file mode 100644 index afe91de97..000000000 --- a/contributed_definitions/nyaml/NXem_method.yaml +++ /dev/null @@ -1,21 +0,0 @@ -category: base -doc: | - Base class to describe specific analysis methods in electron microscopy. - - This base class represent a template how specialized, deep, and method-specific - base classes can be defined with which an (NXem) application - definition gets equipped with specific groups to document method-specific - processing steps and report analyzed quantities. - - The template base class name :ref:`NXem_method` needs to be changed for each - method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. -# :ref:`NXem_se`, :ref:`NXem_bse`. -type: group -NXem_method(NXobject): - (NXprocess): - doc: | - Details about processing steps. - sequence_index(NX_INT): - IMAGE_R_SET(NXimage_r_set): - IMAGE_C_SET(NXimage_c_set): - SPECTRUM_SET(NXspectrum_set): diff --git a/contributed_definitions/nyaml/NXimage_c_set.yaml b/contributed_definitions/nyaml/NXimage_c_set.yaml deleted file mode 100644 index 303017ab1..000000000 --- a/contributed_definitions/nyaml/NXimage_c_set.yaml +++ /dev/null @@ -1,272 +0,0 @@ -category: base -doc: | - Specialized base class container for reporting a set of images in reciprocal space. - - In practice, complex numbers are encoded via some formatted pair of real values. - Typically, fast Algorithms for computing Fourier Transformations (FFT) are - used to encode images in reciprocal (frequency) space. FFT libraries are used - for implementing the key functionalities of these mathematical operations. - - Different libraries use different representations and encoding of the - image computed. Details can be found in the respective sections of the - typical FFT libraries: - - * `FFTW by M. Frigo and S. G. Johnson `_ - * `Intel MKL by the Intel Co. `_ - * `cuFFT by the NVidia Co. `_ - - Users are strongly advised to inspect carefully which specific conventions - their library uses to be able to store and modify the implementation of their - code so that the serialized representations as it is detailed - here for NeXus matches with their intention. - - One- and two-dimensional FFTs should use the stack(NXdata) instances. - Three-dimensional FFTs should use the hyperstack(NXdata) instances. -symbols: - n_images: | - Number of images in the (hyper)stack. - n_k: | - Number of pixel per image in the slowest direction. - n_j: | - Number of pixel per image in the slow direction. - n_i: | - Number of pixel per image in the fast direction. -type: group -NXimage_c_set(NXimage_set): - # details about the FFT library used could for instance be stored in the - # NXprocess group which the NXimage_c_set base class can borrow from its - # NXimage_set parent base class - # process information are composable from the NXimage_set base class - image_oned(NXdata): - doc: | - One-dimensional image. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_i,) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_i,) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_i) - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. - - image_twod(NXdata): - doc: | - Two-dimensional image. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_j, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_j, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_j, n_i) - axis_j(NX_NUMBER): - doc: | - Pixel coordinate center along j direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_j,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. - - image_threed(NXdata): - doc: | - Three-dimensional image. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_k, n_j, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_k, n_j, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_k, n_j, n_i) - axis_k(NX_NUMBER): - doc: | - Pixel coordinate center along k direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_k,) - \@long_name(NX_CHAR): - doc: | - Coordinate along k direction. - axis_j(NX_NUMBER): - doc: | - Pixel coordinate center along j direction. - unit: NX_ANY - dim: (n_j,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. - - stack_oned(NXdata): - doc: | - Collection of one-dimensional images. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_images, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_images, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_images, n_i) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. - - stack_twod(NXdata): - doc: | - Collection of two-dimensional images. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_images, n_j, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_images, n_j, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_images, n_j, n_i) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_j(NX_NUMBER): - doc: | - Pixel coordinate center along j direction. - unit: NX_ANY - dim: (n_j,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. - - stack_threed(NXdata): - doc: | - Collection of three-dimensional images. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_images, n_k, n_j, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_images, n_k, n_j, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_images, n_k, n_j, n_i) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_k(NX_NUMBER): - doc: | - Pixel coordinate center along k direction. - unit: NX_ANY - dim: (n_k,) - \@long_name(NX_CHAR): - doc: | - Coordinate along k direction. - axis_j(NX_NUMBER): - doc: | - Pixel coordinate center along j direction. - unit: NX_ANY - dim: (n_j,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set.yaml b/contributed_definitions/nyaml/NXimage_r_set.yaml deleted file mode 100644 index 5c63988c6..000000000 --- a/contributed_definitions/nyaml/NXimage_r_set.yaml +++ /dev/null @@ -1,188 +0,0 @@ -category: base -doc: | - Specialized base class container for reporting a set of images in real space. -symbols: - n_images: | - Number of images in the stack. - n_z: | - Number of pixel per image in the slowest direction. - n_y: | - Number of pixel per image in the slow direction. - n_x: | - Number of pixel per image in the fast direction. -type: group -NXimage_r_set(NXimage_set): - # process information are composable from the NXimage_set base class - image_oned(NXdata): - doc: | - One-dimensional image. - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_x,) - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. - - image_twod(NXdata): - doc: | - Two-dimensional image. - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_y, n_x) - axis_y(NX_NUMBER): - doc: | - Pixel coordinate center along y direction. - unit: NX_LENGTH - dim: (n_y,) - \@long_name(NX_CHAR): - doc: | - Coordinate along y direction. - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. - - image_threed(NXdata): - doc: | - Three-dimensional image. - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_z, n_y, n_x) - axis_z(NX_NUMBER): - doc: | - Pixel coordinate center along z direction. - unit: NX_LENGTH - dim: (n_z,) - \@long_name(NX_CHAR): - doc: | - Coordinate along z direction. - axis_y(NX_NUMBER): - doc: | - Pixel coordinate center along y direction. - unit: NX_LENGTH - dim: (n_y,) - \@long_name(NX_CHAR): - doc: | - Coordinate along y direction. - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. - - stack_oned(NXdata): - doc: | - Collection of one-dimensional images. - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_images, n_x) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. - - stack_twod(NXdata): - doc: | - Collection of two-dimensional images. - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_images, n_y, n_x) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_y(NX_NUMBER): - doc: | - Pixel coordinate center along y direction. - unit: NX_LENGTH - dim: (n_y,) - \@long_name(NX_CHAR): - doc: | - Coordinate along y direction. - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. - - stack_threed(NXdata): - doc: | - Collection of three-dimensional images. - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_images, n_z, n_y, n_x) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_z(NX_NUMBER): - doc: | - Pixel coordinate center along z direction. - unit: NX_LENGTH - dim: (n_z,) - \@long_name(NX_CHAR): - doc: | - Coordinate along z direction. - axis_y(NX_NUMBER): - doc: | - Pixel coordinate center along y direction. - unit: NX_LENGTH - dim: (n_y,) - \@long_name(NX_CHAR): - doc: | - Coordinate along y direction. - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml deleted file mode 100644 index 79ca31b16..000000000 --- a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml +++ /dev/null @@ -1,123 +0,0 @@ -category: base -doc: | - Base class specialized for reporting a cuboidal stack of diffraction pattern. - - Diffraction pattern, whether they were simulated or measured are the raw data - for computational workflows to characterize the phase and orientation - of crystalline regions in matter. - - Steps of post-processing the diffraction patterns should be documented using - method-specific specialized base classes. All eventual post-processing of - resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. - - To implement an example how this base class can be used we focused in FAIRmat - on Kikuchi diffraction pattern here specifically the research community - of Electron Backscatter Diffraction (EBSD). - - For this reason, this base class and related :ref:`NXem_base` classes extend the - work of `M. A. Jackson et al. `_ - (one of the developers of DREAM.3D) and the H5OINA public file format developed by - `P. Pinard et al. `_ with Oxford Instruments. - - Kikuchi pattern are typically collected with FIB/SEM microscopes, - for two- and three-dimensional orientation microscopy. - - For a detailed overview of these techniques see e.g. - - * `M. A. Groeber et al. `_ - * `A. J. Schwartz et al. `_ - * `P. A. Rottman et al. `_ - - Serial-sectioning demands a recurrent sequence of ion milling and measuring. - This suggests that each serial section is at least an own NXevent_data_em - instance. The three-dimensional characterization as such demands a computational - step where the maps for each serial section get cleaned, aligned, and registered - into an image stack. This image stack represents a digital model of the - inspected microstructural volume. Often this volume is called a (representative) - volume element (RVE). Several software packages exists for performing - these post-processing tasks. - - This example may inspire users of other types of diffraction methods. -symbols: - n_sc: | - Number of scanned points. Scan point may have none, one, or more pattern. - n_p: | - Number of diffraction pattern. - n_y: | - Number of pixel per pattern in the slow direction. - n_x: | - Number of pixel per pattern in the fast direction. -type: group -NXimage_r_set_diff(NXimage_r_set): - pattern_type(NX_CHAR): - doc: | - Category which type of diffraction pattern is reported. - enumeration: [kikuchi] - stack(NXdata): - doc: | - Collected diffraction pattern as an image stack. As raw and closest to the - first retrievable measured data as possible, i.e. do not use this - container to store already averaged, filtered or whatever post-processed - pattern unless these are generated unmodifiably in such manner by the - instrument given the way how the instrument and control software - was configured for your microscope session. - scan_point_identifier(NX_INT): - doc: | - Array which resolves the scan point to which each pattern belongs. - - Scan points are evaluated in sequence starting from scan point zero - until scan point n_sc - 1. Evaluating the cumulated of this array - decodes which pattern in intensity belongs to which scan point. - - Take an example with three scan points: The first scan point has one - pattern, the second has three pattern, the last scan point has no - pattern. In this case the scan_point_identifier are 0, 1, 1, 1. - The length of the scan_point_identifier array is four because four - pattern were measured in total. - - In most cases usually one pattern is averaged by the detector for - some amount of time and then reported as one pattern. - unit: NX_UNITLESS - dim: (n_p,) - intensity(NX_NUMBER): - doc: | - Intensity of the diffraction pattern. - unit: NX_UNITLESS - dim: (n_p, n_y, n_x) - # n_p fast 2, n_y faster 1, n_x fastest 0 - # in axes fast to fastest - # while for _indices fastest to fast - \@long_name(NX_CHAR): - doc: | - Pattern intensity - # \@signal: intensity - # \@axes: [pattern_identifier, ypos, xpos] - # \@xpos_indices: 0 - # \@ypos_indices: 1 - # \@pattern_identifier_indices: 2 - pattern_identifier(NX_INT): - doc: | - Pattern are enumerated starting from 0 to n_p - 1. - unit: NX_UNITLESS - dim: (n_p,) - \@long_name(NX_CHAR): - doc: | - Pattern identifier - # the following fields are taken from the NXimage_r_set base class - # axis_y(R): - # axis_x(R): - -# If we envision a (knowledge) graph for EBSD it consists of individual sub-graphs -# which convey information about the specimen preparation, the measurement of -# the specimen in the electron microscope, the indexing of the collected -# Kikuchi pattern stack, eventual post-processing of the indexed orientation -# images via similarity grouping algorithms to yield (grains, texture). -# Conceptually, these post-processing steps are most frequently serving -# the idea how can one reconstruct so-called microstructural features -# (grains, phases, interfaces) to infer material properties. -# In practice this calls for workflows which quantify correlations between -# the spatial arrangement of the microstructural features, the individual -# (thermodynamic, chemo-mechanical) properties of the features with the -# properties of materials at a coarser scale. -# With NXem and related NXms base classes we propose a covering -# and general solution how to handle such (meta)data with NeXus. From d423b9747fe16546a76b8cbc7a4d2240f054f8ec Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Tue, 13 Aug 2024 16:30:18 +0200 Subject: [PATCH 099/136] Update webpage for optical spectroscopy # Conflicts: # manual/source/classes/base_classes/optical-spectroscopy-structure.rst # manual/source/ellipsometry-structure.rst # manual/source/index.rst # manual/source/optical-spectroscopy-structure.rst --- dev_tools/docs/nxdl_index.py | 2 +- .../optical-spectroscopy-structure.rst | 184 ------------------ 2 files changed, 1 insertion(+), 185 deletions(-) delete mode 100644 manual/source/classes/base_classes/optical-spectroscopy-structure.rst diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index e5840aaeb..3d7139ca0 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -68,7 +68,7 @@ def nxdl_indices() -> Dict[str, dict]: print("---------++++++++-", section) if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}ellipsometry-structure\n") + rst_lines.append(f"{indentation}optical-spectroscopy\n") rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") diff --git a/manual/source/classes/base_classes/optical-spectroscopy-structure.rst b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst deleted file mode 100644 index 2ff2ba1d4..000000000 --- a/manual/source/classes/base_classes/optical-spectroscopy-structure.rst +++ /dev/null @@ -1,184 +0,0 @@ -.. _Optical-Spectroscopy-Structure-BC: - -==================== -Optical Spectroscopy -==================== - -.. index:: - Ellipsometry - Raman - DispersiveMaterial - - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES - - -.. _Ellipsometry-BC: - -Ellipsometry -############ - -Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. -The measurements are based on determining how the polarization state of light changes upon transmission and reflection. -Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. - -In the application definition, we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. - -.. _Raman-BC: - -Raman -############ - -Raman spectroscopy is a characterization method to analyze vibrational properties for liquids, gases, or solids. -The measurements is based on the inelastic light scattering due to the material's vibrations. -Interpretation can be done based on peaks, which represent the phonon properties (intensity, center, width). - -The application definition contains a minimum of descriptive elements required to understand Raman spectroscopy measurements. - - -Application Definitions ------------------------ - - :ref:`NXellipsometry`: - An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - - - -Base Classes ------------- - -This is the set of base classes for describing an optical experiment. - - :ref:`NXbeam` - Beam properties such as intensity, polarization, wavelength or direction. - - :ref:`NXdetector` - A detector for signal detection. - - :ref:`NXsource` - A light source such as laser, lamp or LED. - - :ref:`NXmonochromator` - A monochromator is often used to energetically disperse the scattered or emitted light. - - :ref:`NXsensor` - Specify external parameters that have influenced the sample such as - varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. - - - -.. _DispersiveMaterial-BC: - -Dispersive Material -################### - -A dispersive material is a description for the optical dispersion of materials. -This description may be used to store optical model data from an ellipsometric analysis -(or any other technique) or to build a database of optical constants for optical properties of materials. - -Application Definition ----------------------- - - :ref:`NXdispersive_material`: - An application definition to describe the dispersive properties of a material. - The material may be isotropic, uniaxial or biaxial. Hence, it may contain up - to three dispersive functions or tables. - - - -Base Classes ------------- - -There is a set of base classes for describing a dispersion. - - :ref:`NXdispersion` - This is an umbrella base class for a group of dispersion functions to describe the material. - For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. - If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. - This allows for, e.g. splitting real and imaginary parts and describing them seperately or - adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). - - :ref:`NXdispersion_function` - This dispersion is described by a function and its single and repeated parameter values. - It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` - (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. - - :ref:`NXdispersion_single_parameter` - This denotes a parameter which is used outside the summed part of a dispersion function, - e.g. ``eps_inf`` in the formula example above. - - :ref:`NXdispersion_repeated_parameter` - This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. - ``A`` and ``B`` are repeated parameters in the formula above. - - :ref:`NXdispersion_table` - This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. - -Formula Grammar ---------------- - -Below you find a grammar to which the formula should adhere and which can be used to parse and -evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be -filled with the respective single and repeated params from the stored data. -The grammer is written in the `EBNF `_ dialect -of `Lark `_, which is a parsing toolkit for python. -It is easily translatable to general EBNF and other parser generator dialects. -`Here `_ is a reference implementation in Rust/Python with a -`grammar `_ -written in `lalrpop `_. - -.. code-block:: - - ?assignment: "eps" "=" kkr_expression -> eps - | "n" "=" kkr_expression -> n - - ?kkr_expression: expression - | "" "+" "1j" "*" term -> kkr_term - - ?expression: term - | expression "+" term -> add - | expression "-" term -> sub - - ?term: factor - | term "*" factor -> mul - | term "/" factor -> div - - ?factor: power - | power "**" power -> power - - - ?power: "(" expression ")" - | FUNC "(" expression ")" -> func - | "sum" "[" repeated_expression "]" -> sum_expr - | NAME -> single_param_name - | SIGNED_NUMBER -> number - | BUILTIN -> builtin - - ?repeated_expression: repeated_term - | repeated_expression "+" repeated_term -> add - | repeated_expression "-" repeated_term -> sub - - - ?repeated_term: repeated_factor - | repeated_term "*" repeated_factor -> mul - | repeated_term "/" repeated_factor -> div - - ?repeated_factor: repeated_power - | repeated_power "**" repeated_power -> power - - ?repeated_power: "(" repeated_expression ")" - | FUNC "(" repeated_expression ")" -> func - | SIGNED_NUMBER -> number - | NAME -> param_name - | BUILTIN -> builtin - - FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" - BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" - - %import common.CNAME -> NAME - %import common.SIGNED_NUMBER - %import common.WS_INLINE - - %ignore WS_INLINE - From 0e598ff3034acc5014c28968d52ffd4289dc7df8 Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Wed, 14 Aug 2024 10:26:25 +0200 Subject: [PATCH 100/136] change ellips name to optical spec # Conflicts: # manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst # manual/source/index.rst # manual/source/optical-spectroscopy-structure.rst --- dev_tools/docs/nxdl_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index 3d7139ca0..af9997c67 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -68,7 +68,7 @@ def nxdl_indices() -> Dict[str, dict]: print("---------++++++++-", section) if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}optical-spectroscopy\n") + rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") From 3d7c59ae8eb314c0e50a590bef0052e8790d436a Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Mon, 26 Aug 2024 10:52:55 +0200 Subject: [PATCH 101/136] fix_renaming_of_ellipsometry_to_optical_spec # Conflicts: # manual/source/optical-spectroscopy-structure.rst --- dev_tools/docs/nxdl_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index af9997c67..e700c507a 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -163,7 +163,7 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: and acceptance as either a base class or application definition. Some contributions are grouped together: - :ref:`Optical Spectroscopy ` + :ref:`Optical Spectroscopy ` :ref:`Multi-dimensional Photoemission Spectroscopy ` From b6e2f7ada9b4550665e6214c9975431fd55377f9 Mon Sep 17 00:00:00 2001 From: rettigl Date: Tue, 10 Sep 2024 10:31:36 +0200 Subject: [PATCH 102/136] decode binary strings in nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index c62206bfc..d4212d088 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -767,16 +767,28 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): corresponding to the html documentation name html_name""" bestfit = -1 bestchild = None - if ( - "name" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["name"] == "NXdata" - and hdf_node is not None - and hdf_node.parent is not None - and hdf_node.parent.attrs.get("NX_class") == "NXdata" - ): - (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) - if fnd_child is not None: - return (fnd_child, fit) + try: + if ( + "name" in nxdl_elem.attrib.keys() + and nxdl_elem.attrib["name"] == "NXdata" + and hdf_node is not None + and hdf_node.parent is not None + and hdf_node.parent.attrs.get("NX_class").decode("UTF-8") == "NXdata" + ): + (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) + if fnd_child is not None: + return (fnd_child, fit) + except AttributeError: + if ( + "name" in nxdl_elem.attrib.keys() + and nxdl_elem.attrib["name"] == "NXdata" + and hdf_node is not None + and hdf_node.parent is not None + and hdf_node.parent.attrs.get("NX_class") == "NXdata" + ): + (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) + if fnd_child is not None: + return (fnd_child, fit) for child in nxdl_elem: if not isinstance(child.tag, str): continue From 97fdd8ae62a1b1a8a4daa272a20fd8a06b715ce1 Mon Sep 17 00:00:00 2001 From: rettigl Date: Tue, 10 Sep 2024 22:59:37 +0200 Subject: [PATCH 103/136] add function for decoding --- dev_tools/utils/nxdl_utils.py | 39 +++++++++++++++-------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index d4212d088..d07353e4b 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -14,6 +14,13 @@ from lxml.etree import ParseError as xmlER +def decode_or_not(elem): + """Decodes a byte array to string if necessary""" + if isinstance(elem, bytes): + elem = elem.decode("UTF-8") + return elem + + def remove_namespace_from_tag(tag): """Helper function to remove the namespace from an XML tag.""" @@ -767,28 +774,16 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): corresponding to the html documentation name html_name""" bestfit = -1 bestchild = None - try: - if ( - "name" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["name"] == "NXdata" - and hdf_node is not None - and hdf_node.parent is not None - and hdf_node.parent.attrs.get("NX_class").decode("UTF-8") == "NXdata" - ): - (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) - if fnd_child is not None: - return (fnd_child, fit) - except AttributeError: - if ( - "name" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["name"] == "NXdata" - and hdf_node is not None - and hdf_node.parent is not None - and hdf_node.parent.attrs.get("NX_class") == "NXdata" - ): - (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) - if fnd_child is not None: - return (fnd_child, fit) + if ( + "name" in nxdl_elem.attrib.keys() + and nxdl_elem.attrib["name"] == "NXdata" + and hdf_node is not None + and hdf_node.parent is not None + and decode_or_not(hdf_node.parent.attrs.get("NX_class")) == "NXdata" + ): + (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) + if fnd_child is not None: + return (fnd_child, fit) for child in nxdl_elem: if not isinstance(child.tag, str): continue From eaa8c4df72ccf39089fd126b09ebfefa86cc9852 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:09:09 +0200 Subject: [PATCH 104/136] proper string decoding # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 78 +++++++++++++++++++++++++++++++---- requirements.txt | 3 ++ 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index d07353e4b..a4de29207 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -7,18 +7,82 @@ from functools import lru_cache from glob import glob from pathlib import Path -from typing import List -from typing import Optional +from typing import List, Optional, Union + +import numpy as np import lxml.etree as ET from lxml.etree import ParseError as xmlER +import numpy as np +from typing import Union, List, Optional -def decode_or_not(elem): - """Decodes a byte array to string if necessary""" - if isinstance(elem, bytes): - elem = elem.decode("UTF-8") - return elem +def decode_string( + string_obj: Union[np.ndarray, bytes, str], + decode: bool = True +) -> Optional[Union[str, List[str], np.ndarray, bytes]]: + """ + Decodes a numpy ndarray of byte objects to a Python string or list of strings. + Also handles single bytes and string objects. If `decode` is False, returns the + initial value without decoding. + + Args: + string_obj: A numpy ndarray, bytes, or str that may need decoding. + decode: A boolean flag indicating whether to perform decoding. + + Returns: + A decoded string, a list of decoded strings, or the initial value if `decode` is False. + Returns None if the input is empty or invalid. + + Raises: + ValueError: If `string_obj` is not one of the supported types or decoding fails. + """ + if not decode: + # Return the initial value without decoding + if not isinstance(string_obj, (np.ndarray, bytes, str)): + raise ValueError(f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str.") + if isinstance(string_obj, np.ndarray): + return string_obj.tolist() if string_obj.size > 0 else None + return string_obj + + if isinstance(string_obj, np.ndarray): + if string_obj.size == 0: + return None + + # Handle fixed-length strings by stripping padding + if string_obj.dtype.kind == 'S': + valid_entries = [entry.decode("utf-8").rstrip('\x00') if isinstance(entry, bytes) else entry + for entry in string_obj if isinstance(entry, (str, bytes))] + else: + valid_entries = [entry for entry in string_obj if isinstance(entry, (str, bytes))] + + # Decode bytes to strings where necessary + decoded_list = [] + for entry in valid_entries: + if isinstance(entry, bytes): + try: + decoded_list.append(entry.decode("utf-8")) + except UnicodeDecodeError as e: + raise ValueError(f"Error decoding bytes: {e}") + else: + decoded_list.append(entry) + + # Return a scalar string if there's only one element, otherwise return the list + if len(decoded_list) == 1: + return decoded_list[0] + return decoded_list if decoded_list else None + + elif isinstance(string_obj, bytes): + try: + return string_obj.decode("utf-8") + except UnicodeDecodeError as e: + raise ValueError(f"Error decoding bytes: {e}") + + elif isinstance(string_obj, str): + return string_obj + + else: + raise ValueError(f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str.") def remove_namespace_from_tag(tag): diff --git a/requirements.txt b/requirements.txt index 74c736824..2ed3cbf1d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,3 +15,6 @@ pytest black>=24.1.1 flake8>=4 isort>=5.10 + +# String decoding +numpy \ No newline at end of file From 1526b63a0cc7c22f55072968d707e752ea13ea2f Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:10:52 +0200 Subject: [PATCH 105/136] remove unneeded imports --- dev_tools/utils/nxdl_utils.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index a4de29207..1e99a5853 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -14,9 +14,6 @@ import lxml.etree as ET from lxml.etree import ParseError as xmlER -import numpy as np -from typing import Union, List, Optional - def decode_string( string_obj: Union[np.ndarray, bytes, str], decode: bool = True From 054e6e49d352ec9c2b18e90cd5af0e4190224f52 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:16:56 +0200 Subject: [PATCH 106/136] black formatting # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 1e99a5853..91170e1e8 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -14,9 +14,9 @@ import lxml.etree as ET from lxml.etree import ParseError as xmlER + def decode_string( - string_obj: Union[np.ndarray, bytes, str], - decode: bool = True + string_obj: Union[np.ndarray, bytes, str], decode: bool = True ) -> Optional[Union[str, List[str], np.ndarray, bytes]]: """ Decodes a numpy ndarray of byte objects to a Python string or list of strings. @@ -37,7 +37,9 @@ def decode_string( if not decode: # Return the initial value without decoding if not isinstance(string_obj, (np.ndarray, bytes, str)): - raise ValueError(f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str.") + raise ValueError( + f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str." + ) if isinstance(string_obj, np.ndarray): return string_obj.tolist() if string_obj.size > 0 else None return string_obj @@ -47,11 +49,20 @@ def decode_string( return None # Handle fixed-length strings by stripping padding - if string_obj.dtype.kind == 'S': - valid_entries = [entry.decode("utf-8").rstrip('\x00') if isinstance(entry, bytes) else entry - for entry in string_obj if isinstance(entry, (str, bytes))] + if string_obj.dtype.kind == "S": + valid_entries = [ + ( + entry.decode("utf-8").rstrip("\x00") + if isinstance(entry, bytes) + else entry + ) + for entry in string_obj + if isinstance(entry, (str, bytes)) + ] else: - valid_entries = [entry for entry in string_obj if isinstance(entry, (str, bytes))] + valid_entries = [ + entry for entry in string_obj if isinstance(entry, (str, bytes)) + ] # Decode bytes to strings where necessary decoded_list = [] @@ -79,7 +90,9 @@ def decode_string( return string_obj else: - raise ValueError(f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str.") + raise ValueError( + f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str." + ) def remove_namespace_from_tag(tag): From 6d25290611e1c8d17f77b59affd73ecd41a3c0a4 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:42:41 +0200 Subject: [PATCH 107/136] remove code and move to pynxtools # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 86 +---------------------------------- 1 file changed, 2 insertions(+), 84 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 91170e1e8..c1b50754a 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -7,94 +7,12 @@ from functools import lru_cache from glob import glob from pathlib import Path -from typing import List, Optional, Union - -import numpy as np +from typing import List, Optional import lxml.etree as ET from lxml.etree import ParseError as xmlER -def decode_string( - string_obj: Union[np.ndarray, bytes, str], decode: bool = True -) -> Optional[Union[str, List[str], np.ndarray, bytes]]: - """ - Decodes a numpy ndarray of byte objects to a Python string or list of strings. - Also handles single bytes and string objects. If `decode` is False, returns the - initial value without decoding. - - Args: - string_obj: A numpy ndarray, bytes, or str that may need decoding. - decode: A boolean flag indicating whether to perform decoding. - - Returns: - A decoded string, a list of decoded strings, or the initial value if `decode` is False. - Returns None if the input is empty or invalid. - - Raises: - ValueError: If `string_obj` is not one of the supported types or decoding fails. - """ - if not decode: - # Return the initial value without decoding - if not isinstance(string_obj, (np.ndarray, bytes, str)): - raise ValueError( - f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str." - ) - if isinstance(string_obj, np.ndarray): - return string_obj.tolist() if string_obj.size > 0 else None - return string_obj - - if isinstance(string_obj, np.ndarray): - if string_obj.size == 0: - return None - - # Handle fixed-length strings by stripping padding - if string_obj.dtype.kind == "S": - valid_entries = [ - ( - entry.decode("utf-8").rstrip("\x00") - if isinstance(entry, bytes) - else entry - ) - for entry in string_obj - if isinstance(entry, (str, bytes)) - ] - else: - valid_entries = [ - entry for entry in string_obj if isinstance(entry, (str, bytes)) - ] - - # Decode bytes to strings where necessary - decoded_list = [] - for entry in valid_entries: - if isinstance(entry, bytes): - try: - decoded_list.append(entry.decode("utf-8")) - except UnicodeDecodeError as e: - raise ValueError(f"Error decoding bytes: {e}") - else: - decoded_list.append(entry) - - # Return a scalar string if there's only one element, otherwise return the list - if len(decoded_list) == 1: - return decoded_list[0] - return decoded_list if decoded_list else None - - elif isinstance(string_obj, bytes): - try: - return string_obj.decode("utf-8") - except UnicodeDecodeError as e: - raise ValueError(f"Error decoding bytes: {e}") - - elif isinstance(string_obj, str): - return string_obj - - else: - raise ValueError( - f"Unsupported type {type(string_obj)}. Expected np.ndarray, bytes, or str." - ) - - def remove_namespace_from_tag(tag): """Helper function to remove the namespace from an XML tag.""" @@ -853,7 +771,7 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): and nxdl_elem.attrib["name"] == "NXdata" and hdf_node is not None and hdf_node.parent is not None - and decode_or_not(hdf_node.parent.attrs.get("NX_class")) == "NXdata" + and decode_string(hdf_node.parent.attrs.get("NX_class")) == "NXdata" ): (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) if fnd_child is not None: From 5976222438bd6bf54fdc38924a53987ac485cf2f Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:43:51 +0200 Subject: [PATCH 108/136] remove unneeded requirements # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- requirements.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 2ed3cbf1d..86ea4c21c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,7 +14,4 @@ pytest # Code style and auto-formatting black>=24.1.1 flake8>=4 -isort>=5.10 - -# String decoding -numpy \ No newline at end of file +isort>=5.10 \ No newline at end of file From fbdaf4737b5adf27f49d849fb369646e4ea66bc3 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:53:58 +0200 Subject: [PATCH 109/136] escape black check --- dev_tools/utils/nxdl_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index c1b50754a..ee22d12af 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -771,7 +771,8 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): and nxdl_elem.attrib["name"] == "NXdata" and hdf_node is not None and hdf_node.parent is not None - and decode_string(hdf_node.parent.attrs.get("NX_class")) == "NXdata" + and decode_string(hdf_node.parent.attrs.get("NX_class")) + == "NXdata" # noqa: F821 ): (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) if fnd_child is not None: From 97ce6ff39b25baff961c4b9e82e33611bb4b52a8 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:01:41 +0200 Subject: [PATCH 110/136] ignore flake8 issue --- dev_tools/utils/nxdl_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index ee22d12af..353aea9ba 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -771,8 +771,8 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): and nxdl_elem.attrib["name"] == "NXdata" and hdf_node is not None and hdf_node.parent is not None - and decode_string(hdf_node.parent.attrs.get("NX_class")) - == "NXdata" # noqa: F821 + and decode_string(hdf_node.parent.attrs.get("NX_class")) # noqa: F821 + == "NXdata" ): (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) if fnd_child is not None: From 49c67b51ed1b5906bcfd00c8027b9f158288134c Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:04:03 +0200 Subject: [PATCH 111/136] isort imports --- dev_tools/utils/nxdl_utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 353aea9ba..84b079e9c 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -7,7 +7,8 @@ from functools import lru_cache from glob import glob from pathlib import Path -from typing import List, Optional +from typing import List +from typing import Optional import lxml.etree as ET from lxml.etree import ParseError as xmlER From 0cc527326123c39005e3a6430fd93047e708843b Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 12 Sep 2024 08:48:29 +0200 Subject: [PATCH 112/136] use less strict version of str decoding --- dev_tools/utils/nxdl_utils.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 84b079e9c..18ecd48ba 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -9,11 +9,27 @@ from pathlib import Path from typing import List from typing import Optional +from typing import Union import lxml.etree as ET from lxml.etree import ParseError as xmlER +def decode_or_not(elem: Union[bytes, str]) -> str: + """Decodes a byte array to string if necessary""" + if isinstance(elem, bytes): + try: + return elem.decode("utf-8") + except UnicodeDecodeError as e: + raise ValueError(f"Error decoding bytes: {e}") + + elif isinstance(elem, str): + return elem + + else: + raise ValueError(f"Unsupported type {type(elem)}. Expected bytes, or str.") + + def remove_namespace_from_tag(tag): """Helper function to remove the namespace from an XML tag.""" @@ -772,7 +788,7 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): and nxdl_elem.attrib["name"] == "NXdata" and hdf_node is not None and hdf_node.parent is not None - and decode_string(hdf_node.parent.attrs.get("NX_class")) # noqa: F821 + and decode_or_not(hdf_node.parent.attrs.get("NX_class")) # noqa: F821 == "NXdata" ): (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) From 36d0ac945a4de31b8cf7fa0431b7539390cfd9fc Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:15:44 +0200 Subject: [PATCH 113/136] slightly enhanced version of str decoding, test # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 18ecd48ba..b68e60e6f 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -15,8 +15,15 @@ from lxml.etree import ParseError as xmlER -def decode_or_not(elem: Union[bytes, str]) -> str: +def decode_or_not(elem: Union[bytes, str], decode: bool = True) -> str: """Decodes a byte array to string if necessary""" + __error_msg = f"Unsupported type {type(elem)}. Expected bytes, or str." + if not decode: + # Return the initial value without decoding + if not isinstance(elem, (bytes, str)): + raise ValueError(__error_msg) + return elem + if isinstance(elem, bytes): try: return elem.decode("utf-8") @@ -27,7 +34,7 @@ def decode_or_not(elem: Union[bytes, str]) -> str: return elem else: - raise ValueError(f"Unsupported type {type(elem)}. Expected bytes, or str.") + raise ValueError(__error_msg) def remove_namespace_from_tag(tag): From 0162ec98c6ec333f0bffc47a62b259b9407d64ed Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:17:20 +0200 Subject: [PATCH 114/136] remove flake error catching --- dev_tools/utils/nxdl_utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index b68e60e6f..c0e1a0e19 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -795,8 +795,7 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): and nxdl_elem.attrib["name"] == "NXdata" and hdf_node is not None and hdf_node.parent is not None - and decode_or_not(hdf_node.parent.attrs.get("NX_class")) # noqa: F821 - == "NXdata" + and decode_or_not(hdf_node.parent.attrs.get("NX_class")) == "NXdata" ): (fnd_child, fit) = get_best_nxdata_child(nxdl_elem, hdf_node, hdf_name) if fnd_child is not None: From 663cd5472e75444eedb517f4143368ce905a7fef Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:34:51 +0200 Subject: [PATCH 115/136] remove strict type checking # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index c0e1a0e19..a11f11325 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -9,32 +9,38 @@ from pathlib import Path from typing import List from typing import Optional -from typing import Union import lxml.etree as ET from lxml.etree import ParseError as xmlER -def decode_or_not(elem: Union[bytes, str], decode: bool = True) -> str: - """Decodes a byte array to string if necessary""" - __error_msg = f"Unsupported type {type(elem)}. Expected bytes, or str." +def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): + """ + Decodes a byte array to a string if necessary. All other types are returned untouched. + If `decode` is False, the initial value is returned without decoding, including for byte arrays. + + Args: + elem: Any Python object that may need decoding. + encoding: The encoding scheme to use. Default is "utf-8". + decode: A boolean flag indicating whether to perform decoding. + + Returns: + A decoded string (in case of a byte string) or the initial value. + If `decode` is False, always returns the initial value. + + Raises: + ValueError: If a byte string cannot be decoded using the provided encoding. + """ if not decode: - # Return the initial value without decoding - if not isinstance(elem, (bytes, str)): - raise ValueError(__error_msg) return elem if isinstance(elem, bytes): try: - return elem.decode("utf-8") + return elem.decode(encoding) except UnicodeDecodeError as e: raise ValueError(f"Error decoding bytes: {e}") - elif isinstance(elem, str): - return elem - - else: - raise ValueError(__error_msg) + return elem def remove_namespace_from_tag(tag): From f2c6451e75fccc6f193fe7cd2c452de4de0086a9 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:33:22 +0200 Subject: [PATCH 116/136] add support for list of bytes # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index a11f11325..3abf139c3 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -34,6 +34,14 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): if not decode: return elem + # Handle lists of bytes or strings + elif isinstance(elem, list): + if not elem: + return elem # Return an empty list unchanged + + decoded_list = [decode_or_not(x, encoding, decode) for x in elem] + return decoded_list + if isinstance(elem, bytes): try: return elem.decode(encoding) From 3549fdf517d0211e8c801c6317131928fbd387a2 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:13:17 +0200 Subject: [PATCH 117/136] various small fixes are merging main and fairmat # Conflicts: # contributed_definitions/nyaml/NXdispersive_material.yaml # dev_tools/tests/test_nxdl_utils.py # manual/source/classes/contributed_definitions/mpes-structure.rst # manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst --- .../source/classes/contributed_definitions/em-structure.rst | 2 -- .../source/classes/contributed_definitions/mpes-structure.rst | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/manual/source/classes/contributed_definitions/em-structure.rst b/manual/source/classes/contributed_definitions/em-structure.rst index 6f011c62f..6b9008ae8 100644 --- a/manual/source/classes/contributed_definitions/em-structure.rst +++ b/manual/source/classes/contributed_definitions/em-structure.rst @@ -112,8 +112,6 @@ The following base classes are proposed to support modularizing the storage of p :ref:`NXstage_lab`: As it was mentioned for atom probe microscopy, this is a base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities which modern stages of electron microscopes frequently offer. -Method-specific concepts and their usage in application definitions -################################################################### It became clear during the design of the electron-microscopy-specific additions to NeXus that there are sets of pieces of information (data and metadata) which are relevant for a given experiment but have usually only few connections to the detailed description of the workflow of processing these data into knowledge, motivating the granularization of these pieces of information in their own application definition. In fact, one limitation of application definitions in NeXus is that they define a set of constraints on their graph of controlled concepts and terms. If we take for example diffraction experiments with an electron microscope it is usually the case that (diffraction) patterns are collected in the session at the microscope but all scientifically relevant conclusions are drawn later, i.e. through post-processing these data. These numerical and algorithmic steps define computational workflows where data from the application definitions such as NXem are used as input but many additional concepts and constraints may apply without any need for changing constraints on fields or groups of NXem. If we were to modify NXem for these cases, NXem would likely combinatorially diverge as every different combination of required constraints would demand having their own but almost similar application definition. For this reason, we propose to define the following base classes: diff --git a/manual/source/classes/contributed_definitions/mpes-structure.rst b/manual/source/classes/contributed_definitions/mpes-structure.rst index df89809bf..1d37fdba6 100644 --- a/manual/source/classes/contributed_definitions/mpes-structure.rst +++ b/manual/source/classes/contributed_definitions/mpes-structure.rst @@ -1,8 +1,8 @@ .. _Mpes-Structure: -======================================= +============================================== Photoemission & core-level spectroscopy -======================================= +============================================== .. index:: IntroductionMpes From 08a12a50a6cb9ebd5ceaa66d9decf9256d0f65ac Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:28:46 +0200 Subject: [PATCH 118/136] move doc bundles to applications and base_classes # Conflicts: # manual/source/classes/applications/apm-structure.rst # manual/source/classes/applications/em-structure.rst # manual/source/classes/applications/mpes-structure.rst # manual/source/classes/base_classes/apm-structure.rst # manual/source/classes/base_classes/em-structure.rst # manual/source/classes/base_classes/mpes-structure.rst --- dev_tools/docs/nxdl_index.py | 31 +++ .../classes/applications/apm-structure.rst | 207 ------------------ .../classes/applications/em-structure.rst | 73 ------ .../classes/applications/mpes-structure.rst | 37 ---- .../optical-spectroscopy-structure.rst | 199 +++++++++++++++++ .../classes/base_classes/apm-structure.rst | 187 ---------------- .../classes/base_classes/em-structure.rst | 73 ------ .../classes/base_classes/mpes-structure.rst | 51 ----- .../optical-spectroscopy-structure.rst | 199 +++++++++++++++++ 9 files changed, 429 insertions(+), 628 deletions(-) delete mode 100644 manual/source/classes/applications/apm-structure.rst delete mode 100644 manual/source/classes/applications/em-structure.rst delete mode 100644 manual/source/classes/applications/mpes-structure.rst create mode 100644 manual/source/classes/applications/optical-spectroscopy-structure.rst delete mode 100644 manual/source/classes/base_classes/apm-structure.rst delete mode 100644 manual/source/classes/base_classes/em-structure.rst delete mode 100644 manual/source/classes/base_classes/mpes-structure.rst create mode 100644 manual/source/classes/base_classes/optical-spectroscopy-structure.rst diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index e700c507a..e3f9c9371 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -66,6 +66,12 @@ def nxdl_indices() -> Dict[str, dict]: else: file = "" print("---------++++++++-", section) + if file.endswith(("applications/index.rst", "base_classes/index.rst")): + rst_lines.append(f"{indentation}em-structure\n") + rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") + rst_lines.append(f"{indentation}mpes-structure\n") + rst_lines.append(f"{indentation}apm-structure\n") + if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") @@ -113,6 +119,18 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: *might* be used in an instance of that class. Consider the base classes as a set of *components* that are used to construct a data file. + +Some contributions are grouped together: + :ref:`Optical Spectroscopy ` + + :ref:`Multi-dimensional Photoemission Spectroscopy ` + + :ref:`Atomprobe Microscopy ` + + :ref:`Electron Microscopy ` + +and others are simply listed here: + """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "applications": """ @@ -141,6 +159,19 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: In application definitions involving raw data, write the raw data in the :ref:`NXinstrument` tree and then link to it from the location(s) defined in the relevant application definition. + +Some contributions are grouped together: + :ref:`Optical Spectroscopy ` + + :ref:`Multi-dimensional Photoemission Spectroscopy ` + + :ref:`Atomprobe Microscopy ` + + :ref:`Electron Microscopy ` + + +and others are simply listed here: + """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "contributed_definitions": """ diff --git a/manual/source/classes/applications/apm-structure.rst b/manual/source/classes/applications/apm-structure.rst deleted file mode 100644 index bc99b4a7c..000000000 --- a/manual/source/classes/applications/apm-structure.rst +++ /dev/null @@ -1,207 +0,0 @@ -.. _Apm-Structure-APP: - -===================== -Atom-probe tomography -===================== - -.. index:: - IntroductionApm - ApmAppDef - ApmBC - StatusQuoApm - ApmParaprobeAppDef - ApmGermanNfdi - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS - - -.. _IntroductionApm-APP: - -Introduction -############ - -Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, -steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. -The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. - -.. _ApmAppDef-APP: - -Application Definition -###################### - - :ref:`NXapm`: - A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. The structure of the schema has been designed to also document a simulation of an atom probe - experiment. Having a combined schema for the measurement and the simulation is beneficial to document that - there are many similarities between the measurement and a computer simulation of it. - -.. _ApmBC-APP: - -Base Classes -############ - -The following base classes are proposed to support modularizing the storage of pieces of information: - - :ref:`NXchamber`: - A base class to describe a component of the instrument which houses other components. - A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities - for storing and loading specimens. - - :ref:`NXcoordinate_system_set`: - Base classes to describe different coordinate systems used and/or to be harmonized - or transformed into one another when interpreting the dataset. - - :ref:`NXion`: - A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. - For the usage in atom probe research the maximum number of atoms supported building a molecular ion - is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with - which all possible nuclides (stable, radioactive, or synthetically generated ones) can be described. - - :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about - a component or device of an instrument. - - :ref:`NXpeak`: (about to become complemented by NXpeak_fitting) - A base class to describe peaks mathematically to detail how peaks in - mass-to-charge-state ratio histograms (aka mass spectra) are defined and - labelled as iontypes. - - :ref:`NXpump`: - A base class to describe details about pump(s) used as components of an instrument. - - :ref:`NXpulser_apm`: - A base class to describe the high-voltage and/or laser pulsing capabilities. - - :ref:`NXreflectron`: - A base class to describe a kinetic-energy-sensitive filtering device - for time-of-flight (ToF) mass spectrometry. - - :ref:`NXstage_lab`: - A base class to describe the specimen fixture including the cryo-head. - Nowadays, stages of microscopes represent small-scale laboratory platforms. - Therefore, there is a need to define the characteristics of such stages in more detail, - especially in light of in-situ experiments. Many similarities exists between a stage - in an electron microscope and one in an atom probe instrument. Both offer fixture - functionalities and additional components for applying e.g. stimuli on the specimen. - -Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of -data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named -instances of the :ref:`NXprocess` base class. - - -These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented -to enable reproducible research, if possible even numerical reproducibility of the results, -and learn how pieces of information are connected. In what follows, an example is presented how an -open-source community software can be modified to use descriptions of these computational steps. - -A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe -data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: - - -The respective research software here is the `paraprobe-toolbox `_ -The software is developed by `M. Kühbach et al. `_. -For atom probe research the proposal can also serve as a blue print how computational steps of other software -tool including commercial ones could be developed further to benefit from NeXus. - -.. _IntroductionApmParaprobe-APP: - -apmtools -######## - -The paraprobe-toolbox is an example of an open-source parallelized software for analyzing -point cloud data, for assessing meshes in 3D continuum space, and for studying the effects of -parameterization on descriptors of micro- and nanoscale structural features (crystal defects) -within materials when characterized and studied with atom probe. - -The need for a thorough documentation of the tools in not only the paraprobe-toolbox -was motivated by several needs: - -First, users of software would like to better understand and also be able to study for themselves -which individual parameters and settings for each tool exist and how configuring these -affects analyses quantitatively. This stresses the aspect how to improve documentation. - -Second, scientific software like paraprobe-toolbox implement numerical/algorithmical -(computational) workflows whereby data coming from multiple input sources -(like previous analysis results) are processed and carried through more involved analyses -within several steps inside the tool. The tool then creates output as files. This -provenance and workflow should be documented. - -Individual tools of paraprobe-toolbox are developed in C/C++ and/or Python. -Provenance tracking is useful as it is one component and requirement for making -workflows exactly numerically reproducible and thus to enable reproducibility (the "R" -of the FAIR principles of data stewardship). - -For tools of the paraprobe-toolbox each workflow step is a pair or triple of sub-steps: -1. The creation of a configuration file. -2. The actual analysis using the Python/or C/C++ tools. -3. The optional analyses/visualization of the results based on data in NeXus/HDF5 files generated by each tool. - -.. _StatusQuoApm-APP: - -What has been achieved so far? -############################## - -This proposal summarizes work of members of the FAIRmat project, which is part of the `German -National Research Data Infrastructure `_. The here detailed -proposal documents how all tools of the paraprobe-toolbox were modified to generate -only well-defined configuration files as accepted input and yield specifically formatted output -files according to the following NeXus application definitions. - -Data and metadata between the tools are exchanged with NeXus/HDF5 files. This means that data -inside HDF5 binary containers are named, formatted, and hierarchically structured according -to application definitions. - -For example the application definition NXapm_paraprobe_config_surfacer specifies -how a configuration file for the paraprobe-surfacer tool should be formatted -and which parameters it contains including optionality and cardinality constraints. - -Thereby, each config file uses a controlled vocabulary of terms. Furthermore, -the config files store a SHA256 checksum for each input file. This implements a full -provenance tracking on the input files along the workflow. - -As an example, a user may first range their reconstruction and then compute spatial -correlation functions. The config file for the ranging tool stores the files -which hold the reconstructed ion position and ranging definitions. -The ranging tool generates a results file with the labels of each molecular ion. -This results file is formatted according to the tool-specific `results` -application definition. The generated results file and the reconstruction is -imported by the spatial statistics tool which again keeps track of all files -and reports its results in a spatial statistics tool results file. - -This design makes it possible to rigorously trace which numerical results were achieved -with specific inputs and settings using specifically-versioned tools. Noteworthy -this includes Y-junction on a graph which is where multiple input sources are -combined to generate new results. - -We are convinced that defining, documenting, using, and sharing application definitions -is useful and future-proof strategy for software development and data analyses as it enables -automated provenance tracking which happens silently in the background. - -Base classes have been defined to group common pieces of information for each tool of the -toolbox. For each tool we define a pair of base classes. One for the configuration (input) side -and one for the results (output) side: - - -.. _ApmParaprobeAppDef-APP: - -Application Definitions -####################### - -NXapm_paraprobe application definitions are in fact pairs of application definitions. -One for the configuration (input) side and one for the results (output) side. For each -tool one such pair is proposed: - - -.. _ApmGermanNfdi-APP: - -Joint work German NFDI consortia NFDI-MatWerk and FAIRmat -####################################################################### - -Members of the NFDI-MatWerk and the FAIRmat consortium of the German National Research Data Infrastructure -are working together within the Infrastructure Use Case IUC09 of the NFDI-MatWerk project to work on examples -how software tools in both consortia become better documented and interoperable to use. Within this project, -we have also added the `CompositionSpace tool that has been developed at the Max-Planck-Institut für Eisenforschung -GmbH in Düsseldorf `_ by A. Saxena et al. - -Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: - diff --git a/manual/source/classes/applications/em-structure.rst b/manual/source/classes/applications/em-structure.rst deleted file mode 100644 index 045fcdbb3..000000000 --- a/manual/source/classes/applications/em-structure.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _Em-Structure-APP: - -=================== -Electron microscopy -=================== - -.. index:: - IntroductionEm - EmAppDef - EmBC - EmAnalysisClasses - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS - - -.. _IntroductionEm-APP: - -Introduction -############ - -A set of data schemas is proposed to describe components of an electron microscope and its eventually available focused-ion beam functionalities. -The data schemas were designed from the perspective of how electron microscopes are used by colleagues in the materials-science-branch of electron microscopy. -We realize that the biology-/bio-materials/omics-branch of electron microscopy is eventually in an already more mature state of discussion with respect -to data management practices. In what follows, the focus is on the usage of electron microscopy in condensed-matter physics, chemical physics of solids, -and materials engineering applications. As many of the components of electron microscopes used in the bio-materials communities are the same or at least many -components are very similar, it is likely that the here presented schema definitions can also inspire discussion and exchange with the bio-materials community. -Partner consortia in the German National Research Data Infrastructure are here e.g. NFDI-BioImage, NFDI-Microbiota, NFDI4Health, and e.g. NFDI-Neuro. - -Electron microscopes are functionally very customizable tools: Examples include multi-signal/-modal analyses which are frequently realized as on-the-fly computational analyses, regularly switching between GUI-based instrument control, computational steps, and more and more using high-throughput stream-based processing. Also artificial intelligence methods are increasingly used and are becoming more closely interconnected with classical modes of controlling the instrument and perform data processing. A challenge in electron microscopy is that these steps are often executed within commercial integrated control and analysis software. This makes it difficult to keep track of workflows in a technology-partner-agnostic, i.e. interdisciplinary manner. - -.. _EmAppDef-APP: - -Application Definitions -####################### - -We acknowledge that it can be difficult to agree on a single application definition which is generally enough applicable yet not unnecessarily complex and useful for applications across a variety of instruments, technology partners, and instrument use cases. In what follows, the proposal conceptualizes first the basic components of an electron microscope and the usual workflow of how an electron microscope is used for collecting data with detectors via probing radiation-specimen-matter interaction mechanisms. - -In summary, scientists place a specimen/sample into the microscope, calibrate the instrument, take measurements, and may perform experiments, prepare their specimens with a focused ion beam, calibrate again, and take other measurements, before their session on the instrument ends. In between virtually all of these steps data are collected and stream in from different detectors probing different physical mechanisms of the interaction between electrons or other types of radiation with the specimen. - -A microscope session ends with the scientist removing the specimen from the instrument or parking it so that the next user can start a session. Occasionally, service technicians perform calibrations and maintenance which also can be described as a session on the microscope. We have provided base classes to describe these steps and events and an application definition for electron microscopy: - - :ref:`NXem`: - An application definition which explores the possibilities of electron microscopes. - - -.. _EmBC-APP: - -Base Classes -############ - -The following base classes are proposed to support modularizing the storage of pieces of information related to electron microscopy research: - - - -.. _EmAnalysisClasses-APP: - -We provide specific base classes which granularize frequently collected or analyzed quantities in specific application fields of electron microscopy to deal -with the situation that there are cases were logical connections between generated data artifacts mainly exist for the fact that the data artifacts were -collected during a workflow of electron microscopy research (e.g. taking measurements and then performing method-specific analyses generating new data and conclusions). -We see a value in granularizing out these pieces of information into own classes. In fact, one limitation of application definitions in NeXus, exactly as it applies for serialization -of information also more generally, is currently that they define a set of constraints on their graph of controlled concepts and terms. - -If we take for example diffraction experiments performed with an electron microscope, it is usually the case that (diffraction) patterns are collected in the session at the microscope. -However, all scientifically relevant conclusions are typically drawn later, i.e. through post-processing the collected diffraction (raw) data. These numerical and algorithmic steps -define computational workflows were data from an instance of an application definition such as NXem are used as input but many additional concepts, constraints, and assumptions -are applied without that these demand necessarily changes in the constraints on fields or groups of NXem. If we were to modify NXem for these cases, -NXem would combinatorially diverge as every different combination of required constraints demands having an own but almost similar application definition. -For this reason, method-specific base classes are used which granularize out how specific pieces of information are processed further to eventually enable their -storage (i.e. serialization) using NeXus. - -More consolidation through the use of NXsubentry classes should be considered in the future. For now we use an approach whereby base classes are combined to reuse vocabulary and a hierarchical organization of pieces of information with specific constraints which are relevant only for specific usage of such data by specific tools used by an eventually smaller circle of users. - diff --git a/manual/source/classes/applications/mpes-structure.rst b/manual/source/classes/applications/mpes-structure.rst deleted file mode 100644 index ee2c29b92..000000000 --- a/manual/source/classes/applications/mpes-structure.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. _Mpes-Structure-APP: - -======================================= -Photoemission & core-level spectroscopy -======================================= - -.. index:: - IntroductionMpes - MpesAppDef - MpesBC - MpesCommonBC - MpesExtendedBC - - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF APPLICATION DEFINITIONS - - -. _IntroductionMpes-APP: - -Introduction -############ - -Set of data storage objects to describe multidimensional photoemission (MPES) experiments including x-ray photoelectron spectroscopy (XPS), ultraviolet photoelectron spectroscopy (UPS), -hard x-ray photoelectron spectroscopy (HAXPES), angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) -and photoemission electron microscopy (PEEM). Also includes descriptors for advanced specializations, such as spin-resolution, time resolution, -near-ambient pressure conditions, dichroism etc. - -.. _MpesAppDef-APP: - -Application Definitions -####################### - -:ref:`NXmpes`: - A general application definition with minimalistic metadata requirements, apt to describe all photoemission experiments. - - diff --git a/manual/source/classes/applications/optical-spectroscopy-structure.rst b/manual/source/classes/applications/optical-spectroscopy-structure.rst new file mode 100644 index 000000000..b9f5e11c1 --- /dev/null +++ b/manual/source/classes/applications/optical-spectroscopy-structure.rst @@ -0,0 +1,199 @@ +.. _Optical-Spectroscopy-Structure-APP: + +==================== +Optical Spectroscopy +==================== + +.. index:: + Ellipsometry + Raman + DispersiveMaterial + + +.. _Ellipsometry-APP: + +Ellipsometry +############ + +Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. +The measurements are based on determining how the polarization state of light changes upon transmission and reflection. +Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. + +In the application definition, we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. + +.. _Raman-APP: + +Raman +############ + +Raman spectroscopy is a characterization method to analyze vibrational properties for liquids, gases, or solids. +The measurements is based on the inelastic light scattering due to the material's vibrations. +Interpretation can be done based on peaks, which represent the phonon properties (intensity, center, width). + +The application definition contains a minimum of descriptive elements required to understand Raman spectroscopy measurements. + + +Application Definitions +----------------------- + + :ref:`NXoptical_spectroscopy`: + A generic application definition for spectroscopy measurements. This includes in particular ellipsometry and Raman spectroscopy measurements, but also other techniques such as photoluminescence, transmission, and reflection measurements. The requirements are: (i) an incident photon beam, (ii) a detector to measure scattered/emitted photons, and (iii) a sample. + + :ref:`NXellipsometry`: + An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. + + :ref:`NXraman`: + An application definition for Raman spectroscopy measurements. + + +Base Classes +------------ + +This is the set of base classes for describing an optical experiment. + + :ref:`NXbeam_device` + Beam devices are used to relate a beam, which has always at least one origin + and at least one destination. + + By referencing the beam devices with each other, a beam path can be + constructed. This can be used for vizualization or beam propery modeling + along the beam path. + + :ref:`NXbeam` + Beam properties such as intensity, polarization, wavelength or direction. + + :ref:`NXdetector` + A detector for signal detection. + + :ref:`NXsource` + A light source such as laser, lamp or LED. + + :ref:`NXmonochromator` + A monochromator is often used to energetically disperse the scattered or emitted light. + + :ref:`NXlens_opt` + Description of an optical lens. + + :ref:`NXwaveplate` + A waveplate or retarder. + + :ref:`NXsensor` + Specify external parameters that have influenced the sample such as + varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. + + + +.. _DispersiveMaterial-APP: + +Dispersive Material +################### + +A dispersive material is a description for the optical dispersion of materials. +This description may be used to store optical model data from an ellipsometric analysis +(or any other technique) or to build a database of optical constants for optical properties of materials. + +Application Definition +---------------------- + + :ref:`NXdispersive_material`: + An application definition to describe the dispersive properties of a material. + The material may be isotropic, uniaxial or biaxial. Hence, it may contain up + to three dispersive functions or tables. + + + +Base Classes +------------ + +There is a set of base classes for describing a dispersion. + + :ref:`NXdispersion` + This is an umbrella base class for a group of dispersion functions to describe the material. + For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. + If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. + This allows for, e.g. splitting real and imaginary parts and describing them seperately or + adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). + + :ref:`NXdispersion_function` + This dispersion is described by a function and its single and repeated parameter values. + It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` + (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. + + :ref:`NXdispersion_single_parameter` + This denotes a parameter which is used outside the summed part of a dispersion function, + e.g. ``eps_inf`` in the formula example above. + + :ref:`NXdispersion_repeated_parameter` + This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. + ``A`` and ``B`` are repeated parameters in the formula above. + + :ref:`NXdispersion_table` + This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. + +Formula Grammar +--------------- + +Below you find a grammar to which the formula should adhere and which can be used to parse and +evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be +filled with the respective single and repeated params from the stored data. +The grammer is written in the `EBNF `_ dialect +of `Lark `_, which is a parsing toolkit for python. +It is easily translatable to general EBNF and other parser generator dialects. +`Here `_ is a reference implementation in Rust/Python with a +`grammar `_ +written in `lalrpop `_. + +.. code-block:: + + ?assignment: "eps" "=" kkr_expression -> eps + | "n" "=" kkr_expression -> n + + ?kkr_expression: expression + | "" "+" "1j" "*" term -> kkr_term + + ?expression: term + | expression "+" term -> add + | expression "-" term -> sub + + ?term: factor + | term "*" factor -> mul + | term "/" factor -> div + + ?factor: power + | power "**" power -> power + + + ?power: "(" expression ")" + | FUNC "(" expression ")" -> func + | "sum" "[" repeated_expression "]" -> sum_expr + | NAME -> single_param_name + | SIGNED_NUMBER -> number + | BUILTIN -> builtin + + ?repeated_expression: repeated_term + | repeated_expression "+" repeated_term -> add + | repeated_expression "-" repeated_term -> sub + + + ?repeated_term: repeated_factor + | repeated_term "*" repeated_factor -> mul + | repeated_term "/" repeated_factor -> div + + ?repeated_factor: repeated_power + | repeated_power "**" repeated_power -> power + + ?repeated_power: "(" repeated_expression ")" + | FUNC "(" repeated_expression ")" -> func + | SIGNED_NUMBER -> number + | NAME -> param_name + | BUILTIN -> builtin + + FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" + BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" + + %import common.CNAME -> NAME + %import common.SIGNED_NUMBER + %import common.WS_INLINE + + %ignore WS_INLINE + diff --git a/manual/source/classes/base_classes/apm-structure.rst b/manual/source/classes/base_classes/apm-structure.rst deleted file mode 100644 index c66f42420..000000000 --- a/manual/source/classes/base_classes/apm-structure.rst +++ /dev/null @@ -1,187 +0,0 @@ -.. _Apm-Structure-BC: - -===================== -Atom-probe tomography -===================== - -.. index:: - IntroductionApm - ApmAppDef - ApmBC - StatusQuoApm - ApmParaprobeAppDef - ApmGermanNfdi - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES - - -.. _IntroductionApm-BC: - -Introduction -############ - -Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, -steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. -The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. - -.. _ApmAppDef-BC: - -Application Definition -###################### - - :ref:`NXapm`: - A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. The structure of the schema has been designed to also document a simulation of an atom probe - experiment. Having a combined schema for the measurement and the simulation is beneficial to document that - there are many similarities between the measurement and a computer simulation of it. - -.. _ApmBC-BC: - -Base Classes -############ - -The following base classes are proposed to support modularizing the storage of pieces of information: - - :ref:`NXchamber`: - A base class to describe a component of the instrument which houses other components. - A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities - for storing and loading specimens. - - :ref:`NXcoordinate_system_set`: - Base classes to describe different coordinate systems used and/or to be harmonized - or transformed into one another when interpreting the dataset. - - :ref:`NXion`: - A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. - For the usage in atom probe research the maximum number of atoms supported building a molecular ion - is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with - which all possible nuclides (stable, radioactive, or synthetically generated ones) can be described. - - :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about - a component or device of an instrument. - - -Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of -data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named -instances of the :ref:`NXprocess` base class. - -Several base classes were defined to document processing of atom probe data with established algorithms: - - -These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented -to enable reproducible research, if possible even numerical reproducibility of the results, -and learn how pieces of information are connected. In what follows, an example is presented how an -open-source community software can be modified to use descriptions of these computational steps. - -A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe -data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: - - -The respective research software here is the `paraprobe-toolbox `_ -The software is developed by `M. Kühbach et al. `_. -For atom probe research the proposal can also serve as a blue print how computational steps of other software -tool including commercial ones could be developed further to benefit from NeXus. - -.. _IntroductionApmParaprobe-BC: - -apmtools -######## - -The paraprobe-toolbox is an example of an open-source parallelized software for analyzing -point cloud data, for assessing meshes in 3D continuum space, and for studying the effects of -parameterization on descriptors of micro- and nanoscale structural features (crystal defects) -within materials when characterized and studied with atom probe. - -The need for a thorough documentation of the tools in not only the paraprobe-toolbox -was motivated by several needs: - -First, users of software would like to better understand and also be able to study for themselves -which individual parameters and settings for each tool exist and how configuring these -affects analyses quantitatively. This stresses the aspect how to improve documentation. - -Second, scientific software like paraprobe-toolbox implement numerical/algorithmical -(computational) workflows whereby data coming from multiple input sources -(like previous analysis results) are processed and carried through more involved analyses -within several steps inside the tool. The tool then creates output as files. This -provenance and workflow should be documented. - -Individual tools of paraprobe-toolbox are developed in C/C++ and/or Python. -Provenance tracking is useful as it is one component and requirement for making -workflows exactly numerically reproducible and thus to enable reproducibility (the "R" -of the FAIR principles of data stewardship). - -For tools of the paraprobe-toolbox each workflow step is a pair or triple of sub-steps: -1. The creation of a configuration file. -2. The actual analysis using the Python/or C/C++ tools. -3. The optional analyses/visualization of the results based on data in NeXus/HDF5 files generated by each tool. - -.. _StatusQuoApm-BC: - -What has been achieved so far? -############################## - -This proposal summarizes work of members of the FAIRmat project, which is part of the `German -National Research Data Infrastructure `_. The here detailed -proposal documents how all tools of the paraprobe-toolbox were modified to generate -only well-defined configuration files as accepted input and yield specifically formatted output -files according to the following NeXus application definitions. - -Data and metadata between the tools are exchanged with NeXus/HDF5 files. This means that data -inside HDF5 binary containers are named, formatted, and hierarchically structured according -to application definitions. - -For example the application definition NXapm_paraprobe_config_surfacer specifies -how a configuration file for the paraprobe-surfacer tool should be formatted -and which parameters it contains including optionality and cardinality constraints. - -Thereby, each config file uses a controlled vocabulary of terms. Furthermore, -the config files store a SHA256 checksum for each input file. This implements a full -provenance tracking on the input files along the workflow. - -As an example, a user may first range their reconstruction and then compute spatial -correlation functions. The config file for the ranging tool stores the files -which hold the reconstructed ion position and ranging definitions. -The ranging tool generates a results file with the labels of each molecular ion. -This results file is formatted according to the tool-specific `results` -application definition. The generated results file and the reconstruction is -imported by the spatial statistics tool which again keeps track of all files -and reports its results in a spatial statistics tool results file. - -This design makes it possible to rigorously trace which numerical results were achieved -with specific inputs and settings using specifically-versioned tools. Noteworthy -this includes Y-junction on a graph which is where multiple input sources are -combined to generate new results. - -We are convinced that defining, documenting, using, and sharing application definitions -is useful and future-proof strategy for software development and data analyses as it enables -automated provenance tracking which happens silently in the background. - -Base classes have been defined to group common pieces of information for each tool of the -toolbox. For each tool we define a pair of base classes. One for the configuration (input) side -and one for the results (output) side: - - -.. _ApmParaprobeAppDef-BC: - -Application Definitions -####################### - -NXapm_paraprobe application definitions are in fact pairs of application definitions. -One for the configuration (input) side and one for the results (output) side. For each -tool one such pair is proposed: - - -.. _ApmGermanNfdi-BC: - -Joint work German NFDI consortia NFDI-MatWerk and FAIRmat -####################################################################### - -Members of the NFDI-MatWerk and the FAIRmat consortium of the German National Research Data Infrastructure -are working together within the Infrastructure Use Case IUC09 of the NFDI-MatWerk project to work on examples -how software tools in both consortia become better documented and interoperable to use. Within this project, -we have also added the `CompositionSpace tool that has been developed at the Max-Planck-Institut für Eisenforschung -GmbH in Düsseldorf `_ by A. Saxena et al. - -Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: - diff --git a/manual/source/classes/base_classes/em-structure.rst b/manual/source/classes/base_classes/em-structure.rst deleted file mode 100644 index 167c9c6ff..000000000 --- a/manual/source/classes/base_classes/em-structure.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _Em-Structure-BC: - -=================== -Electron microscopy -=================== - -.. index:: - IntroductionEm - EmAppDef - EmBC - EmAnalysisClasses - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES - - -.. _IntroductionEm-BC: - -Introduction -############ - -A set of data schemas is proposed to describe components of an electron microscope and its eventually available focused-ion beam functionalities. -The data schemas were designed from the perspective of how electron microscopes are used by colleagues in the materials-science-branch of electron microscopy. -We realize that the biology-/bio-materials/omics-branch of electron microscopy is eventually in an already more mature state of discussion with respect -to data management practices. In what follows, the focus is on the usage of electron microscopy in condensed-matter physics, chemical physics of solids, -and materials engineering applications. As many of the components of electron microscopes used in the bio-materials communities are the same or at least many -components are very similar, it is likely that the here presented schema definitions can also inspire discussion and exchange with the bio-materials community. -Partner consortia in the German National Research Data Infrastructure are here e.g. NFDI-BioImage, NFDI-Microbiota, NFDI4Health, and e.g. NFDI-Neuro. - -Electron microscopes are functionally very customizable tools: Examples include multi-signal/-modal analyses which are frequently realized as on-the-fly computational analyses, regularly switching between GUI-based instrument control, computational steps, and more and more using high-throughput stream-based processing. Also artificial intelligence methods are increasingly used and are becoming more closely interconnected with classical modes of controlling the instrument and perform data processing. A challenge in electron microscopy is that these steps are often executed within commercial integrated control and analysis software. This makes it difficult to keep track of workflows in a technology-partner-agnostic, i.e. interdisciplinary manner. - -.. _EmAppDef-BC: - -Application Definitions -####################### - -We acknowledge that it can be difficult to agree on a single application definition which is generally enough applicable yet not unnecessarily complex and useful for applications across a variety of instruments, technology partners, and instrument use cases. In what follows, the proposal conceptualizes first the basic components of an electron microscope and the usual workflow of how an electron microscope is used for collecting data with detectors via probing radiation-specimen-matter interaction mechanisms. - -In summary, scientists place a specimen/sample into the microscope, calibrate the instrument, take measurements, and may perform experiments, prepare their specimens with a focused ion beam, calibrate again, and take other measurements, before their session on the instrument ends. In between virtually all of these steps data are collected and stream in from different detectors probing different physical mechanisms of the interaction between electrons or other types of radiation with the specimen. - -A microscope session ends with the scientist removing the specimen from the instrument or parking it so that the next user can start a session. Occasionally, service technicians perform calibrations and maintenance which also can be described as a session on the microscope. We have provided base classes to describe these steps and events and an application definition for electron microscopy: - - :ref:`NXem`: - An application definition which explores the possibilities of electron microscopes. - - -.. _EmBC-BC: - -Base Classes -############ - -The following base classes are proposed to support modularizing the storage of pieces of information related to electron microscopy research: - - - -.. _EmAnalysisClasses-BC: - -We provide specific base classes which granularize frequently collected or analyzed quantities in specific application fields of electron microscopy to deal -with the situation that there are cases were logical connections between generated data artifacts mainly exist for the fact that the data artifacts were -collected during a workflow of electron microscopy research (e.g. taking measurements and then performing method-specific analyses generating new data and conclusions). -We see a value in granularizing out these pieces of information into own classes. In fact, one limitation of application definitions in NeXus, exactly as it applies for serialization -of information also more generally, is currently that they define a set of constraints on their graph of controlled concepts and terms. - -If we take for example diffraction experiments performed with an electron microscope, it is usually the case that (diffraction) patterns are collected in the session at the microscope. -However, all scientifically relevant conclusions are typically drawn later, i.e. through post-processing the collected diffraction (raw) data. These numerical and algorithmic steps -define computational workflows were data from an instance of an application definition such as NXem are used as input but many additional concepts, constraints, and assumptions -are applied without that these demand necessarily changes in the constraints on fields or groups of NXem. If we were to modify NXem for these cases, -NXem would combinatorially diverge as every different combination of required constraints demands having an own but almost similar application definition. -For this reason, method-specific base classes are used which granularize out how specific pieces of information are processed further to eventually enable their -storage (i.e. serialization) using NeXus. - -More consolidation through the use of NXsubentry classes should be considered in the future. For now we use an approach whereby base classes are combined to reuse vocabulary and a hierarchical organization of pieces of information with specific constraints which are relevant only for specific usage of such data by specific tools used by an eventually smaller circle of users. - diff --git a/manual/source/classes/base_classes/mpes-structure.rst b/manual/source/classes/base_classes/mpes-structure.rst deleted file mode 100644 index 910d09331..000000000 --- a/manual/source/classes/base_classes/mpes-structure.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. _Mpes-Structure-BC: - -======================================= -Photoemission & core-level spectroscopy -======================================= - -.. index:: - IntroductionMpes - MpesAppDef - MpesBC - MpesCommonBC - MpesExtendedBC - - - -EXAMPLE FOR DOCUMENTATION OF A GROUP OF BASE CLASSES - - -.. _IntroductionMpes-BC: - -Introduction -############ - -Set of data storage objects to describe multidimensional photoemission (MPES) experiments including x-ray photoelectron spectroscopy (XPS), ultraviolet photoelectron spectroscopy (UPS), -hard x-ray photoelectron spectroscopy (HAXPES), angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) -and photoemission electron microscopy (PEEM). Also includes descriptors for advanced specializations, such as spin-resolution, time resolution, -near-ambient pressure conditions, dichroism etc. - -.. _MpesBC-BC: - -Base Classes -############ - -:ref:`NXelectronanalyser`: - A base class to describe electron kinetic energy analizers. Contains the collective characteristics of the instrument such as energy resolution, and includes the following subclasses: - - :ref:`NXcollectioncolumn`: - Base class to describe the set of electronic lenses in the electron collection column (standard, PEEM, momentum-microscope, etc.). - - - -Four base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: - - -.. _MpesCommonBC-BC: - -Common Base Classes -################### - -There are related base classes that are common to other techniques: - diff --git a/manual/source/classes/base_classes/optical-spectroscopy-structure.rst b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst new file mode 100644 index 000000000..cf610fc21 --- /dev/null +++ b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst @@ -0,0 +1,199 @@ +.. _Optical-Spectroscopy-Structure-BC: + +==================== +Optical Spectroscopy +==================== + +.. index:: + Ellipsometry + Raman + DispersiveMaterial + + +.. _Ellipsometry-BC: + +Ellipsometry +############ + +Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. +The measurements are based on determining how the polarization state of light changes upon transmission and reflection. +Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. + +In the application definition, we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. + +.. _Raman-BC: + +Raman +############ + +Raman spectroscopy is a characterization method to analyze vibrational properties for liquids, gases, or solids. +The measurements is based on the inelastic light scattering due to the material's vibrations. +Interpretation can be done based on peaks, which represent the phonon properties (intensity, center, width). + +The application definition contains a minimum of descriptive elements required to understand Raman spectroscopy measurements. + + +Application Definitions +----------------------- + + :ref:`NXoptical_spectroscopy`: + A generic application definition for spectroscopy measurements. This includes in particular ellipsometry and Raman spectroscopy measurements, but also other techniques such as photoluminescence, transmission, and reflection measurements. The requirements are: (i) an incident photon beam, (ii) a detector to measure scattered/emitted photons, and (iii) a sample. + + :ref:`NXellipsometry`: + An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. + + :ref:`NXraman`: + An application definition for Raman spectroscopy measurements. + + +Base Classes +------------ + +This is the set of base classes for describing an optical experiment. + + :ref:`NXbeam_device` + Beam devices are used to relate a beam, which has always at least one origin + and at least one destination. + + By referencing the beam devices with each other, a beam path can be + constructed. This can be used for vizualization or beam propery modeling + along the beam path. + + :ref:`NXbeam` + Beam properties such as intensity, polarization, wavelength or direction. + + :ref:`NXdetector` + A detector for signal detection. + + :ref:`NXsource` + A light source such as laser, lamp or LED. + + :ref:`NXmonochromator` + A monochromator is often used to energetically disperse the scattered or emitted light. + + :ref:`NXlens_opt` + Description of an optical lens. + + :ref:`NXwaveplate` + A waveplate or retarder. + + :ref:`NXsensor` + Specify external parameters that have influenced the sample such as + varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. + + + +.. _DispersiveMaterial-BC: + +Dispersive Material +################### + +A dispersive material is a description for the optical dispersion of materials. +This description may be used to store optical model data from an ellipsometric analysis +(or any other technique) or to build a database of optical constants for optical properties of materials. + +Application Definition +---------------------- + + :ref:`NXdispersive_material`: + An application definition to describe the dispersive properties of a material. + The material may be isotropic, uniaxial or biaxial. Hence, it may contain up + to three dispersive functions or tables. + + + +Base Classes +------------ + +There is a set of base classes for describing a dispersion. + + :ref:`NXdispersion` + This is an umbrella base class for a group of dispersion functions to describe the material. + For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. + If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. + This allows for, e.g. splitting real and imaginary parts and describing them seperately or + adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). + + :ref:`NXdispersion_function` + This dispersion is described by a function and its single and repeated parameter values. + It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` + (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. + + :ref:`NXdispersion_single_parameter` + This denotes a parameter which is used outside the summed part of a dispersion function, + e.g. ``eps_inf`` in the formula example above. + + :ref:`NXdispersion_repeated_parameter` + This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. + ``A`` and ``B`` are repeated parameters in the formula above. + + :ref:`NXdispersion_table` + This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. + +Formula Grammar +--------------- + +Below you find a grammar to which the formula should adhere and which can be used to parse and +evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be +filled with the respective single and repeated params from the stored data. +The grammer is written in the `EBNF `_ dialect +of `Lark `_, which is a parsing toolkit for python. +It is easily translatable to general EBNF and other parser generator dialects. +`Here `_ is a reference implementation in Rust/Python with a +`grammar `_ +written in `lalrpop `_. + +.. code-block:: + + ?assignment: "eps" "=" kkr_expression -> eps + | "n" "=" kkr_expression -> n + + ?kkr_expression: expression + | "" "+" "1j" "*" term -> kkr_term + + ?expression: term + | expression "+" term -> add + | expression "-" term -> sub + + ?term: factor + | term "*" factor -> mul + | term "/" factor -> div + + ?factor: power + | power "**" power -> power + + + ?power: "(" expression ")" + | FUNC "(" expression ")" -> func + | "sum" "[" repeated_expression "]" -> sum_expr + | NAME -> single_param_name + | SIGNED_NUMBER -> number + | BUILTIN -> builtin + + ?repeated_expression: repeated_term + | repeated_expression "+" repeated_term -> add + | repeated_expression "-" repeated_term -> sub + + + ?repeated_term: repeated_factor + | repeated_term "*" repeated_factor -> mul + | repeated_term "/" repeated_factor -> div + + ?repeated_factor: repeated_power + | repeated_power "**" repeated_power -> power + + ?repeated_power: "(" repeated_expression ")" + | FUNC "(" repeated_expression ")" -> func + | SIGNED_NUMBER -> number + | NAME -> param_name + | BUILTIN -> builtin + + FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" + BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" + + %import common.CNAME -> NAME + %import common.SIGNED_NUMBER + %import common.WS_INLINE + + %ignore WS_INLINE + From f2ede8ee7101d8e34d319c5eb8313e0bb38ddb17 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:28:41 +0200 Subject: [PATCH 119/136] remove fairmat-specific files # Conflicts: # .github/workflows/ci.yaml # manual/source/img/FAIRmat_new.png --- .github/workflows/ci.yaml | 4 ++-- dev_tools/globals/urls.py | 2 +- manual/source/icme-structure.rst | 9 --------- manual/source/img/FAIRmat_new.png | Bin 24990 -> 0 bytes manual/source/img/FAIRmat_new_with_text.png | Bin 29306 -> 0 bytes requirements.txt | 2 +- 6 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 manual/source/icme-structure.rst delete mode 100644 manual/source/img/FAIRmat_new.png delete mode 100644 manual/source/img/FAIRmat_new_with_text.png diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 489cac82a..4da534ddf 100755 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,10 +3,10 @@ name: Documentation build on: push: branches: - - fairmat # push commit to the fairmat branch + - main # push commit to the main branch pull_request: branches: - - fairmat # pull request to the fairmat branch + - main # pull request to the main branch workflow_dispatch: # allow manual triggering inputs: deploy: diff --git a/dev_tools/globals/urls.py b/dev_tools/globals/urls.py index 2929070cc..729b7d102 100644 --- a/dev_tools/globals/urls.py +++ b/dev_tools/globals/urls.py @@ -1,2 +1,2 @@ -REPO_URL = "https://github.com/FAIRmat-NFDI/nexus_definitions/tree/fairmat" +REPO_URL = "https://github.com/nexusformat/definitions/blob/main" MANUAL_URL = "https://manual.nexusformat.org" diff --git a/manual/source/icme-structure.rst b/manual/source/icme-structure.rst deleted file mode 100644 index 8ff31eaf7..000000000 --- a/manual/source/icme-structure.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _Icme-Structure-Fairmat: - -============================================== -Integrated Computational Materials Engineering -============================================== - -With a large set of data schemas for computational geometry, and methods from condensed-matter physics as well as materials engineering we are convinced that the NeXus standardization framework can be one component of efforts to harmonize and consolidate the zoo of descriptions and data schemas used within the field of Integrated Computational Materials Engineering (ICME). - -A status report along these lines of thoughts and ongoing efforts is available here: :ref:`Icme-Structure`. diff --git a/manual/source/img/FAIRmat_new.png b/manual/source/img/FAIRmat_new.png deleted file mode 100644 index eeddabe3400c469ed1619f50d834533d2afc0303..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24990 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 diff --git a/requirements.txt b/requirements.txt index 86ea4c21c..b274b11d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,6 @@ sphinx-toolbox pytest # Code style and auto-formatting -black>=24.1.1 +black>=22.3 flake8>=4 isort>=5.10 \ No newline at end of file From e299df47b3b652e4f3fabb449994cd18ef3e6b28 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:51:40 +0200 Subject: [PATCH 120/136] pull out modifications for fairmat-2024-dev-tools-and-manual # Conflicts: # base_classes/NXaperture.nxdl.xml # base_classes/NXapm_sim.nxdl.xml # base_classes/NXfit_parameter.nxdl.xml # base_classes/NXroi.nxdl.xml # contributed_definitions/NXcg_primitive_set.nxdl.xml # contributed_definitions/NXcoordinate_system.nxdl.xml # contributed_definitions/NXcrystal_structure.nxdl.xml # contributed_definitions/NXcs_io_sys.nxdl.xml # contributed_definitions/NXcs_mm_obj.nxdl.xml # contributed_definitions/NXelectronanalyser.nxdl.xml # contributed_definitions/NXem_adf.nxdl.xml # contributed_definitions/NXem_correlation.nxdl.xml # contributed_definitions/NXem_eels.nxdl.xml # contributed_definitions/NXem_msr.nxdl.xml # contributed_definitions/NXevent_data_em_set.nxdl.xml # contributed_definitions/NXfabrication.nxdl.xml # contributed_definitions/NXinteraction_vol_em.nxdl.xml # contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml # contributed_definitions/NXmicrostructure_imm_results.nxdl.xml # contributed_definitions/NXms_mtex_config.nxdl.xml # contributed_definitions/NXms_odf.nxdl.xml # contributed_definitions/NXms_pf.nxdl.xml # contributed_definitions/NXroi.nxdl.xml # contributed_definitions/NXslip_system_set.nxdl.xml --- base_classes/NXentry.nxdl.xml | 0 contributed_definitions/NXatom_set.nxdl.xml | 158 ---- .../NXcg_primitive_set.nxdl.xml | 212 ----- .../NXcoordinate_system.nxdl.xml | 143 --- .../NXcrystal_structure.nxdl.xml | 280 ------ contributed_definitions/NXcs_mm_obj.nxdl.xml | 51 - .../NXdispersive_material.nxdl.xml | 11 +- .../NXelectronanalyser.nxdl.xml | 6 +- contributed_definitions/NXem_adf.nxdl.xml | 46 - .../NXem_correlation.nxdl.xml | 245 ----- .../NXem_ebsd_conventions.nxdl.xml | 610 ++++++++++++ contributed_definitions/NXem_eels.nxdl.xml | 74 -- contributed_definitions/NXem_msr.nxdl.xml | 96 -- .../NXinteraction_vol_em.nxdl.xml | 66 +- .../NXmicrostructure_gragles_results.nxdl.xml | 38 - .../NXmicrostructure_imm_results.nxdl.xml | 190 ---- .../NXms_mtex_config.nxdl.xml | 310 ------- contributed_definitions/NXms_odf.nxdl.xml | 171 ---- contributed_definitions/NXms_pf.nxdl.xml | 111 --- contributed_definitions/NXopt.nxdl.xml | 868 ++++++++++++++++++ contributed_definitions/NXroi.nxdl.xml | 34 - .../NXslip_system_set.nxdl.xml | 85 ++ 22 files changed, 1599 insertions(+), 2206 deletions(-) mode change 100644 => 100755 base_classes/NXentry.nxdl.xml delete mode 100644 contributed_definitions/NXatom_set.nxdl.xml delete mode 100644 contributed_definitions/NXcg_primitive_set.nxdl.xml delete mode 100644 contributed_definitions/NXcoordinate_system.nxdl.xml delete mode 100644 contributed_definitions/NXcrystal_structure.nxdl.xml delete mode 100644 contributed_definitions/NXcs_mm_obj.nxdl.xml delete mode 100644 contributed_definitions/NXem_adf.nxdl.xml delete mode 100644 contributed_definitions/NXem_correlation.nxdl.xml create mode 100644 contributed_definitions/NXem_ebsd_conventions.nxdl.xml delete mode 100644 contributed_definitions/NXem_eels.nxdl.xml delete mode 100644 contributed_definitions/NXem_msr.nxdl.xml delete mode 100644 contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml delete mode 100644 contributed_definitions/NXmicrostructure_imm_results.nxdl.xml delete mode 100644 contributed_definitions/NXms_mtex_config.nxdl.xml delete mode 100644 contributed_definitions/NXms_odf.nxdl.xml delete mode 100644 contributed_definitions/NXms_pf.nxdl.xml create mode 100644 contributed_definitions/NXopt.nxdl.xml delete mode 100644 contributed_definitions/NXroi.nxdl.xml create mode 100644 contributed_definitions/NXslip_system_set.nxdl.xml diff --git a/base_classes/NXentry.nxdl.xml b/base_classes/NXentry.nxdl.xml old mode 100644 new mode 100755 diff --git a/contributed_definitions/NXatom_set.nxdl.xml b/contributed_definitions/NXatom_set.nxdl.xml deleted file mode 100644 index 0a1e20856..000000000 --- a/contributed_definitions/NXatom_set.nxdl.xml +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Maximum number of atoms/isotopes allowed per (molecular) ion (fragment). - - - - - Number of mass-to-charge-state-ratio range intervals for ion type. - - - - - Base class for documenting a set of atoms. - - - - A unique identifier whereby such an ion can be referred to - via the service offered as described in identifier_type. - - - - - How can the identifier be resolved? - - - - - - - - Ion type (ion species) identifier. - - The identifier zero is reserved for the special unknown ion type. - - - - - Vector of nuclide hash values. - - Individual hash values :math:`H` is :math:`H = Z + N \cdot 256` with :math:`Z` - encode the number of protons :math:`Z` and the number of neutrons :math:`N` - of each nuclide respectively. :math:`Z` and :math:`N` have to be 8-bit unsigned integers. - - The array is sorted in decreasing order. For the rationale behind this see `M. Kühbach et al. (2021) <https://doi.org/10.1017/S1431927621012241>`_ - - - - - - - - Table which decodes the entries in nuclide_hash into a human-readable matrix of instances. - The first column specifies the nuclide mass number, i.e. using the hashvalues - from the isotope_vector this is :math:`Z + N` or 0. The value 0 documents that no - isotope-specific information about the element encoded is relevant. - The second row specifies the number of protons :math:`Z` or 0. - The value 0 in this case documents a placeholder or that no element-specific - information is relevant. - Taking a carbon-14 nuclide as an example the mass number is 14. - That is encoded as a value pair (14, 6) as one row of the table. - - Therefore, this notation is the typical superscribed nuclide mass number - and subscripted number of protons element notation e.g. :math:`^{14}C`. - The array is stored matching the order of nuclide_hash. - - - - - - - - - - Assumed volume of the ion. - - In atom probe microscopy this field can be used to store the reconstructed - volume per ion (average) which is typically stored alongside ranging - definitions. - - - - - Charge of the ion. - - - - - Signed charge state if the atoms form an ion reported in multiples of electron charge. - - In the example of atom probe microscopy, only positive values will be measured - as the ions are accelerated by a negatively signed bias electric field. - In the case that the charge state is not explicitly recoverable, the value should - be set to zero. - - In atom probe microscopy this is for example the case when using - classical ranging definition files in formats like RNG, RRNG. - These file formats do not document the charge state explicitly - but the number of atoms of each element per molecular ion - surplus the mass-to-charge-state-ratio interval. - Details on ranging definition files can be found in the literature: - `M. K. Miller <https://doi.org/10.1002/sia.1719>`_ - - - - - Human-readable name (e.g. Al +++) of the atom set, the atom group, or ion type. - The string should consists of UTF-8 characters, ideally using LaTeX - notation to specify the isotopes, ions, and charge state. - Examples are 12C + or Al +++. - - To ease automated parsing, isotope_vector should be the - preferred machine-readable information used. - - - - - Associated lower (mqmin) and upper (mqmax) bounds of the - mass-to-charge-state ratio interval(s) [mqmin, mqmax] - (boundaries inclusive). This field is primarily of interest - for documenting :ref:`NXprocess` steps of indexing a - ToF/mass-to-charge state histogram. - - - - - - - diff --git a/contributed_definitions/NXcg_primitive_set.nxdl.xml b/contributed_definitions/NXcg_primitive_set.nxdl.xml deleted file mode 100644 index ac451bdc6..000000000 --- a/contributed_definitions/NXcg_primitive_set.nxdl.xml +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - The dimensionality of the space. - - - - - The cardinality of the set, i.e. the number of members. - - - - - Computational geometry description of a set of primitives in Euclidean space. - - Primitives must neither be degenerated nor self-intersect. - Individual primitives can differ in their properties (e.g. size, shape, rotation). - - - - - Hint to help resolve in which Euclidean coordinate system field values - like center or orientation are defined. - - - - - The dimensionality of the primitive set. - - - - - - - - - - The cardinality of the primitive set. - - - - - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - - Therefore, implicit identifier are completely defined by the value of - identifier_offset and cardinality. For example if identifier run from - -2 to 3 the value for identifier_offset is -2. - - For explicit indexing the field identifier has to be used. - Fortran-/Matlab- and C-/Python-style indexing have specific implicit - identifier conventions where identifier_offset is 1 and 0 respectively. - - - - - Identifier of each member for explicit indexing. - - - - - - - - The center of mass position of each primitive. - - - - - - - - - - True if the center is a center of mass. - - - - - - - - A qualitative description of the shape of each primitive. - - - - - - - - - Qualifier for the length of characteristic features of the primitive. - - Often the term length is associated with the assumption that one - edge is parallel to an axis of the coordinate system. - - - - - - - - Qualifier often used to describe the length of one characteristic edge - within the coordinate system. - - - - - - - - True if primitive is closed such that it has properties like area or volume. - - - - - - - - Volume of each primitive. - - Set to NaN if does not apply for primitives for which is_closed is False. - - - - - - - - Alias for surface_area of each primitive. - - Set to NaN if does not apply for primitives for which is_closed is False. - - - - - - - - Direction unit vector which points along the - longest principal axis of each primitive. - - Use the depends_on attribute to specify in which coordinate system - these direction unit vectors are defined. - - - - - - - - - - - diff --git a/contributed_definitions/NXcoordinate_system.nxdl.xml b/contributed_definitions/NXcoordinate_system.nxdl.xml deleted file mode 100644 index a8dcb8369..000000000 --- a/contributed_definitions/NXcoordinate_system.nxdl.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - Base class to detail a coordinate system (CS). - - Whenever possible, an instance of :ref:`NXcoordinate_system` should be used as - a member in an :ref:`NXcoordinate_system_set` and the name of the instance - should be this alias. This may support a process whereby jargon when talking - about coordinate systems and conventions may become cleaner for users - because it is not evident for people outside a lab that terms like e.g. - tip space or specimen space refer to the same coordinate system. - This is an example of jargon used in e.g. the field of atom - probe tomography. - - - - Human-readable field telling where the origin of this CS is. - Exemplar values could be *left corner of the lab bench*, *door-handle* - *pinhole through which the electron beam exists the pole piece*. - *barycenter of the triangle*, *center of mass of the stone*. - - - - - - An alternative name given to that coordinate system. - - - - - Coordinate system type. - - - - - - - - Handedness of the coordinate system if it is a Cartesian. - - - - - - - - - Possibility to define an alias for the name of the x-axis. - - - - - Human-readable field telling in which direction the x-axis points if that - instance of :ref:`NXcoordinate_system` has no reference to any parent and as such - is the mighty world reference frame. - - Exemplar values could be direction of gravity. - - - - - Base unit vector along the first axis which spans the coordinate system. - This axis is frequently referred to as the x-axis in real space and - the i-axis in reciprocal space. - - - - - - - - Possibility to define an alias for the name of the y-axis. - - - - - Human-readable field telling in which direction the y-axis points if that - instance of :ref:`NXcoordinate_system` has no reference to any parent and as such - is the mighty world reference frame. - - See docstring of x_alias for further details. - - - - - Base unit vector along the second axis which spans the coordinate system. - This axis is frequently referred to as the y-axis in real space and - the j-axis in reciprocal space. - - - - - - - - Possibility to define an alias for the name of the z-axis. - - - - - Human-readable field telling in which direction the z-axis points if that - instance of :ref:`NXcoordinate_system` has no reference to any parent and as such - is the mighty world reference frame. - - See docstring of x_alias for further details. - - - - - Base unit vector along the second axis which spans the coordinate system. - This axis is frequently referred to as the z-axis in real space and - the k-axis in reciprocal space. - - - - - - diff --git a/contributed_definitions/NXcrystal_structure.nxdl.xml b/contributed_definitions/NXcrystal_structure.nxdl.xml deleted file mode 100644 index 4baccda13..000000000 --- a/contributed_definitions/NXcrystal_structure.nxdl.xml +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - - - Number of reflectors (Miller crystallographic plane triplets). - - - - - Number of atom positions. - - - - - Dimensionality of the lattice. - - - - - Base class to describe the atomic crystal structure of a phase. - - This base class contains key metadata that are relevant parameter to every - physics-based model to simulate radiation matter interaction. - - Examples where such base class is useful are kinematic or dynamic - diffraction simulations of e.g. (Kikuchi or other type of) patterns. - - - - Detail in which reference frame the unit cell is defined. - - - - - Dimensionality of the lattice. - - - - - - - - - - Reference to another resource that was used for - instantiating this structure model. - - - - - Crystallography unit cell parameters a, b, and c. - - - - - - - - - Crystallography unit cell parameters alpha, beta, and gamma. - - - - - - - - Area of the unit cell considering that d = 2. - - - - - Volume of the unit cell considering that d = 3. - - - - - Crystal system - - - - - - - - - - - - - - - Laue group using International Table of Crystallography Notation. - - - - - - Point group using International Table of Crystallography Notation. - - - - - - Space group from the International Table of Crystallography Notation. - - - - - - True if space group is considered a centrosymmetric one. - False if space group is considered a non-centrosymmetric one. - Centrosymmetric has all types and combinations of symmetry elements - (translation, rotational axis, mirror planes, center of inversion) - Non-centrosymmetric compared to centrosymmetric is constrained (no inversion). - Chiral compared to non-centrosymmetric is constrained (no mirror planes). - - - - - True if space group is considered a chiral one. - False if space group is consider a non-chiral one. - - - - - Identifier for each phase. - - The value 0 is reserved for the unknown phase that represents the - null-model no sufficiently significant confirmation. In other words, - the phase_name is n/a, notIndexed. - - The phase identifier value has to match with the integer postfix of the - group name which represents that instance in a NeXus/HDF5 file, i.e. - if two phases were used e.g. 0 and 1, two instances of an - :ref:`NXcrystal_structure` named phase0 and phase1 - should be stored in the HDF5 file. - - - - - - Name of the phase/alias. - - If the phase_identifier is 0 and one would like to use the field - phase_name the value should be n/a. - - - - - Label for each atom position. - - - - - - - - The hash value :math:`H` is :math:`H = Z + N*256` with :math:`Z` - the number of protons and :math:`N` the number of neutrons - of each isotope respectively. Z and N have to be 8-bit unsigned integers. - For the rationale behind this `M. Kühbach et al. (2021) <https://doi.org/10.1017/S1431927621012241>`_ - - - - - - - - - Atom positions. - - - - - - - - Reference to an instance of :ref:`NXcoordinate_system` - whereby the positions can be resolved. - - - - - - - Relative occupancy of the atom position. - - - - - - - - How many reflectors are distinguished. - - Value has to match value for symbol n_hkl. - - - - - - Miller indices :math:`(hkl)[uvw]` of the planes. - - The first triplet specify :math:`(hkl)` the second triplet :math:`[uvw]`. - Miller indices refer to the Cartesian right-handed coordinate system - of the unit cell. - - - - - - - - - Spacing between crystallographic planes as defined by field miller. - - - - - - - - Relative intensity of the signal for the plane. - - - - - - - - In case the :ref:`NXcrystal_structure` base class is used - with analyzed orientation maps this field stores how many scan points - of the map were identified as that phase. - - - - - - - diff --git a/contributed_definitions/NXcs_mm_obj.nxdl.xml b/contributed_definitions/NXcs_mm_obj.nxdl.xml deleted file mode 100644 index e2b247079..000000000 --- a/contributed_definitions/NXcs_mm_obj.nxdl.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a memory in a memory system. - - - - Qualifier for the type of random access memory. - - - - - - Total amount of data which the medium can hold. - - - - - - Given name to the I/O unit. - - - - diff --git a/contributed_definitions/NXdispersive_material.nxdl.xml b/contributed_definitions/NXdispersive_material.nxdl.xml index bc70d81a8..e4e4118b6 100644 --- a/contributed_definitions/NXdispersive_material.nxdl.xml +++ b/contributed_definitions/NXdispersive_material.nxdl.xml @@ -46,6 +46,15 @@ + + Name of the program used for creating this dispersion + + + Version of the program used + + + Date and time of creating this dispersion. + @@ -222,4 +231,4 @@ - \ No newline at end of file + diff --git a/contributed_definitions/NXelectronanalyser.nxdl.xml b/contributed_definitions/NXelectronanalyser.nxdl.xml index 956d0c931..db991447d 100644 --- a/contributed_definitions/NXelectronanalyser.nxdl.xml +++ b/contributed_definitions/NXelectronanalyser.nxdl.xml @@ -28,13 +28,13 @@ - Number of fast axes (axes acquired simultaneously, without scanning a - physical quantity) + Number of fast axes (axes acquired symultaneously, without scanning a pysical + quantity) - Number of slow axes (axes acquired scanning a physical quantity) + Number of slow axes (axes acquired scanning a pysical quantity) diff --git a/contributed_definitions/NXem_adf.nxdl.xml b/contributed_definitions/NXem_adf.nxdl.xml deleted file mode 100644 index 7e9902988..000000000 --- a/contributed_definitions/NXem_adf.nxdl.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - Base class method-specific for annular dark field imaging. - - In the majority of cases simple d-dimensional regular scan patterns are used - to probe a region-of-interest (ROI). Examples can be single point aka spot - measurements, line profiles, or (rectangular) surface mappings. - The latter pattern is the most frequently used. - - For now the base class provides for scans for which the settings, - binning, and energy resolution is the same for each scan point. - - - - - Annulus inner (first value) and outer (second value) half angle. - - - - - - - diff --git a/contributed_definitions/NXem_correlation.nxdl.xml b/contributed_definitions/NXem_correlation.nxdl.xml deleted file mode 100644 index 58c0f6825..000000000 --- a/contributed_definitions/NXem_correlation.nxdl.xml +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - Base class to combine different method-specific data in electron microscopy. - - This base class represent a template for documenting correlations - (spatial, temporal) between different method-specific results. - - - - Details about processing steps. - - - - - - Details about correlated or logically connected EBSD datasets. - - One important class of such correlated experiments are the so-called - (quasi) in-situ experiments. In this case the same or nearly the same ROI - gets analyzed via a repetitive sequence of thermomechanical treatment, - sample preparation, measurement, on-the-fly-indexing. Phenomena - investigated are recrystallization, strain accumulation, material damage. - Post-processing is required to correlate and reidentify eventual - microstructural features or local ROIs across several orientation maps. - - Another important class of correlated experiments are the so-called - serial-sectioning experiments. Here the same sample is measured - repetitively after polishing each time, to create a stack of - orientation data which can be reconstructed to a - three-dimensional volume ROI. - - Data can be correlated in time, position (spatial), or both (spatiotemporal). - - Spatial correlations between repetitively characterized regions-of-interests - are typically correlated using image registration and alignment algorithms. - For this typically so-called landmarks are used. These can be grains with - a very large size or specific shape, i.e. grains which are qualitatively - different enough to be used as a guide how images are shifted relative to - one another. Other commonly used landmarks are fiducial marks which are - milled into the specimen surface using focus-ion beam milling and/or various - types of indentation methods. - - As far as the same physical region-of-interest is just measured several times, - the additional issue of the depth increment is not a concern. However, correct - assumptions for the depth increment, amount of material removed along the milling - direction is relevant for accurate and precise three-dimensional (serial-sectioning) - correlations. For these studies it can be tricky though to assume or estimate - useful depth increments. Different strategies have been proposed like - calibrations, wedged-shaped landmarks and computer simulation assisted - assumption making. - - Despite the use of landmarks, there are many practical issues which make the - processing of correlations imprecise and inaccurate. Among these are drift - and shift of the specimen, instabilities of the holder, the beam, irrespective - of the source of the drift, charging effects, here specifically causing local - image distortions and rotations which may require special processing algorithms - to reduce such imprecisions. - - Time correlations face all of the above-mentioned issues surplus the challenge - that specific experimental protocols have to be used to ensure the material state - is observed at specific physical time. The example of quasi in-situ characterization - of crystal growth phenomena, a common topic in engineering or modern catalysis research - makes it necessary to consider that e.g. the target value for the desired annealing - temperature is not just gauged based on macroscopic arguments but considers - that transient effects take place. Heating or quenching a sample might thus might - not have been executed under conditions in the interaction volume as they are - documented and/or assumed. - - These issue cause that correlations have an error margin as to how accurately - respective datasets were not only just synced based on the geometry of the - region-of-interests and the time markers but also to asssure which physical - conditions the specimen experienced over the course of the measurements. - - The fourth example of the em_om reference implementation explores the use of the - correlation group with a serial-sectioning datasets that was collected by the - classical Inconel 100 dataset collected by M. D. Uchic and colleagues - (M. Groeber M, Haley BK, Uchic MD, Dimiduk DM, Ghosh S 3d reconstruction and - characterization of polycrystalline microstructures using a fib-sem system data set. - Mater Charac 2006, 57 259–273. 10.1016/j.matchar.2006.01.019M). - - This dataset was specifically relevant in driving forward the implementation - of the DREAM.3D software. DREAM.3D is an open-source software project for - post-processing and reconstructing, i.e. correlating sets of orientation - microscopy data foremost spatially. One focus of the software is the - (post-)processing of EBSD datasets. Another cutting edge tool with similar - scope but a commercial solution by Bruker is QUBE which was developed by - P. Konijnenberg and coworkers. - - Conceptually, software like DREAM.3D supports users with creating linear - workflows of post-processing tasks. Workflows can be instructed via the - graphical user interface or via so-called pipeline processing via command line - calls. DREAM.3D is especially useful because its internal system documents all - input, output, and parameter of the processing steps. This makes DREAM.3D a - good candidate to interface with tools like em_om parser. Specifically, DREAM.3D - documents numerical results via a customized HDF5 file format called DREAM3D. - Workflow steps and settings are stored as nested dictionaries in JSON syntax - inside a supplementary JSON file or alongside the data in the DREAM3D file. - DREAM.3D has a few hundred algorithms implemented. These are called filters - in DREAM.3D terminology. - - Users configure a workflow which instructs DREAM.3D to send the data through - a chain of predefined and configured filters. Given that for each analysis - the filter is documented via its version tags surplus its parameter and setting - via a controlled vocabulary, interpreting the content of a DREAM3D HDF5 file - is possible in an automated manner using a parser. This makes DREAM.3D analyses - repeatable and self-descriptive. A key limitation though is that most frequently - the initial set of input data come from commercial files like ANG. - This missing link between the provenance of these input files, their associated - creation as electron microscope session, is also what NXem_ebsd solves. - - Nevertheless, as this can be solved with e.g. NXem_ebsd we are convinced that - the DREAM.3D and the em_om parser can work productively together to realize - RDMS-agnostic parsing of serial-section analyses. - - The internal documentation of the DREAM.3D workflow also simplifies the - provenance tracking represented by an instance of NXem_ebsd as not every - intermediate results has to be stored. Therefore, the fourth example - focuses on the key result obtained from DREAM.3D - the reconstructed - and aligned three-dimensional orientation map. - - Usually, this result is the starting point for further post-processing - and characterization of structural features. As here orientation microscopy - is insofar scale invariant using DREAM.3D, NXem_ebsd, and em_om should - be useful for different characterization methods, such as EBSD, Transmission - Kikuchi Diffraction (TKD), Automated Crystal Orientation Mapping (ACOM), - Nanobeam Electron Diffraction (using commercial systems like NanoMegas ASTAR) - or open-source implementations of these techniques (such as via pyxem/orix). - - The result of orientation microscopy methods are maps of local orientation - and thermodynamic phase (crystal structure) pieces of information. Virtually - all post-processing of such results for structural features includes again - a workflow of steps which are covered though by the NXms partner application - definition. The respective source of the data in an instance of NXms can - again be a link or reference to an instance of NXem_ebsd to complete the - chain of provenance. - - - - - - Descriptor representing the image contrast. - - - - - - Title of the default plot. - - - - - Descriptor values displaying the ROI. - - - - - - - - - - Descriptor values. - - - - - - Calibrated coordinate along the z-axis. - - - - - - - Label for the z axis - - - - - - Calibrated coordinate along the y-axis. - - - - - - - Label for the y axis - - - - - - Calibrated coordinate along the x-axis. - - - - - - - Label for the x axis - - - - - - - diff --git a/contributed_definitions/NXem_ebsd_conventions.nxdl.xml b/contributed_definitions/NXem_ebsd_conventions.nxdl.xml new file mode 100644 index 000000000..7ef85f871 --- /dev/null +++ b/contributed_definitions/NXem_ebsd_conventions.nxdl.xml @@ -0,0 +1,610 @@ + + + + + + + Conventions for rotations and coordinate systems to interpret EBSD data. + + This is the main issue which currently is not in all cases documented + and thus limits the interoperability and value of collected EBSD data. + Not communicating EBSD data with such contextual pieces of information + and the use of file formats which do not store this information is the + key unsolved problem. + + + + + Mathematical conventions and materials-science-specific conventions + required for interpreting every collection of orientation data. + + + + Convention how a positive rotation angle is defined when viewing + from the end of the rotation unit vector towards its origin, + i.e. in accordance with convention 2 of + DOI: 10.1088/0965-0393/23/8/083501. + Counter_clockwise is equivalent to a right-handed choice. + Clockwise is equivalent to a left-handed choice. + + + + + + + + + + How are rotations interpreted into an orientation + according to convention 3 of + DOI: 10.1088/0965-0393/23/8/083501. + + + + + + + + + + How are Euler angles interpreted given that there are several + choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of + DOI: 10.1088/0965-0393/23/8/083501. + The most frequently used convention is ZXZ which is based on + the work of H.-J. Bunge but other conventions are possible. + + + + + + + + + To which angular range is the rotation angle argument of an + axis-angle pair parameterization constrained according to + convention 5 of DOI: 10.1088/0965-0393/23/8/083501. + + + + + + + + + Which sign convention is followed when converting orientations + between different parameterizations/representations according + to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. + + + + + + + + + + + Details about eventually relevant named directions that may + give reasons for anisotropies. The classical example is cold-rolling + where one has to specify which directions (rolling, transverse, and normal) + align how with the direction of the base vectors of the sample_reference_frame. + + + + Type of coordinate system and reference frame according to + convention 1 of DOI: 10.1088/0965-0393/23/8/083501. + + + + + + + + + + Direction of the positively pointing x-axis base vector of + the processing_reference_frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. + + + + + + + + + + + + + + Name or alias assigned to the x-axis base vector, e.g. rolling direction. + + + + + Direction of the positively pointing y-axis base vector of + the processing_reference_frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + + + + + + + + + + + + + + Name or alias assigned to the y-axis base vector, e.g. transverse direction. + + + + + Direction of the positively pointing z-axis base vector of + the processing_reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + + + + + + + + + + + + + + Name or alias assigned to the z-axis base vector, e.g. normal direction. + + + + + Location of the origin of the processing_reference_frame. + This specifies the location Xp = 0, Yp = 0, Zp = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + + + + + + + + + + + + + + + + + Details about the sample/specimen reference frame. + + + + Type of coordinate system and reference frame according to + convention 1 of DOI: 10.1088/0965-0393/23/8/083501. + The reference frame for the sample surface reference is used for + identifying positions on a (virtual) image which is formed by + information collected from an electron beam scanning the + sample surface. We assume the configuration is inspected by + looking towards the sample surface from a position that is + located behind the detector. + Reference DOI: 10.1016/j.matchar.2016.04.008 + The sample surface reference frame has coordinates Xs, Ys, Zs. + In three dimensions these coordinates are not necessarily + located on the surface of the sample as there are multiple + faces/sides of the sample. Most frequently though the coordinate + system here is used to define the surface which the electron + beam scans. + + + + + + + + + + Direction of the positively pointing x-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + + + + + + + + + + + + + + Direction of the positively pointing y-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + + + + + + + + + + + + + + Direction of the positively pointing z-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + + + + + + + + + + + + + + Location of the origin of the sample surface reference frame. + This specifies the location Xs = 0, Ys = 0, Zs = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + + + + + + + + + + + + + + + + + Details about the detector reference frame. + + + + Type of coordinate system/reference frame used for + identifying positions in detector space Xd, Yd, Zd, + according to DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + + Direction of the positively pointing x-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + + + + + + + + + + + + + + Direction of the positively pointing y-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + Direction of the positively pointing z-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + Where is the origin of the detector space reference + frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + + + + + + + + + + + + + + + + + Details about the gnomonic projection reference frame. + + + + Type of coordinate system/reference frame used for identifying + positions in the gnomonic projection space Xg, Yg, Zg + according to DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + + Direction of the positively pointing "gnomomic" x-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + + + + + + + + + + + + + + Direction of the positively pointing "gnomomic" y-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + Direction of the positively pointing "gnomomic" z-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + Is the origin of the gnomonic coordinate system located + where we assume the location of the pattern centre. + This is the location Xg = 0, Yg = 0, Zg = 0 according to + reference DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + + Details about the definition of the pattern centre + as a special point in the gnomonic projection reference frame. + + + + From which border of the EBSP (in the detector reference frame) + is the pattern centre's x-position (PCx) measured? + Keywords assume the region-of-interest is defined by + a rectangle. We observe this rectangle and inspect the + direction of the outer-unit normals to the edges of + this rectangle. + + + + + + + + + + + + In which direction are positive values for PCx measured from + the specified boundary. Keep in mind that the gnomonic space + is in virtually all cases embedded in the detector space. + Specifically, the XgYg plane is defined such that it is + embedded/laying inside the XdYd plane (of the detector + reference frame). + When the normalization direction is the same as e.g. the + detector x-axis direction, we state that we effectively + normalize in fractions of the width of the detector. + + The issue with terms like width and height is that these + degenerate if the detector region-of-interest is square-shaped. + This is why we should better avoid talking about width and height but + state how we would measure distances practically with a ruler and + how we then measure positive distances. + + + + + + + + + + + + From which border of the EBSP (in the detector reference + frame) is the pattern centre's y-position (PCy) measured? + For further details inspect the help button of + xaxis_boundary_convention. + + + + + + + + + + + + In which direction are positive values for PCy measured from + the specified boundary. + For further details inspect the help button of + xaxis_normalization_direction. + + + + + + + + + + + + diff --git a/contributed_definitions/NXem_eels.nxdl.xml b/contributed_definitions/NXem_eels.nxdl.xml deleted file mode 100644 index 0b8b756bf..000000000 --- a/contributed_definitions/NXem_eels.nxdl.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - Number of electron energy loss bins. - - - - - Base class method-specific for Electron Energy Loss Spectroscopy (EELS). - - - - - NXspectrum_set_em specialized for EELS. - - - - - - - - - - Energy loss. - - - - - - - - - Energy loss. - - - - - - - Energy loss. - - - - - - - diff --git a/contributed_definitions/NXem_msr.nxdl.xml b/contributed_definitions/NXem_msr.nxdl.xml deleted file mode 100644 index a6442b1e2..000000000 --- a/contributed_definitions/NXem_msr.nxdl.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - Base class for collecting a session with a real electron microscope. - - For collecting data and experiments which are simulations of an - electron microscope use the :ref:`NXem_sim` base class. - - - - (Meta)data of the microscope and the lab in which it stands. - - This em_lab group differs from potential em_lab groups inside - :ref:`NXevent_data_em` instances in that here the more static descriptions - are kept while changing, i.e. time-dependent pieces of information are - logged, via the em_lab group inside the desired number of instances - of NXevent_data_em. - - While using an :ref:`NXevent_data_em` instance, users should store only those - settings about a component which are relevant to understand the current - state of the component. Here, current means for the time interval which - the event covers (as it is detailed via start_time and end_time) timestamps. - - For example it is not relevant to store in each :ref:`NXevent_data_em` - electron_source group again the details of the gun type and the manufacturer - but only the high-voltage value and that only if it is different from the value - that is specified in the em_lab section for the static settings. - - In effect, this defines an information inference hierarchy which starts - in an individual :ref:`NXevent_data_em` instance followed by a probing of the - static section. - - - - Given name of the microscope at the hosting institution. - This is an alias. Examples could be NionHermes, Titan, JEOL, - Gemini, etc. - - - - - Location of the lab or place where the instrument is installed. - Using GEOREF is preferred. - - - - - - - - - - Description of the type of the detector. - - Electron microscopes have typically multiple detectors. - Different technologies are in use like CCD, scintillator, - direct electron, CMOS, or image plate to name but a few. - - - - Instrument-specific alias/name - - - - - - - - - - diff --git a/contributed_definitions/NXinteraction_vol_em.nxdl.xml b/contributed_definitions/NXinteraction_vol_em.nxdl.xml index 59c71c10e..a6beeb648 100644 --- a/contributed_definitions/NXinteraction_vol_em.nxdl.xml +++ b/contributed_definitions/NXinteraction_vol_em.nxdl.xml @@ -1,56 +1,36 @@ - + - - + - Base class for describing the interaction volume of particle-matter interaction. + Base class for storing details about a modelled shape of interaction volume. - Computer models like Monte Carlo or molecular dynamics / electron- or ion-beam - interaction simulations can be used to qualify and (or) quantify the shape of - the interaction volume. Results of such simulations can be summary statistics - or single-particle resolved sets of trajectories. + The interaction volume is mainly relevant in scanning electron microscopy + when the sample is thick enough so that the beam is unable to illuminate + through the specimen. + Computer models like Monte Carlo or molecular dynamics / electron beam + interaction simulations can be used to qualify and/or quantify the shape of + the interaction volume. Explicit or implicit descriptions are possible. - * An implicit description is via a set of electron/specimen interactions - represented ideally as trajectory data from the computer simulation. - * An explicit description is via an iso-contour surface using either - a simulation grid or a triangulated surface mesh of the approximated - iso-contour surface evaluated at specific threshold values. - Iso-contours could be computed from electron or particle fluxes through - an imaginary control surface (the iso-surface). - Threshold values can be defined by particles passing through a unit control - volume (electrons) or energy-levels (e.g. the case of X-rays). - Details depend on the model. - * Another explicit description is via theoretical models which may - be relevant e.g. for X-ray spectroscopy + * An implicit description is via a set of electron/specimen interactions + represented ideally as trajectory data from the computer simulation. + * An explicit description is via an iso-contour surface using either + a simulation grid or a triangulated surface mesh of the approximated + iso-contour surface evaluated at specific threshold values. + Iso-contours could be computed from electron or particle fluxes through + an imaginary control surface (the iso-surface). + Threshold values can be defined by particles passing through a unit control + volume (electrons) or energy-levels (e.g. the case of X-rays). + Details depend on the model. + * Another explicit description is via theoretical models which may + be relevant e.g. for X-ray spectroscopy Further details on how the interaction volume can be quantified is available in the literature for example: - * `S. Richter et al. <https://doi.org/10.1088/1757-899X/109/1/012014>`_ - * `J. Bünger et al. <https://doi.org/10.1017/S1431927622000083>`_ - * `J. F. Ziegler et al. <https://doi.org/10.1007/978-3-642-68779-2_5>`_ + * `S. Richter et al. <https://doi.org/10.1088/1757-899X/109/1/012014>`_ + * `J. Bünger et al. <https://doi.org/10.1017/S1431927622000083>`_ diff --git a/contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml b/contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml deleted file mode 100644 index 7b6fb5180..000000000 --- a/contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - Application definition for documenting results with GraGLeS. - - - - - - - - - - diff --git a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml deleted file mode 100644 index 90f7c7877..000000000 --- a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - Number of material points along the edge of the square- or cube-shaped domain. - - - - - Number of crystals. - - - - - Application definition for the results of the legacy (micro)structure generator developed - by the Institut für Metallkunde und Metallphysik at RWTH Aachen University. - - * `N. Leuning et al. <https://doi.org/10.3390/ma14216588>`_ - * `C. Mießen <https://doi.org/10.18154/RWTH-2017-10148>`_ - * `M. Kühbach <https://doi.org/10.18154/RWTH-2018-00294>`_ - * `M. Kühbach et al. <https://github.com/mkuehbach/GraGLeS>`_ - - The tool can be used to instantiate specific configurations for two- and three-dimensional discretized microstructures. - Specifically, single-phase material that is composed of crystals, so-called (parent) grains which are tessellated into so-called sub-grains. - Grains are modelled as elongated crystals to mimic fundamental geometrical constraints of the interface network in deformed material. - - - - - - - - - - - Discouraged free-text field to add further details to the computation. - - - - - - - - - - - - - - - Programs and libraries representing the computational environment - - - - - - - - - - - - - - Default plot showing the grid. - - - - - - - - Crystal identifier that was assigned to each material point. - - - - - - Material point barycentre coordinate along z direction. - - - - - - - Coordinate along z direction. - - - - - - Material point barycentre coordinate along y direction. - - - - - - - Coordinate along y direction. - - - - - - Material point barycentre coordinate along x direction. - - - - - - - Coordinate along x direction. - - - - - - - - - - - - - - - - - - - - - - - - - - True if the crystal is considered a sub-grain. - False if the crystal is considered a grain. - - - - - - - - Bunge-Euler angle orientation of each crystal. - - - - - - - - - Mean-field dislocation density as a measure of the stored elastic energy - content that is stored in the dislocation network of this grain and related - defects within each crystal. - - - - - - - - - diff --git a/contributed_definitions/NXms_mtex_config.nxdl.xml b/contributed_definitions/NXms_mtex_config.nxdl.xml deleted file mode 100644 index a810d12b3..000000000 --- a/contributed_definitions/NXms_mtex_config.nxdl.xml +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - Base class to store the configuration when using the MTex/Matlab software. - - MTex is a Matlab package for texture analysis used in the Materials and Earth Sciences. - See `R. Hielscher et al. <https://mtex-toolbox.github.io/publications>`_ and - the `MTex source code <https://github.com/mtex-toolbox>`_ for details. - - - - Reference frame and orientation conventions. - Consult the `MTex docs <https://mtex-toolbox.github.io/EBSDReferenceFrame.html>`_ for details. - - - - TODO with MTex developers - - - - - - TODO with MTex developers - - - - - - TODO with MTex developers - - - - - - TODO with MTex developers - - - - - - TODO with MTex developers - - - - - - - - - - - Settings relevant for generating plots. - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - True if MTex renders a scale bar with figures. - - - - - True if MTex renders a grid with figures. - - - - - Code for the function handle used for annotating pole figure plots. - - - - - TODO with MTex developers - - - - - - - - - TODO with MTex developers - - - - - - - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - - Miscellaneous other settings of MTex. - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - - - Miscellaneous settings relevant for numerics. - - - - Return value of the Matlab eps command. - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - - Miscellaneous settings relevant of the system where MTex runs. - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - TODO with MTex developers - - - - - - Collection of paths from where MTex reads information and code. - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - Absolute path to specific component of MTex source code. - - - - - List of file type suffixes for which MTex assumes - texture/pole figure information. - - - - - List of file type suffixes for which MTex assumes EBSD content. - - - - - diff --git a/contributed_definitions/NXms_odf.nxdl.xml b/contributed_definitions/NXms_odf.nxdl.xml deleted file mode 100644 index 988034557..000000000 --- a/contributed_definitions/NXms_odf.nxdl.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - Number of pixel per varphi section plot along the varphi_one fastest direction. - - - - - Number of pixel per varphi section plot along the capital_phi slow direction. - - - - - Number of pixel per varphi section plot along the varphi_two slowest direction. - - - - - Number of local maxima evaluated in the component analysis. - - - - - Base class to store an orientation distribution function (ODF) computation. - - - - Details about the algorithm used for computing the ODF. - - - - Point group of the crystal structure (International Table of Crystallography) - of the phase for which the here documented phase-dependent ODF was computed. - - - - - Point group assumed for processing-induced *sample symmetries*. - (according to International Table of Crystallography). - - - - - Halfwidth of the kernel. - - - - - Name of the kernel. - - - - - Resolution of the kernel. - - - - - - - Number of local maxima evaluated for the ODF. - - - - - - Euler angle representation of the kth-most maxima of the ODF - in decreasing order of the intensity maximum. - - - - - - - - - Disorientation threshold within which intensity of the ODF - is integrated for the component analysis. - - - - - Integrated ODF intensity within a theta-ball of SO3 about - each location as specified for each location in the order - and reported in the order of these locations. - - - - - - - - - Visualization of the ODF intensity as orthogonal sections through Euler space. - - This is one example of typical default plots used in the texture - community in Materials Engineering. - - Mind that the Euler space is a distorted space. Therefore, equivalent - orientations show intensity contributions in eventually multiple - locations. - - - - - ODF intensity at probed locations relative to - null model of a completely random texture. - - - - - - - - - - Pixel center angular position along the :math:`\varphi_1` direction. - - - - - - - - - Pixel center angular position along the :math:`\varphi_2` direction. - - - - - - - - - Pixel center angular position along the :math:`\Phi` direction. - - - - - - - - diff --git a/contributed_definitions/NXms_pf.nxdl.xml b/contributed_definitions/NXms_pf.nxdl.xml deleted file mode 100644 index 9a627ac62..000000000 --- a/contributed_definitions/NXms_pf.nxdl.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - Number of pixel per pole figure in the slow direction. - - - - - Number of pixel per pole figure in the fast direction. - - - - - Base class to store a pole figure (PF) computation. - - - - Details about the algorithm that was used to compute the pole figure. - - - - Point group of the crystal structure of the phase for which the - here documented phase-dependent pole figure was computed - (according to International Table of Crystallography). - - - - - Point group assumed for processing induced *sample symmetries* - (according to International Table of Crystallography). - - - - - Halfwidth of the kernel. - - - - - Miller indices (:math:`(hkl)[uvw]`) to specify the pole figure. - - - - - Resolution of the kernel. - - - - - - Pole figure. - - - - - Pole figure intensity. - - - - - - - - - Pixel center along y direction in the equatorial plane of - a stereographic projection of the unit sphere. - - - - - - - - - Pixel center along x direction in the equatorial plane of - a stereographic projection of the unit sphere. - - - - - - - - diff --git a/contributed_definitions/NXopt.nxdl.xml b/contributed_definitions/NXopt.nxdl.xml new file mode 100644 index 000000000..be636590f --- /dev/null +++ b/contributed_definitions/NXopt.nxdl.xml @@ -0,0 +1,868 @@ + + + + + + + + + Variables used throughout the document, e.g. dimensions or parameters. + + + + Length of the spectrum array (e.g. wavelength or energy) of the measured + data. + + + + + Number of sensors used to measure parameters that influence the sample, + such as temperature or pressure. + + + + + Number of measurements (1st dimension of measured_data array). This is + equal to the number of parameters scanned. For example, if the experiment + was performed at three different temperatures and two different pressures + N_measurements = 2*3 = 6. + + + + + Number of detection angles of the beam reflected or scattered off the + sample. + + + + + Number of angles of incidence of the incident beam. + + + + + Number of observables that are saved in a measurement. e.g. one for + intensity, reflectivity or transmittance, two for Psi and Delta etc. This + is equal to the second dimension of the data array 'measured_data' and the + number of column names. + + + + + An application definition for optical spectroscopy experiments. + + + + An application definition template for optical spectroscopy experiments. + + A general optical experiment consists of a light or excitation source, a + beam path, a sample + its stage + its environment, and a detection unit. + Examples are reflection or transmission measurements, photoluminescence, + Raman spectroscopy, ellipsometry etc. + + + + An application definition describing a general optical experiment. + + + + Version number to identify which definition of this application + definition was used for this entry/data. + + + + + URL where to find further material (documentation, examples) relevant + to the application definition. + + + + + + + + + A (globally persistent) unique identifier of the experiment. + (i) The identifier is usually defined by the facility or principle + investigator. + (ii) The identifier enables to link experiments to e.g. proposals. + + + + + An optional free-text description of the experiment. + + However, details of the experiment should be defined in the specific + fields of this application definition rather than in this experiment + description. + + + + + Specify the type of the optical experiment. + + + + + Start time of the experiment. UTC offset should be specified. + + + + + Contact information of at least the user of the instrument or the + investigator who performed this experiment. + Adding multiple users, if relevant, is recommended. + + + + Name of the user. + + + + + Name of the affiliation of the user at the point in time when the + experiment was performed. + + + + + Street address of the user's affiliation. + + + + + Email address of the user. + + + + + Author ID defined by https://orcid.org/. + + + + + Telephone number of the user. + + + + + + Properties of the experimental setup. This includes general information + about the instrument (such as model, company etc.), information about + the calibration of the instrument, elements of the beam path including + the excitation or light source and the detector unit, the sample stage + (plus the sample environment, which also includes sensors used to + monitor external conditions) and elements of the beam path. + + Meta data describing the sample should be specified in ENTRY/SAMPLE + outside of ENTRY/INSTRUMENT. + + + + The name of the instrument. + + + + The used version of the hardware if available. If not a commercial + instrument use date of completion of the hardware. + + + + + + Name of the company which build the instrument. + + + + + ISO8601 date when the instrument was constructed. + UTC offset should be specified. + + + + + + Commercial or otherwise defined given name of the program that was + used to measure the data, i.e. the software used to start and + record the measured data and/or metadata. + If home written, one can provide the actual steps in the NOTE + subfield here. + + + + + Either version with build number, commit hash, or description of a + (online) repository where the source code of the program and build + instructions can be found so that the program can be configured in + such a way that result files can be created ideally in a + deterministic manner. + + + + + Website of the software. + + + + + + Commercial or otherwise defined name of the firmware that was used + for the measurement - if available. + + + + Version and build number or commit hash of the software source code. + + + + + Website of the software. + + + + + + Was a calibration performed? If yes, when was it done? If the + calibration time is provided, it should be specified in + ENTRY/INSTRUMENT/calibration/calibration_time. + + + + + + + + + + + + The calibration data and metadata should be described in a separate NeXus file + with the link provided in 'calibration_link'. + + + + If calibtration status is 'calibration time provided', specify the + ISO8601 date when calibration was last performed before this + measurement. UTC offset should be specified. + + + + + Link to the NeXus file containing the calibration data and metadata. + + + + + + Describes an arrangement of optical or other elements, e.g. the beam + path between the light source and the sample, or between the sample + and the detector unit (including the sources and detectors + themselves). + + If a beam splitter (i.e. a device that splits the incoming beam into + two or more beams) is part of the beam path, two or more NXbeam_path + fields may be needed to fully describe the beam paths and the correct + sequence of the beam path elements. + Use as many beam paths as needed to describe the setup. + + + + + Angle(s) of the incident beam vs. the normal of the bottom reflective + (substrate) surface in the sample. + + + + + + + + + Detection angle(s) of the beam reflected or scattered off the sample + vs. the normal of the bottom reflective (substrate) surface in the + sample if not equal to the angle(s) of incidence. + + + + + + + + Sample stage, holding the sample at a specific position in X,Y,Z + (Cartesian) coordinate system and at an orientation defined + by three Euler angles (alpha, beta, gamma). + + + + Specify the type of the sample stage. + + + + + + + + + + + + If there is no motorized stage, we should at least qualify where + the beam hits the sample and in what direction the sample stands + in a free-text description, e.g. 'center of sample, long edge + parallel to the plane of incidence'. + + + + + Specify external parameters that have influenced the sample, such + as the surrounding medium, and varied parameters e.g. temperature, + pressure, pH value, optical excitation etc. + + + + Describe what was the medium above or around the sample. The + common model is built up from the substrate to the medium on the + other side. Both boundaries are assumed infinite in the model. + Here, define the name of the medium (e.g. water, air, UHV, etc.). + + + + + Array of pairs of complex refractive indices n + ik of the medium + for every measured spectral point/wavelength/energy. + Only necessary if the measurement was performed not in air, or + something very well known, e.g. high purity water. + + + + + + + + + A sensor used to monitor an external condition influencing the + sample, such as temperature or pressure. It is suggested to + replace 'PARAMETER' by the type of the varied parameter defined + in 'parameter_type'. + The measured parameter values should be provided in 'values'. + For each parameter, a 'PARAMETER(NXsensor)' field needs to exist. + In other words, there are N_sensors 'PARAMETER(NXsensor)' fields. + + + + Indicates which parameter was changed. Its definition must exist + below. The specified variable has to be N_measurements long, + providing the parameters for each data set. If you vary more than + one parameter simultaneously. + If the measured parameter is not contained in the list `other` + should be specified and the `parameter_type_name` should be provided. + + + + + + + + + + + + + + + + + + + + + + + + + If the parameter_type is `other` a name should be specified here. + + + + + Number of different parameter values at which the measurement + was performed. For example, if the measurement was performed at + temperatures of 4, 77 and 300 K, then number_of_parameters = 3. + + + + + Vector containing the values of the varied parameter. Its + length is equal to N_measurements. The order of the values + should be as follows: + + * Order the sensors according to number_of_parameters starting + with the lowest number. If number_of_parameters is equal for + two sensors order them alphabetically (sensor/parameter name). + * The first sensor's j parameters should be ordered in the + following way. The first N_measurements/number_of_parameters + entries of the vector contain the first parameter (a1), the + second N_measurements/number_of_parameters contain the second + parameter (a2) etc., so the vector looks like: + [ + a1,a1,...,a1, + a2,a2,...,a2, + ... + aj,aj,...aj + ] + * The kth sensor's m parameters should be ordered in the + following way: + [ + p1,...p1,p2,...,p2,...pm,...,pm, + p1,...p1,p2,...,p2,...pm,...,pm, + ... + p1,...p1,p2,...,p2,...pm,...,pm + ] + * The last sensor's n parameters should be ordered in the + following way: + [ + z1,z2,...,zn, + z1,z2,...,zn, + ... + z1,z2,...,zn] + + For example, if the experiment was performed at three different + temperatures (T1, T2, T3), two different pressures (p1, p2) and + two different angles of incidence (a1, a2), then + N_measurements = 12 and the order of the values for the various + parameter vectors is: + + * angle_of_incidence: [a1,a1,a1,a1,a1,a1,a2,a2,a2,a2,a2,a2] + * pressure: [p1,p1,p1,p2,p2,p2,p1,p1,p1,p2,p2,p2] + * temperature: [T1,T2,T3,T1,T2,T3,T1,T2,T3,T1,T2,T3] + + + + + + + + + + For environmental measurements, the environment (liquid, vapor + etc.) is enclosed in a cell, which has windows both in the + direction of the source (entry window) and the detector (exit + window) (looking from the sample). In case that the entry and exit + windows are not the same type and do not have the same properties, + use a second 'WINDOW(MXaperture)' field. + + The windows also add a phase shift to the light altering the + measured signal. This shift has to be corrected based on measuring + a known sample (reference sample) or the actual sample of interest + in the environmental cell. State if a window correction has been + performed in 'window_effects_corrected'. Reference data should be + considered as a separate experiment, and a link to the NeXus file + should be added in reference_data_link in measured_data. + + The window is considered to be a part of the sample stage but also + beam path. Hence, its position within the beam path should be + defined by the 'depends_on' field. + + + + Specify the position of the window in the beam path by pointing + to the preceding element in the sequence of beam path elements. + + + + + Was a window correction performed? If 'True' describe the window + correction procedure in 'window_correction/procedure'. + + + + + Was a window correction performed? If 'True' describe the + window correction procedure in '' + + + + Describe when (before or after the main measurement + time + stamp in 'date') and how the window effects have been + corrected, i.e. either mathematically or by performing a + reference measurement. In the latter case, provide the link to + to the reference data in 'reference_data_link'. + + + + + Link to the NeXus file which describes the reference data if a + reference measurement for window correction was performed. + Ideally, the reference measurement was performed on a reference + sample and on the same sample, and using the same conditions as + for the actual measurement with and without windows. It should + have been conducted as close in time to the actual measurement + as possible. + + + + + + The material of the window. + + + + + + + + + + + + + + + If you specified 'other' as material, decsribe here what it is. + + + + + Thickness of the window. + + + + + Angle of the window normal (outer) vs. the substrate normal + (similar to the angle of incidence). + + + + + + + + Properties of the sample, such as sample type, layer structure, + chemical formula, atom types, its history etc. + Information about the sample stage and sample environment should be + described in ENTRY/INSTRUMENT/sample_stage. + + + + Descriptive name of the sample + + + + + Specify the type of sample, e.g. thin film, single crystal etc. + + + + + + + + + + + + Qualitative description of the layer structure for the sample, + starting with the top layer (i.e. the one on the front surface, on + which the light incident), e.g. native oxide/bulk substrate, or + Si/native oxide/thermal oxide/polymer/peptide. + + + + + Chemical formula of the sample. Use the Hill system (explained here: + https://en.wikipedia.org/wiki/Chemical_formula#Hill_system) to write + the chemical formula. In case the sample consists of several layers, + this should be a list of the chemical formulas of the individual + layers, where the first entry is the chemical formula of the top + layer (the one on the front surface, on which the light incident). + The order must be consistent with layer_structure + + + + + List of comma-separated elements from the periodic table that are + contained in the sample. If the sample substance has multiple + components, all elements from each component must be included in + 'atom_types'. + + + + + Ideally, a reference to the location or a unique (globally + persistent) identifier (e.g.) of e.g. another file which gives + as many as possible details of the material, its microstructure, + and its thermo-chemo-mechanical processing/preparation history. + In the case that such a detailed history of the sample is not + available, use this field as a free-text description to specify + details of the sample and its preparation. + + + + + ISO8601 date with time zone (UTC offset) specified. + + + + + Description of the substrate. + + + + + Specify the sample orientation. + + + + + + Measured data, data errors, and varied parameters. If reference data + were measured they should be considered a separate experiment and a + link to its NeXus file should be added in reference_data_link. + + + + An identifier to correlate data to the experimental conditions, + if several were used in this measurement; typically an index of 0-N. + + + + + Select which type of data was recorded, for example intensity, + reflectivity, transmittance, Psi and Delta etc. + It is possible to have multiple selections. The enumeration list + depends on the type of experiment and may differ for different + application definitions. + + + + + + + + + + + + + + + + + Spectral values (e.g. wavelength or energy) used for the measurement. + An array of 1 or more elements. Length defines N_spectrum. Replace + 'SPECTRUM' by the physical quantity that is used, e.g. wavelength. + + + + + + + If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. + If the unit of the measured data is not covered by NXDL units state + here which unit was used. + + + + + + Resulting data from the measurement, described by 'data_type'. + + The first dimension is defined by the number of measurements taken, + (N_measurements). The instructions on how to order the values + contained in the parameter vectors given in the doc string of + INSTRUMENT/sample_stage/environment_conditions/PARAMETER/values, + define the N_measurements parameter sets. For example, if the + experiment was performed at three different temperatures + (T1, T2, T3), two different pressures (p1, p2) and two different + angles of incidence (a1, a2), the first measurement was taken at the + parameters {a1,p1,T1}, the second measurement at {a1,p1,T2} etc. + + + + + + + + + If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. + If the unit of the measured data is not covered by NXDL units state + here which unit was used. + + + + + + Specified uncertainties (errors) of the data described by 'data_type' + and provided in 'measured_data'. + + + + + + + + + If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. + If the unit of the measured data is not covered by NXDL units state + here which unit was used. + + + + + + List of links to the values of the sensors. Add a link for each + varied parameter (i.e. for each sensor). + + + + + + + + Link to the NeXus file which describes the reference data if a + reference measurement was performed. Ideally, the reference + measurement was performed using the same conditions as the actual + measurement and should be as close in time to the actual measurement + as possible. + + + + + + Commercial or otherwise defined given name of the program that was + used to generate the result file(s) with measured data and/or + metadata (in most cases, this is the same as INSTRUMENT/software). + If home written, one can provide the actual steps in the NOTE + subfield here. + + + + + Either version with build number, commit hash, or description of a + (online) repository where the source code of the program and build + instructions can be found so that the program can be configured in + such a way that result files can be created ideally in a + deterministic manner. + + + + + Website of the software. + + + + + + A plot of the multi-dimensional data array provided in + ENTRY/data/measured_data. + + + + Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) + + + + + + + Parameters that are derived from the measured data. + + + + Light loss due to depolarization as a value in [0-1]. + + + + + + + + + + Jones quality factor. + + + + + + + + + + Reflectivity. + + + + + + + + + + Transmittance. + + + + + + + + + + + Commercial or otherwise defined given name of the program that was + used to generate or calculate the derived parameters. + If home written, one can provide the actual steps in the NOTE + subfield here. + + + + + Either version with build number, commit hash, or description of a + (online) repository where the source code of the program and build + instructions can be found so that the program can be configured in + such a way that result files can be created ideally in a + deterministic manner. + + + + + + + A default view of the data provided in ENTRY/data_collection/measured_data. This + should be the part of the data set which provides the most suitable + representation of the data. + + + + Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) + + + + + diff --git a/contributed_definitions/NXroi.nxdl.xml b/contributed_definitions/NXroi.nxdl.xml deleted file mode 100644 index b77834bb6..000000000 --- a/contributed_definitions/NXroi.nxdl.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - Base class to describe a region-of-interest analyzed. - - - - Details about processing steps. - - - - diff --git a/contributed_definitions/NXslip_system_set.nxdl.xml b/contributed_definitions/NXslip_system_set.nxdl.xml new file mode 100644 index 000000000..8fafee2e4 --- /dev/null +++ b/contributed_definitions/NXslip_system_set.nxdl.xml @@ -0,0 +1,85 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Number of slip systems. + + + + + Base class for describing a set of crystallographic slip systems. + + + + + + + + + + + + + + + + + + Array of Miller indices which describe the crystallographic plane. + + + + + + + + + + Array of Miller indices which describe the crystallographic direction. + + + + + + + + + For each slip system a marker whether the specified Miller indices + refer to the specific slip system or the set of crystallographic equivalent + slip systems of the respective family of slip systems. + + + + + + From 09da5231a5998f23598d5324a9c52518d985047b Mon Sep 17 00:00:00 2001 From: sanbrock Date: Thu, 3 Oct 2024 14:35:25 +0200 Subject: [PATCH 121/136] using nameType="partial" and "any" according to their new meaning # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 61 +++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 3abf139c3..afbc99014 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -148,7 +148,7 @@ def get_nx_class(nxdl_elem): return nxdl_elem.attrib.get("type", "NX_CHAR") -def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False) -> int: +def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False, name_partial: bool = False) -> int: """ Checks if an HDF5 node name corresponds to a child of the NXDL element. A group of uppercase letters anywhere in the name is treated as freely choosable @@ -211,8 +211,12 @@ def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False) -> int: for s1, s2 in zip(uppercase.upper(), match.upper()): if s1 == s2: match_count += 1 - - return len(name) + match_count - uppercase_count + + if name_partial: + return len(name) + match_count - uppercase_count + elif name_any: + return match_count + return -1 def get_nx_classes(): @@ -304,10 +308,13 @@ def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): return True if not hdf_name: # search for name fits is only allowed for hdf_nodes return False - try: # check if nameType allows different name - name_any = bool(child.attrib["nameType"] == "any") - except KeyError: - name_any = False + name_any = ("nameType" in child.attrib.keys() + and child.attrib["nameType"] == "any" + ) or ( + get_local_name_from_xml(child) == "group" + and "nameType" not in child.attrib.keys() + and "name" not in child.attrib.keys() + ) params = [act_htmlname, chk_name, name_any, nxdl_elem, child, name] return belongs_to_capital(params) @@ -316,12 +323,20 @@ def belongs_to_capital(params): """Checking continues for Upper case""" (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params # or starts with capital and no reserved words used + name_partial = ( + "nameType" in child.attrib.keys() + and child.attrib["nameType"] == "partial" + ) or ( + get_local_name_from_xml(child) == "group" + and "nameType" not in child.attrib.keys() + and "name" not in child.attrib.keys() + ) if ( - (name_any or (act_htmlname[0].isalpha() and act_htmlname[0].isupper())) + (name_any or name_partial) and name != "doc" and name != "enumeration" ): - fit = get_nx_namefit(chk_name, act_htmlname, name_any) # check if name fits + fit = get_nx_namefit(chk_name, act_htmlname, name_any=name_any, name_partial=name_partial) # check if name fits if fit < 0: return False for child2 in nxdl_elem: @@ -333,8 +348,17 @@ def belongs_to_capital(params): ): continue # check if the name of another sibling fits better - name_any2 = child2.attrib.get("nameType") == "any" - fit2 = get_nx_namefit(chk_name, get_node_name(child2), name_any2) + name_any2 = child2.attrib.get("nameType") == "any" or ( + get_local_name_from_xml(child2) == "group" + and "nameType" not in child2.attrib.keys() + and "name" not in child2.attrib.keys() + ) + name_partial2 = ( + "nameType" in child2.attrib.keys() + and child2.attrib["nameType"] == "partial" + ) + if name_partial2 or name_any2: + fit2 = get_nx_namefit(chk_name, get_node_name(child2), name_any=name_any2, name_partial=name_partial2) if fit2 > fit: return False # accept this fit @@ -822,10 +846,19 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): nexus_type != "group" or get_nx_class(child) == hdf_class_name ): name_any = ( - "nameType" in nxdl_elem.attrib.keys() - and nxdl_elem.attrib["nameType"] == "any" + "nameType" in child.attrib.keys() + and child.attrib["nameType"] == "any" + ) or ( + nexus_type == "group" + and "nameType" not in child.attrib.keys() + and "name" not in child.attrib.keys() + ) + name_partial = ( + "nameType" in child.attrib.keys() + and child.attrib["nameType"] == "partial" ) - fit = get_nx_namefit(hdf_name, get_node_name(child), name_any) + if name_partial or name_any: + fit = get_nx_namefit(hdf_name, get_node_name(child), name_any=name_any, name_partial=name_partial) if fit > bestfit: bestfit = fit bestchild = set_nxdlpath(child, nxdl_elem) From 455f86c8c782ec0950ab6b77e0af10a87eaadeaf Mon Sep 17 00:00:00 2001 From: sanbrock Date: Thu, 3 Oct 2024 14:38:27 +0200 Subject: [PATCH 122/136] linting # Conflicts: # dev_tools/tests/test_nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 58 ++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index afbc99014..74f5d7863 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -148,7 +148,9 @@ def get_nx_class(nxdl_elem): return nxdl_elem.attrib.get("type", "NX_CHAR") -def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False, name_partial: bool = False) -> int: +def get_nx_namefit( + hdf_name: str, name: str, name_any: bool = False, name_partial: bool = False +) -> int: """ Checks if an HDF5 node name corresponds to a child of the NXDL element. A group of uppercase letters anywhere in the name is treated as freely choosable @@ -211,7 +213,7 @@ def get_nx_namefit(hdf_name: str, name: str, name_any: bool = False, name_partia for s1, s2 in zip(uppercase.upper(), match.upper()): if s1 == s2: match_count += 1 - + if name_partial: return len(name) + match_count - uppercase_count elif name_any: @@ -308,10 +310,10 @@ def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): return True if not hdf_name: # search for name fits is only allowed for hdf_nodes return False - name_any = ("nameType" in child.attrib.keys() - and child.attrib["nameType"] == "any" + name_any = ( + "nameType" in child.attrib.keys() and child.attrib["nameType"] == "any" ) or ( - get_local_name_from_xml(child) == "group" + get_local_name_from_xml(child) == "group" and "nameType" not in child.attrib.keys() and "name" not in child.attrib.keys() ) @@ -323,20 +325,17 @@ def belongs_to_capital(params): """Checking continues for Upper case""" (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params # or starts with capital and no reserved words used - name_partial = ( - "nameType" in child.attrib.keys() - and child.attrib["nameType"] == "partial" + name_partial = ( + "nameType" in child.attrib.keys() and child.attrib["nameType"] == "partial" ) or ( - get_local_name_from_xml(child) == "group" - and "nameType" not in child.attrib.keys() - and "name" not in child.attrib.keys() + get_local_name_from_xml(child) == "group" + and "nameType" not in child.attrib.keys() + and "name" not in child.attrib.keys() ) - if ( - (name_any or name_partial) - and name != "doc" - and name != "enumeration" - ): - fit = get_nx_namefit(chk_name, act_htmlname, name_any=name_any, name_partial=name_partial) # check if name fits + if (name_any or name_partial) and name != "doc" and name != "enumeration": + fit = get_nx_namefit( + chk_name, act_htmlname, name_any=name_any, name_partial=name_partial + ) # check if name fits if fit < 0: return False for child2 in nxdl_elem: @@ -349,16 +348,21 @@ def belongs_to_capital(params): continue # check if the name of another sibling fits better name_any2 = child2.attrib.get("nameType") == "any" or ( - get_local_name_from_xml(child2) == "group" + get_local_name_from_xml(child2) == "group" and "nameType" not in child2.attrib.keys() and "name" not in child2.attrib.keys() ) - name_partial2 = ( + name_partial2 = ( "nameType" in child2.attrib.keys() and child2.attrib["nameType"] == "partial" ) if name_partial2 or name_any2: - fit2 = get_nx_namefit(chk_name, get_node_name(child2), name_any=name_any2, name_partial=name_partial2) + fit2 = get_nx_namefit( + chk_name, + get_node_name(child2), + name_any=name_any2, + name_partial=name_partial2, + ) if fit2 > fit: return False # accept this fit @@ -846,19 +850,23 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): nexus_type != "group" or get_nx_class(child) == hdf_class_name ): name_any = ( - "nameType" in child.attrib.keys() - and child.attrib["nameType"] == "any" + "nameType" in child.attrib.keys() and child.attrib["nameType"] == "any" ) or ( - nexus_type == "group" + nexus_type == "group" and "nameType" not in child.attrib.keys() and "name" not in child.attrib.keys() ) - name_partial = ( + name_partial = ( "nameType" in child.attrib.keys() and child.attrib["nameType"] == "partial" ) if name_partial or name_any: - fit = get_nx_namefit(hdf_name, get_node_name(child), name_any=name_any, name_partial=name_partial) + fit = get_nx_namefit( + hdf_name, + get_node_name(child), + name_any=name_any, + name_partial=name_partial, + ) if fit > bestfit: bestfit = fit bestchild = set_nxdlpath(child, nxdl_elem) From a1a3cc5f24153c349aec52046ad4a0b3d1c597da Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 4 Oct 2024 09:59:13 +0200 Subject: [PATCH 123/136] revert unintentional changes from cherry-pick --- MANIFEST.in | 4 - build/manual/source/conf.py | 100 ---- .../NXcomponent_em.nxdl.xml | 69 --- .../NXcoordinate_system_em_ebsd.nxdl.xml | 225 --------- contributed_definitions/NXcs_cpu_obj.nxdl.xml | 39 -- contributed_definitions/NXcs_cpu_sys.nxdl.xml | 48 -- contributed_definitions/NXcs_gpu_obj.nxdl.xml | 39 -- contributed_definitions/NXcs_gpu_sys.nxdl.xml | 47 -- contributed_definitions/NXem_base.nxdl.xml | 389 --------------- .../NXem_conventions_ebsd.nxdl.xml | 230 --------- contributed_definitions/NXms_ipf.nxdl.xml | 383 --------------- contributed_definitions/NXms_ipf_set.nxdl.xml | 33 -- contributed_definitions/NXms_odf_set.nxdl.xml | 33 -- contributed_definitions/NXms_pf_set.nxdl.xml | 33 -- contributed_definitions/NXms_recon.nxdl.xml | 454 ------------------ contributed_definitions/nyaml/NXatom_set.yaml | 104 ---- .../nyaml/NXcg_primitive_set.yaml | 136 ------ .../nyaml/NXcomponent_em.yaml | 39 -- .../nyaml/NXcoordinate_system.yaml | 86 ---- .../nyaml/NXcoordinate_system_em_ebsd.yaml | 120 ----- .../nyaml/NXcrystal_structure.yaml | 178 ------- .../nyaml/NXcs_cpu_obj.yaml | 12 - .../nyaml/NXcs_cpu_sys.yaml | 21 - .../nyaml/NXcs_gpu_obj.yaml | 12 - .../nyaml/NXcs_gpu_sys.yaml | 20 - .../nyaml/NXcs_mm_obj.yaml | 21 - contributed_definitions/nyaml/NXem_adf.yaml | 19 - contributed_definitions/nyaml/NXem_base.yaml | 297 ------------ .../nyaml/NXem_conventions.yaml | 296 ------------ .../nyaml/NXem_conventions_ebsd.yaml | 125 ----- .../nyaml/NXem_correlation.yaml | 191 -------- contributed_definitions/nyaml/NXem_eels.yaml | 42 -- contributed_definitions/nyaml/NXem_msr.yaml | 63 --- .../NXmicrostructure_gragles_results.yaml | 10 - .../nyaml/NXmicrostructure_slip_system.yaml | 46 -- contributed_definitions/nyaml/NXms_ipf.yaml | 299 ------------ .../nyaml/NXms_ipf_set.yaml | 9 - .../nyaml/NXms_mtex_config.yaml | 187 -------- contributed_definitions/nyaml/NXms_odf.yaml | 99 ---- .../nyaml/NXms_odf_set.yaml | 9 - contributed_definitions/nyaml/NXms_pf.yaml | 59 --- .../nyaml/NXms_pf_set.yaml | 9 - contributed_definitions/nyaml/NXms_recon.yaml | 315 ------------ contributed_definitions/nyaml/NXroi.yaml | 9 - requirements.txt | 2 +- 45 files changed, 1 insertion(+), 4960 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 build/manual/source/conf.py delete mode 100644 contributed_definitions/NXcomponent_em.nxdl.xml delete mode 100644 contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml delete mode 100644 contributed_definitions/NXcs_cpu_obj.nxdl.xml delete mode 100644 contributed_definitions/NXcs_cpu_sys.nxdl.xml delete mode 100644 contributed_definitions/NXcs_gpu_obj.nxdl.xml delete mode 100644 contributed_definitions/NXcs_gpu_sys.nxdl.xml delete mode 100644 contributed_definitions/NXem_base.nxdl.xml delete mode 100644 contributed_definitions/NXem_conventions_ebsd.nxdl.xml delete mode 100644 contributed_definitions/NXms_ipf.nxdl.xml delete mode 100644 contributed_definitions/NXms_ipf_set.nxdl.xml delete mode 100644 contributed_definitions/NXms_odf_set.nxdl.xml delete mode 100644 contributed_definitions/NXms_pf_set.nxdl.xml delete mode 100644 contributed_definitions/NXms_recon.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXatom_set.yaml delete mode 100644 contributed_definitions/nyaml/NXcg_primitive_set.yaml delete mode 100644 contributed_definitions/nyaml/NXcomponent_em.yaml delete mode 100644 contributed_definitions/nyaml/NXcoordinate_system.yaml delete mode 100644 contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml delete mode 100644 contributed_definitions/nyaml/NXcrystal_structure.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_cpu_obj.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_cpu_sys.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_gpu_obj.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_gpu_sys.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_mm_obj.yaml delete mode 100644 contributed_definitions/nyaml/NXem_adf.yaml delete mode 100644 contributed_definitions/nyaml/NXem_base.yaml delete mode 100644 contributed_definitions/nyaml/NXem_conventions.yaml delete mode 100644 contributed_definitions/nyaml/NXem_conventions_ebsd.yaml delete mode 100644 contributed_definitions/nyaml/NXem_correlation.yaml delete mode 100644 contributed_definitions/nyaml/NXem_eels.yaml delete mode 100644 contributed_definitions/nyaml/NXem_msr.yaml delete mode 100644 contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml delete mode 100644 contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml delete mode 100644 contributed_definitions/nyaml/NXms_ipf.yaml delete mode 100644 contributed_definitions/nyaml/NXms_ipf_set.yaml delete mode 100644 contributed_definitions/nyaml/NXms_mtex_config.yaml delete mode 100644 contributed_definitions/nyaml/NXms_odf.yaml delete mode 100644 contributed_definitions/nyaml/NXms_odf_set.yaml delete mode 100644 contributed_definitions/nyaml/NXms_pf.yaml delete mode 100644 contributed_definitions/nyaml/NXms_pf_set.yaml delete mode 100644 contributed_definitions/nyaml/NXms_recon.yaml delete mode 100644 contributed_definitions/nyaml/NXroi.yaml diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 20485f628..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -recursive-include applications/ *.nxdl.xml -recursive-include contributed_definitions/ *.nxdl.xml -recursive-include base_classes/ *.nxdl.xml -include ./ *.xsd \ No newline at end of file diff --git a/build/manual/source/conf.py b/build/manual/source/conf.py deleted file mode 100644 index f6d05e297..000000000 --- a/build/manual/source/conf.py +++ /dev/null @@ -1,100 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -import sys, os, datetime - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- Project information ----------------------------------------------------- - -project = 'nexus' -author = 'NIAC, https://www.nexusformat.org' -copyright = u'1996-{}, {}'.format(datetime.datetime.now().year, author) -description = u'NeXus: A Common Data Format for Neutron, X-ray, and Muon Science' - -# The full version, including alpha/beta/rc tags -version = u'unknown NXDL version' -release = u'unknown NXDL release' -nxdl_version = open('../../NXDL_VERSION').read().strip() -if nxdl_version is not None: - version = nxdl_version.split('.')[0] - release = nxdl_version - - -# -- General configuration --------------------------------------------------- - -# https://github.com/nexusformat/definitions/issues/659#issuecomment-577438319 -needs_sphinx = '2.3' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.mathjax', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', - 'sphinx.ext.githubpages', - 'sphinx.ext.todo', - 'sphinx_tabs.tabs' -] - -# Show `.. todo` directives in the output -# todo_include_todos = True - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -# html_theme = 'alabaster' -html_theme = 'sphinxdoc' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add extra files -html_extra_path = ['CNAME'] - -html_sidebars = { - '**': [ - 'localtoc.html', - 'relations.html', - 'sourcelink.html', - 'searchbox.html', - 'google_search.html' - ], -} - -# Output file base name for HTML help builder. -htmlhelp_basename = 'NeXusManualdoc' - -# -- Options for Latex output ------------------------------------------------- -latex_elements = { - 'maxlistdepth':25, # some application definitions are deeply nested - 'preamble': r''' - \usepackage{amsbsy} - \usepackage[utf8]{inputenc}''' -} diff --git a/contributed_definitions/NXcomponent_em.nxdl.xml b/contributed_definitions/NXcomponent_em.nxdl.xml deleted file mode 100644 index bedba8b6f..000000000 --- a/contributed_definitions/NXcomponent_em.nxdl.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - Base class for components used in an electron microscope. - - The electron microscope can be a real one or a simulated microscope. - The key motivation behind this generalization is the observation that in all - cases a controlled electron beam is generated in reality or that beam is simulated - and this beam is then used or modified in a controlled manner for the purpose - of studying physical interaction mechanisms of the beam with matter. - Here it does not matter whether one considers a real specimen or a simulated one. - - Using a common description for the real experiment in the lab and - what is - typically a simplification of it - via a computer simulation, has the benefit - that many pieces of information can be stored in the same way. In effect, - users are guided with finding information and unnecessary descriptive - variety for what are exactly the same concept is avoided to work towards - more interoperability. - - Another motivation to make no fundamental distinction between a scanning and - a transmission electron microscope is that both are electron microscopes whose - components are often very similar. - - - - Given name to the component e.g stage, lens C1, etc. - - - - - Ideally, a (globally) unique persistent identifier, link, or text to a - resource which gives further details to this component. - If such resource does not exist, a free-text field to report - further details about the component is possible. - - - - - - - Collection of axis-based translations and rotations to describe the - location and geometry of the component in the instrument. - - - diff --git a/contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml b/contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml deleted file mode 100644 index 8c0c49ace..000000000 --- a/contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - Base class for method-specific conventions EBSD. - - Solves the key issue that currently conventions used for collecting and interpreting - EBSD data are not always explicitly communicating which limits interoperability and - reusability of EBSD data. - - - - Details about the gnomonic projection reference frame. - - - - Type of coordinate system/reference frame used for identifying - positions in the gnomonic projection space Xg, Yg, Zg - according to DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - Handedness of coordinate system. - - - - - - - - - Is the origin of the gnomonic coordinate system located - where we assume the location of the pattern centre. - This is the location Xg = 0, Yg = 0, Zg = 0 according to - reference DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - Direction of the positively pointing "gnomomic" x-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - - - - - - - - - - - - - - Direction of the positively pointing "gnomomic" y-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - Direction of the positively pointing "gnomomic" z-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - - Details about the definition of the pattern centre - as a special point in the gnomonic projection reference frame. - - - - From which border of the EBSP (in the detector reference frame) - is the pattern centre's x-position (PCx) measured? - Keywords assume the region-of-interest is defined by - a rectangle. We observe this rectangle and inspect the - direction of the outer-unit normals to the edges of - this rectangle. - - - - - - - - - - - - In which direction are positive values for PCx measured from - the specified boundary. Keep in mind that the gnomonic space - is in virtually all cases embedded in the detector space. - Specifically, the XgYg plane is defined such that it is - embedded/laying inside the XdYd plane (of the detector - reference frame). - When the normalization direction is the same as e.g. the - detector x-axis direction, we state that we effectively - normalize in fractions of the width of the detector. - - The issue with terms like width and height is that these - degenerate if the detector region-of-interest is square-shaped. - This is why we should better avoid talking about width and height but - state how we would measure distances practically with a ruler and - how we then measure positive distances. - - - - - - - - - - - - From which border of the EBSP (in the detector reference - frame) is the pattern centre's y-position (PCy) measured? - For further details inspect the help button of - xaxis_boundary_convention. - - - - - - - - - - - - In which direction are positive values for PCy measured from - the specified boundary. - For further details inspect the help button of - xaxis_normalization_direction. - - - - - - - - - - - - diff --git a/contributed_definitions/NXcs_cpu_obj.nxdl.xml b/contributed_definitions/NXcs_cpu_obj.nxdl.xml deleted file mode 100644 index 6ce5370a3..000000000 --- a/contributed_definitions/NXcs_cpu_obj.nxdl.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a (central) processing unit (C)PU of a computer. - - - - Given name of the CPU. Users should be as specific as possible. - - - - diff --git a/contributed_definitions/NXcs_cpu_sys.nxdl.xml b/contributed_definitions/NXcs_cpu_sys.nxdl.xml deleted file mode 100644 index 0de162c66..000000000 --- a/contributed_definitions/NXcs_cpu_sys.nxdl.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a system of classical central processing units. - - For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. - - - - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single CPU one - could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of - :ref:`NXcs_cpu_sys`. - A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` - inside one instance of :ref:`NXcs_cpu_sys`. - A server with two dual-socket server nodes one could describe - with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. - - - diff --git a/contributed_definitions/NXcs_gpu_obj.nxdl.xml b/contributed_definitions/NXcs_gpu_obj.nxdl.xml deleted file mode 100644 index 3c5b6c26a..000000000 --- a/contributed_definitions/NXcs_gpu_obj.nxdl.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a graphic processing unit (GPU) of a computer. - - - - Given name of the GPU. Users should be as specific as possible. - - - - diff --git a/contributed_definitions/NXcs_gpu_sys.nxdl.xml b/contributed_definitions/NXcs_gpu_sys.nxdl.xml deleted file mode 100644 index 217f1adb2..000000000 --- a/contributed_definitions/NXcs_gpu_sys.nxdl.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a system of coprocessor or graphics processors. - - - - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single GPU one - could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of - :ref:`NXcs_gpu_sys`. - A desktop computer with two GPUs one could describe using two instances - of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. - A GPU server like nowadays used for artificial intelligence - one could describe as a system with n instances of :ref:`NXcs_gpu_obj` - in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. - - - diff --git a/contributed_definitions/NXem_base.nxdl.xml b/contributed_definitions/NXem_base.nxdl.xml deleted file mode 100644 index 479819893..000000000 --- a/contributed_definitions/NXem_base.nxdl.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. - - This base class combines a method-specific and technical-design-level base class - instance to provide a template for storing parameterized descriptions of - pieces of information collected when performing electron microscopy research. - - The base class here shows all possible branches without making any statements - as to which of these have to be used in an instance. Thereby, the base class - provides a template how to name and structure concepts in a hierarchy - to support finding information and reducing the need for renaming and - restructuring information for a research field where many scientists perform - very specific research but who all also share commonalities like usage of - controlled electron beams, a focus on studies of electron beam matter interaction - to explore physical mechanisms and phenomena, or the desire to characterize materials - using electron microscopy. - - - - A collection of all programs and libraries which are considered relevant - to understand with which software tools this NeXus file instance was - generated. Ideally, to enable a binary recreation from the input data. - - Examples include the name and version of the libraries used to write the - instance. Ideally, the software that writes these :ref:`NXprogram` instances - also includes the version of the set of NeXus classes i.e. the specific - set of base classes, application definitions, and contributed definitions - with which the here described concepts can be resolved. - - For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ - which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ - research data management system, it makes sense to store e.g. the GitHub - repository commit and respective submodule references used. - - - - - - The configuration of the I/O writer software (e.g. `pynxtools <https://github.com/FAIRmat-NFDI/pynxtools>`_) - which was used to generate this NeXus file instance. - - - - - - An at least as strong as SHA256 hashvalue of the file - which specifies the application definition. - - - - - NeXus NXDL schema to which this file conforms. - - - - - - - - Ideally, a (globally) unique persistent identifier - for referring to this experiment. - - An experiment should be understood in that this can be an experiment - in reality or a computer simulation because also the latter is an - experiment (see the Cambridge Dictionary experiment: - *a test done in order to find out something, eg if an idea is correct*). - - The identifier is usually issued by the facility, laboratory, - or the principle investigator. The identifier enables to link - experiments/simulations to e.g. proposals. - - - - - Free-text description about the experiment. - - Users are strongly advised to parameterize their description of the - experiment by using the respective base classes instead of writing prose - into this field. - - The reason is that such free-text field is difficult to machine-interpret. - The motivation behind keeping this field for now is to learn through - the information entered in this field in how far the current base - classes are incomplete. - - - - - ISO 8601 time code with local time zone offset to UTC information included - when the microscope session started. If the application demands that time - codes in this section of the application definition should only be used - for specifying when the experiment was performed - and the exact - duration is not relevant - this start_time field should be used. - - Often though it is useful to specify a time interval via setting both - a start_time and an end_time because this enables software tools and - users to collect a more detailed bookkeeping of the experiment. - - The user should be aware that even with having both time instances specified, - it may not be possible to infer how long the experiment took or for how - long data were acquired. - - More detailed timing data over the course of the experiment have - to be collected to compute this. These computations can take - advantage of individual time stamps start_time and end_time - in :ref:`NXevent_data_em` instances. - - - - - ISO 8601 time code with local time zone offset to UTC included when - the microscope session ended. See docstring of the start_time field - to see how the start_time and end_time should be used together. - - - - - - The program and eventual software libraries used with which the - NeXus instance was created. For the NOMAD OASIS research data - management system e.g. pynxtools and eventually all modules - if desired. - - - - - - Possibility to store a collection of data artifacts - associated with the experiment. - - - - - - Contact information and eventually details of at least one person - who performed or was involved in the session. This can be the - principle investigator who performed this experiment or the student - who performed the simulation. - Adding multiple users if relevant is recommended. - - - - Given (first) name and surname of the user. - - - - - Name of the affiliation of the user at the point in time - when the experiment was performed. - - - - - Postal address of the affiliation. - - - - - Email address of the user at the point in time when the experiment - was performed. Writing the most permanently used email is recommended. - - - - - Service as another mean of identification of a user than by the name. - Examples could be details about an ORCID or social media account of - the user. - - - - - (Business) (tele)phone number of the user at the point - in time when the experiment was performed. - - - - - Which role does the user have in the place and at the point - in time when the experiment was performed? Technician operating - the microscope, student, postdoc, principle investigator, or guest - are common examples. - - - - - - - A description of the material characterized in the experiment. - Sample and specimen are threaded as de facto synonyms. - Samples can be real specimens or virtual (see method). - - - - A qualifier whether the sample is a real one or a - virtual one (in a computer simulation) - - - - - - - - - - Ideally, (globally) unique persistent identifier which distinguishes - the specimen from all others and especially the predecessor/origin - from where the specimen was cut. - - This field must not be used for an alias! Instead, use name. - - In cases where multiple specimens were loaded into the microscope, - the identifier has to resolve the specific sample, whose results are - stored by this :ref:`NXentry` instance, because a single NXentry should be - used only for the characterization of a single specimen. - - Details about the specimen preparation should be - stored in resources referring to parent_identifier. - - - - - Identifier of the sample from which the sample was cut or the string - *None*. The purpose of this field is to support functionalities - for tracking sample provenance via a research data management system. - - - - - ISO 8601 time code with local time zone offset to UTC information - when the specimen was prepared. - - Ideally, report the end of the preparation, i.e. the last known time - the measured specimen surface was actively prepared. Ideally, this - matches the last timestamp that is mentioned in the digital resource - pointed to by parent_identifier. - - Knowing when the specimen was exposed to e.g. specific atmosphere is - especially required for environmentally sensitive material such as - hydrogen charged specimens or experiments including tracers with a - short half time. Additional time stamps prior to preparation_date - should better be placed in resources which describe but which do not pollute - the description here with prose. Resolving these connected pieces of information - is considered within the responsibility of the research data management - system. - - - - - An alias used to refer to the specimen to please readability for humans. - - - - - List of comma-separated elements from the periodic table that are - contained in the sample. If the sample substance has multiple - components, all elements from each component must be included in - `atom_types`. - - The purpose of the field is to offer research data management systems an - opportunity to parse the relevant elements without having to interpret - these from the resources pointed to by parent_identifier or walk through - eventually deeply nested groups in data instances. - - - - - - (Measured) sample thickness. - - The information is recorded to qualify if the beam used was likely - able to shine through the specimen. For scanning electron microscopy, - in many cases the specimen is typically thicker than what is - illuminatable by the electron beam. - - In this case the value should be set to the actual thickness of - the specimen viewed for an illumination situation where the nominal - surface normal of the specimen is parallel to the optical axis. - - - - - - - (Measured) density of the specimen. - - For multi-layered specimens this field should only be used to describe - the density of the excited volume. For scanning electron microscopy - the usage of this field is discouraged and instead an instance of an - :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` - instances can provide a cleaner description of the relevant details - why one may wish to store the density of the specimen. - - - - - Discouraged free-text field to provide further detail although adding - parent_identifier and having a working research data management system - should provide this contextualization. - - - - - - - - - - - - A region-of-interest analyzed either during or after the session - for which specific processed data generated from the measured or the - simulated data are available. - - - - - - - - - - - - diff --git a/contributed_definitions/NXem_conventions_ebsd.nxdl.xml b/contributed_definitions/NXem_conventions_ebsd.nxdl.xml deleted file mode 100644 index 8a19f1e29..000000000 --- a/contributed_definitions/NXem_conventions_ebsd.nxdl.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - Base class for method-specific conventions EBSD. - - This base class is expected to be used with :ref:`NXem_conventions`. - - This is the main issue which currently is not in all cases documented - and thus limits the interoperability and value of collected EBSD data. - Not communicating EBSD data with such contextual pieces of information - and the use of file formats which do not store this information is the - key unsolved problem. - - - - Details about the gnomonic projection reference frame. - - - - Type of coordinate system/reference frame used for identifying - positions in the gnomonic projection space Xg, Yg, Zg - according to DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - Handedness of coordinate system. - - - - - - - - - Is the origin of the gnomonic coordinate system located - where we assume the location of the pattern centre. - This is the location Xg = 0, Yg = 0, Zg = 0 according to - reference DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - Direction of the positively pointing "gnomomic" x-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - - - - - - - - - - - - - - Direction of the positively pointing "gnomomic" y-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - Direction of the positively pointing "gnomomic" z-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - - Details about the definition of the pattern centre - as a special point in the gnomonic projection reference frame. - - - - From which border of the EBSP (in the detector reference frame) - is the pattern centre's x-position (PCx) measured? - Keywords assume the region-of-interest is defined by - a rectangle. We observe this rectangle and inspect the - direction of the outer-unit normals to the edges of - this rectangle. - - - - - - - - - - - - In which direction are positive values for PCx measured from - the specified boundary. Keep in mind that the gnomonic space - is in virtually all cases embedded in the detector space. - Specifically, the XgYg plane is defined such that it is - embedded/laying inside the XdYd plane (of the detector - reference frame). - When the normalization direction is the same as e.g. the - detector x-axis direction, we state that we effectively - normalize in fractions of the width of the detector. - - The issue with terms like width and height is that these - degenerate if the detector region-of-interest is square-shaped. - This is why we should better avoid talking about width and height but - state how we would measure distances practically with a ruler and - how we then measure positive distances. - - - - - - - - - - - - From which border of the EBSP (in the detector reference - frame) is the pattern centre's y-position (PCy) measured? - For further details inspect the help button of - xaxis_boundary_convention. - - - - - - - - - - - - In which direction are positive values for PCy measured from - the specified boundary. - For further details inspect the help button of - xaxis_normalization_direction. - - - - - - - - - - - - diff --git a/contributed_definitions/NXms_ipf.nxdl.xml b/contributed_definitions/NXms_ipf.nxdl.xml deleted file mode 100644 index 49568b0ac..000000000 --- a/contributed_definitions/NXms_ipf.nxdl.xml +++ /dev/null @@ -1,383 +0,0 @@ - - - - - - - - - Number of pixel along the z slowest direction. - - - - - Number of pixel along the y slow direction. - - - - - Number of pixel along the x fast direction. - - - - - Number of RGB values along the fastest direction, always three. - - - - - Dimensionality of the mapping (either 2 or 3). - - - - - Base class to store an inverse pole figure (IPF) mapping (IPF map). - - - - Reference to the coordinate system whereby the projection_direction is defined. - - If the field depends_on is not provided but a parent of the instance - of this base class or its specialization defines an :ref:`NXcoordinate_system_set` - and exactly one :ref:`NXcoordinate_system`, the reference points to this system. - - If nothing is provided and none of the above-mentioned references pointing - in a parent, McStas is assumed. - - - - - The direction along which orientations are projected. - - - - - - - - Details about the original grid. - - Here original grid means the one onto which the IPF map was computed - when exported from the tech partner's file format representation. - - - - - Details about the grid onto which the IPF is recomputed. - - Rescaling the visualization of the IPF map may be needed to enable - visualization in specific software tools like H5Web. - The value specifies the fractional change of the spacing between - the original mapping and the scaled one. - - - - - How where orientation values at the location of the output grid - positions computed. - - Nearest neighbour means the orientation of the closed (Euclidean distance) - grid point of the input_grid was taken. - - - - - - - - Inverse pole figure mapping. - - Default inverse pole figure (IPF) plot of the data specific for each - phase. No ipf_mapID instances for non-indexed scan points as these are - by definition assigned the null phase with phase_identifier 0. - Inspect the definition of :ref:`NXcrystal_structure` and its field - phase_identifier for further details. - - Details about possible regridding and associated interpolation - during the computation of the IPF map visualization can be stored - using the input_grid, output_grid, and interpolation fields. - - The main purpose of this map is to offer a normalized default representation - of the IPF map for consumption by a research data management system (RDMS). - This is aligned with the first aim of :ref:`NXms_ipf`, to bring colleagues and - users of IPF maps together to discuss which pieces of information - need to be stored together. We are convinced a step-by-step design and - community-driven discussion about which pieces of information should - and/or need to be included is a practical strategy to work towards an - interoperable description and data model for exchanging IPF maps as specific - community-accepted tools to convey orientation maps. - - With this design the individual RDMS solutions and tools can still continue - to support specific custom data analyses workflow and routes but at least - there is one common understanding which enables also those users who are - not necessarily experts in all the details of the underlying techniques - can understand and thus eventually judge if the dataset is worth to be - reused or repurposed. - - - - - - Inverse pole figure color code for each map coordinate. - - - - - - - - - - Pixel center coordinate calibrated for step size along the z axis of the map. - - - - - - - - - Pixel center coordinate calibrated for step size along the y axis of the map. - - - - - - - - - Pixel center coordinate calibrated for step size along the x axis of the map. - - - - - - - - - - The color code which maps colors into orientation into the fundamental zone. - - For each stereographic standard triangle (SST), i.e. a rendering of the - fundamental zone of the crystal-symmetry-reduced orientation space - SO3, it is possible to define a color model which assigns each point in - the fundamental zone a color. - - Different mapping models are used. These implement (slightly) different - scaling relations. Differences exist across representations of tech partners. - - Differences are which base colors of the RGB color model are placed in - which extremal position of the SST and where the white point is located. - - For further details see: - - * [G. Nolze et al.](https://doi.org/10.1107/S1600576716012942) - * Srikanth Patala and coworkers"'" work and of others. - - Details are implementation-specific and not standardized yet. - - Given that the SST has a complicated geometry, it cannot yet be - visualized using tools like H5Web, which is why for now the matrix - of a rasterized image which is rendered by the backend tool gets - copied into an RGB matrix to offer a default plot. - - - - - - Inverse pole figure color code for each map coordinate. - - - - - - - - - - Pixel along the y-axis. - - - - - - - - - Pixel along the x-axis. - - - - - - - - - diff --git a/contributed_definitions/NXms_ipf_set.nxdl.xml b/contributed_definitions/NXms_ipf_set.nxdl.xml deleted file mode 100644 index 776eb0a6c..000000000 --- a/contributed_definitions/NXms_ipf_set.nxdl.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - Base class to group multiple :ref:`NXms_ipf` instances. - - A collection of inverse pole figure approximations. - - - diff --git a/contributed_definitions/NXms_odf_set.nxdl.xml b/contributed_definitions/NXms_odf_set.nxdl.xml deleted file mode 100644 index d41a609a8..000000000 --- a/contributed_definitions/NXms_odf_set.nxdl.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - Base class to group multiple :ref:`NXms_odf` instances. - - A collection of orientation distribution function approximations. - - - diff --git a/contributed_definitions/NXms_pf_set.nxdl.xml b/contributed_definitions/NXms_pf_set.nxdl.xml deleted file mode 100644 index 3ca5fc000..000000000 --- a/contributed_definitions/NXms_pf_set.nxdl.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - Base class to group multiple :ref:`NXms_pf` instances. - - A collection of pole figure approximations. - - - diff --git a/contributed_definitions/NXms_recon.nxdl.xml b/contributed_definitions/NXms_recon.nxdl.xml deleted file mode 100644 index 99e629ba2..000000000 --- a/contributed_definitions/NXms_recon.nxdl.xml +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - - The number of crystal projections. - - - - - The number of interface projections. - - - - - The number of assumed triple junction projections aka triple points. - - - - - - The number of crystals. - - - - - The number of interfaces - - - - - The number of triple lines - - - - - The number of quadruple junctions. - - - - - Base class to describe discretized (micro)structural features of a material. - - One instance of this base class can be used to describe the current configuration - the base class does not include time-dependent descriptions for the sake of - clarity and because of the fact that virtually all simulations or experiments - probe time by sampling. Therefore, time-dependent state descriptions should - be realized with creating a set of :ref:`NXms_snapshot_set` with instances of - :ref:`NXms_snapshot` using e.g. :ref:`NXms_recon` base class instances. - - - - - The configuration and parameterization of the reconstruction algorithm - whereby the microstructural features were identified. - - - - - Dimensionality of the analysis. - - This field can be used e.g. by a research data management system - to identify if the described feature set specifies a - one-, two-, or three-dimensional feature set. - - - - - - - - - - Which algorithm is used to reconstruct the features. - - - - - - - - - - - Threshold to define at which disorientation angle to assume - two crystalline regions have a significant orientation difference - which warrants to argue that there is an interface between the - two regions. - - - - - - - - - - - - - Projections of crystals on the sample surface as typically - characterized with optical or electron microscopy. - - - - Reference to lines(NXcg_polyline_set) which supports the - discretized shape of each cross-sectioned crystal. - - Most microscopy techniques support to generate only a two-dimensional - representation (projection) of the characterized material. - - For true volumetric techniques use the specifically - specialized crystals :ref:`NXms_feature_set` instead. - See stereology literature for more details e.g. - E.E. Underwood's book entitled Quantitative Stereology - - - - - Number of crystals. - - - - - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - - - - - Identifier used for crystals for explicit indexing. - - - - - - - - How many phases are distinguished - - - - - Integer offset whereby the identifier of the first member - of the set differs from zero. - - - - - - Identifier used for phase for explicit indexing. - - - - - - - - - True, if the crystal makes contact with the edge of the ROI, - false otherwise. - - - - - - - - Average disorientation angle between individual orientation of the - crystal at probed positions (weighted by area of that position) versus - the average disorientation of the crystal. - - - - - - - - - Calibrated area of surrounded by the polyline about each crystal. - - - - - - - - - - Projections of grain or phase boundaries as typically sectioned - with optical or electron microscopy characterization. - - - - Reference to lines(NXcg_polyline_set) which supports the - discretized shape of each cross-sectioned crystal. - - Set of tuples of polyline segments which build the interface. - - - - - - Set of pairs of crystal_identifier resolved via depends_on which - are adjacent to each interface. - - - - - - - - The specific crystal_projections(NXms_feature_set) instance - to resolve crystal identifier. - - - - - - - Set of pairs of triple_point_identifier which the interface connects. - For 2D projections of 3D microstructural features a triple point is - physically only the projection of a triple line. - - - - - - - - The specific triple_line_projections(NXms_feature_set) instance - whereby to resolve triple_point identifier. - - - - - - - The length of the interface. - - This is not necessarily the same as the length of the individual - polyline segments whereby the interface is discretized. - - The actual coordinate system whereby the geometry is calibrated - with real physical dimensions is typically documented by the - depends_on attribute of the respective NXcg_primitive_set. - This depends_on attribute should point explicitly to an - instance of a :ref:`NXcoordinate_system` to support users as - much as possible with interpreting how and where the lines are - located in the reference frame. - - - - - - - - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - - - - - Identifier for each interface using explicit indexing. - - - - - - - - - - Projections of triple lines as typically characterized with optical - or electron microscopy. - - Mind that most specimens are thermo-chemo-mechanically treated before - they are characterized. Therefore, the projected crystal defects are - have physically no longer the same structure as in the bulk. - - Examples are manifest as effects such as thermal grooving, or relaxation - effects of an intersection between a triple line that is cut - by the specimen surface as these defects are then exposed typically - to a different atmosphere and hence have different thermodynamic boundary - conditions than of their true volumetric defects in the bulk. - - - - Reference to points(NXcg_point_set) which supports the - locations of these triple points. - - - - - - Number of triple points. - - - - - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - - - - - Identifier for each triple point using explicit indexing. - - - - - - - - Set of triple point identifiers. - - - - - - - The relevant points(NXcg_point_set) instance whereby to - resolve interface identifiers. - - - - - - Set of triplets of identifier of line-like features. - Each triplet resolves which three interface projections - the triple point connects. - - - - - - - - The specific interface_projections(NXms_feature_set) - instance whereby to resolve interface identifiers. - - - - - - - Triplet of identifier of polyline segments. Each triplet resolves - which three segments of polyline segments the triple junction connects. - - - - - - - - The specific lines(NXcg_polyline_set) instance to resolve - polyline segments. - - - - - - diff --git a/contributed_definitions/nyaml/NXatom_set.yaml b/contributed_definitions/nyaml/NXatom_set.yaml deleted file mode 100644 index 3e83a1bef..000000000 --- a/contributed_definitions/nyaml/NXatom_set.yaml +++ /dev/null @@ -1,104 +0,0 @@ -category: base -doc: | - Base class for documenting a set of atoms. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. - n_ivec_max: | - Maximum number of atoms/isotopes allowed per (molecular) ion (fragment). - n_ranges: | - Number of mass-to-charge-state-ratio range intervals for ion type. -type: group -NXatom_set(NXobject): - identifier(NX_CHAR): - doc: | - A unique identifier whereby such an ion can be referred to - via the service offered as described in identifier_type. - identifier_type(NX_CHAR): - doc: | - How can the identifier be resolved? - enumeration: [inchi] - ion_type(NX_UINT): - doc: | - Ion type (ion species) identifier. - - The identifier zero is reserved for the special unknown ion type. - unit: NX_UNITLESS - nuclide_hash(NX_UINT): - doc: | - Vector of nuclide hash values. - - Individual hash values :math:`H` is :math:`H = Z + N \cdot 256` with :math:`Z` - encode the number of protons :math:`Z` and the number of neutrons :math:`N` - of each nuclide respectively. :math:`Z` and :math:`N` have to be 8-bit unsigned integers. - - The array is sorted in decreasing order. For the rationale behind this see `M. Kühbach et al. (2021) `_ - unit: NX_UNITLESS - dim: (n_ivec_max,) - nuclide_list(NX_UINT): - doc: | - Table which decodes the entries in nuclide_hash into a human-readable matrix of instances. - The first column specifies the nuclide mass number, i.e. using the hashvalues - from the isotope_vector this is :math:`Z + N` or 0. The value 0 documents that no - isotope-specific information about the element encoded is relevant. - The second row specifies the number of protons :math:`Z` or 0. - The value 0 in this case documents a placeholder or that no element-specific - information is relevant. - Taking a carbon-14 nuclide as an example the mass number is 14. - That is encoded as a value pair (14, 6) as one row of the table. - - Therefore, this notation is the typical superscribed nuclide mass number - and subscripted number of protons element notation e.g. :math:`^{14}C`. - The array is stored matching the order of nuclide_hash. - unit: NX_UNITLESS - dim: (n_ivecmax, 2) - # color(NX_CHAR): - # doc: | - # Color code used for visualizing such ions. - volume(NX_NUMBER): - doc: | - Assumed volume of the ion. - - In atom probe microscopy this field can be used to store the reconstructed - volume per ion (average) which is typically stored alongside ranging - definitions. - unit: NX_VOLUME - charge(NX_NUMBER): - doc: | - Charge of the ion. - unit: NX_CHARGE - charge_state(NX_NUMBER): - doc: | - Signed charge state if the atoms form an ion reported in multiples of electron charge. - - In the example of atom probe microscopy, only positive values will be measured - as the ions are accelerated by a negatively signed bias electric field. - In the case that the charge state is not explicitly recoverable, the value should - be set to zero. - - In atom probe microscopy this is for example the case when using - classical ranging definition files in formats like RNG, RRNG. - These file formats do not document the charge state explicitly - but the number of atoms of each element per molecular ion - surplus the mass-to-charge-state-ratio interval. - Details on ranging definition files can be found in the literature: - `M. K. Miller `_ - unit: NX_UNITLESS - name(NX_CHAR): - doc: | - Human-readable name (e.g. Al +++) of the atom set, the atom group, or ion type. - The string should consists of UTF-8 characters, ideally using LaTeX - notation to specify the isotopes, ions, and charge state. - Examples are 12C + or Al +++. - - To ease automated parsing, isotope_vector should be the - preferred machine-readable information used. - mass_to_charge_range(NX_NUMBER): - doc: | - Associated lower (mqmin) and upper (mqmax) bounds of the - mass-to-charge-state ratio interval(s) [mqmin, mqmax] - (boundaries inclusive). This field is primarily of interest - for documenting :ref:`NXprocess` steps of indexing a - ToF/mass-to-charge state histogram. - unit: NX_ANY # u - dim: (n_ranges, 2) diff --git a/contributed_definitions/nyaml/NXcg_primitive_set.yaml b/contributed_definitions/nyaml/NXcg_primitive_set.yaml deleted file mode 100644 index 586929596..000000000 --- a/contributed_definitions/nyaml/NXcg_primitive_set.yaml +++ /dev/null @@ -1,136 +0,0 @@ -category: base -doc: | - Computational geometry description of a set of primitives in Euclidean space. - - Primitives must neither be degenerated nor self-intersect. - Individual primitives can differ in their properties (e.g. size, shape, rotation). -# this base class defines common fields and properties of geometric primitives -# more complex primitive sets like NXcg_cylinder_set are considered specializations -# of NXcg_primitive_set. They contain all fields and groups which NXcg_primitive_set -# defines. This is an action of compositing an information set; an act of inheriting -# TODO:: many properties of non-degenerate primitives are in the number set -# R+ instead of in R+0 but currently NeXus does not allow for such value range -# constraints unless the coarsely discretized NX_INT, NX_POSINT, NX_FLOAT -# but there is no say NX_FLOAT+0 -# MK::but in computational geometry numerical precision matters as it defines -# whether objects numerically intersect or not and thus it can make a real difference -# if one stores triangles with 16, 32, or 64 bit precision, however: -# are two triangle_set instance A and B no longer conceptually triangle sets -# because A stores the positions of vertices using int8 while B stores such using float64 ? -# we here assume that we still conceptually talk that A and B are triangle sets -# but this brings at the level of the application definition the problem that if the -# precision is not properly constrainted a consuming application will not obtain -# the instances of the concept triangle_set with relevant high enough precision -# and thus neither the base class nor the application definition is specific enough -# for what it was designed in the first place - be specific about the requirements -# on your data... -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. - d: | - The dimensionality of the space. - c: | - The cardinality of the set, i.e. the number of members. -type: group -NXcg_primitive_set(NXobject): - # individual specializations like NXcg_polyline_set typically overwrite - # the meaning of the depends_on concept to build consistent inference chains - # to enable an instantiation of the actual geometric primitives - \@depends_on(NX_CHAR): - doc: | - Hint to help resolve in which Euclidean coordinate system field values - like center or orientation are defined. - dimensionality(NX_POSINT): - doc: | - The dimensionality of the primitive set. - unit: NX_UNITLESS - enumeration: [1, 2, 3] - cardinality(NX_POSINT): - doc: | - The cardinality of the primitive set. - unit: NX_UNITLESS - identifier_offset(NX_INT): - doc: | - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - - Therefore, implicit identifier are completely defined by the value of - identifier_offset and cardinality. For example if identifier run from - -2 to 3 the value for identifier_offset is -2. - - For explicit indexing the field identifier has to be used. - Fortran-/Matlab- and C-/Python-style indexing have specific implicit - identifier conventions where identifier_offset is 1 and 0 respectively. - unit: NX_UNITLESS - identifier(NX_INT): - doc: | - Identifier of each member for explicit indexing. - dim: (c,) # numpy style indexing - center(NX_NUMBER): - doc: | - The center of mass position of each primitive. - unit: NX_ANY - dim: (c, d) - # a depends_on to define in which coordinate system - is_center_of_mass(NX_BOOLEAN): - doc: | - True if the center is a center of mass. - dim: (c,) - shape(NX_NUMBER): - doc: | - A qualitative description of the shape of each primitive. - unit: NX_LENGTH - dim: (c, d) - length(NX_NUMBER): - doc: | - Qualifier for the length of characteristic features of the primitive. - - Often the term length is associated with the assumption that one - edge is parallel to an axis of the coordinate system. - unit: NX_LENGTH - dim: (c,) - width(NX_NUMBER): - doc: | - Qualifier often used to describe the length of one characteristic edge - within the coordinate system. - unit: NX_LENGTH - dim: (c,) - is_closed(NX_BOOLEAN): - doc: | - True if primitive is closed such that it has properties like area or volume. - dim: (c,) - volume(NX_NUMBER): - doc: | - Volume of each primitive. - - Set to NaN if does not apply for primitives for which is_closed is False. - unit: NX_VOLUME - dim: (c,) - area(NX_NUMBER): - doc: | - Alias for surface_area of each primitive. - - Set to NaN if does not apply for primitives for which is_closed is False. - unit: NX_AREA - dim: (c,) - orientation(NX_NUMBER): - doc: | - Direction unit vector which points along the - longest principal axis of each primitive. - - Use the depends_on attribute to specify in which coordinate system - these direction unit vectors are defined. - unit: NX_DIMENSIONLESS - dim: (c, d) - vertex_normal(NXcg_unit_normal_set): - edge_normal(NXcg_unit_normal_set): - face_normal(NXcg_unit_normal_set): - # roi(NXcg_parallelogram_set or NXcg_hexahedron_set) - # aabb(NXcg_parallelogram_set or NXcg_hexahedron_set) - # obb(NXcg_parallelogram_set or NXcg_hexahedron_set) - # MK::one could add (NXcg_parallelogram_set) and/or (NXcg_hexahedron_set) - # but then one would not give any hint at the base class level how to name diff --git a/contributed_definitions/nyaml/NXcomponent_em.yaml b/contributed_definitions/nyaml/NXcomponent_em.yaml deleted file mode 100644 index 78870cc26..000000000 --- a/contributed_definitions/nyaml/NXcomponent_em.yaml +++ /dev/null @@ -1,39 +0,0 @@ -category: base -doc: | - Base class for components used in an electron microscope. - - The electron microscope can be a real one or a simulated microscope. - The key motivation behind this generalization is the observation that in all - cases a controlled electron beam is generated in reality or that beam is simulated - and this beam is then used or modified in a controlled manner for the purpose - of studying physical interaction mechanisms of the beam with matter. - Here it does not matter whether one considers a real specimen or a simulated one. - - Using a common description for the real experiment in the lab and - what is - typically a simplification of it - via a computer simulation, has the benefit - that many pieces of information can be stored in the same way. In effect, - users are guided with finding information and unnecessary descriptive - variety for what are exactly the same concept is avoided to work towards - more interoperability. - - Another motivation to make no fundamental distinction between a scanning and - a transmission electron microscope is that both are electron microscopes whose - components are often very similar. -# `point Electronic GmbH `_ -type: group -NXcomponent_em(NXobject): - name(NX_CHAR): - doc: | - Given name to the component e.g stage, lens C1, etc. - description(NX_CHAR): # NXidentifier - doc: | - Ideally, a (globally) unique persistent identifier, link, or text to a - resource which gives further details to this component. - If such resource does not exist, a free-text field to report - further details about the component is possible. - (NXfabrication): - (NXprogram): - (NXtransformations): - doc: | - Collection of axis-based translations and rotations to describe the - location and geometry of the component in the instrument. diff --git a/contributed_definitions/nyaml/NXcoordinate_system.yaml b/contributed_definitions/nyaml/NXcoordinate_system.yaml deleted file mode 100644 index b21939900..000000000 --- a/contributed_definitions/nyaml/NXcoordinate_system.yaml +++ /dev/null @@ -1,86 +0,0 @@ -category: base -doc: | - Base class to detail a coordinate system (CS). - - Whenever possible, an instance of :ref:`NXcoordinate_system` should be used as - a member in an :ref:`NXcoordinate_system_set` and the name of the instance - should be this alias. This may support a process whereby jargon when talking - about coordinate systems and conventions may become cleaner for users - because it is not evident for people outside a lab that terms like e.g. - tip space or specimen space refer to the same coordinate system. - This is an example of jargon used in e.g. the field of atom - probe tomography. -type: group -NXcoordinate_system(NXobject): - origin(NX_CHAR): - doc: | - Human-readable field telling where the origin of this CS is. - Exemplar values could be *left corner of the lab bench*, *door-handle* - *pinhole through which the electron beam exists the pole piece*. - *barycenter of the triangle*, *center of mass of the stone*. - # implementing a proposal for "a common base table" along thoughts like: - # https://manual.nexusformat.org/classes/base_classes/NXtransformations.html#nxtransformations - # similar to a place where all transformations are stored - # https://www.zenodo.org/record/3526738/files/lyso009a_0087.JF07T32V01_master.h5?download=1 - alias(NX_CHAR): - doc: | - An alternative name given to that coordinate system. - type(NX_CHAR): - doc: | - Coordinate system type. - enumeration: [cartesian] - handedness(NX_CHAR): - doc: | - Handedness of the coordinate system if it is a Cartesian. - enumeration: [right_handed, left_handed] - x_alias(NX_CHAR): - doc: | - Possibility to define an alias for the name of the x-axis. - x_direction(NX_CHAR): - doc: | - Human-readable field telling in which direction the x-axis points if that - instance of :ref:`NXcoordinate_system` has no reference to any parent and as such - is the mighty world reference frame. - - Exemplar values could be direction of gravity. - x(NX_NUMBER): - doc: | - Base unit vector along the first axis which spans the coordinate system. - This axis is frequently referred to as the x-axis in real space and - the i-axis in reciprocal space. - unit: NX_LENGTH - dim: (3,) - y_alias(NX_CHAR): - doc: | - Possibility to define an alias for the name of the y-axis. - y_direction(NX_CHAR): - doc: | - Human-readable field telling in which direction the y-axis points if that - instance of :ref:`NXcoordinate_system` has no reference to any parent and as such - is the mighty world reference frame. - - See docstring of x_alias for further details. - y(NX_NUMBER): - doc: | - Base unit vector along the second axis which spans the coordinate system. - This axis is frequently referred to as the y-axis in real space and - the j-axis in reciprocal space. - unit: NX_LENGTH - dim: (3,) - z_alias(NX_CHAR): - doc: | - Possibility to define an alias for the name of the z-axis. - z_direction(NX_CHAR): - doc: | - Human-readable field telling in which direction the z-axis points if that - instance of :ref:`NXcoordinate_system` has no reference to any parent and as such - is the mighty world reference frame. - - See docstring of x_alias for further details. - z(NX_NUMBER): - doc: | - Base unit vector along the second axis which spans the coordinate system. - This axis is frequently referred to as the z-axis in real space and - the k-axis in reciprocal space. - unit: NX_LENGTH - dim: (3,) diff --git a/contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml b/contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml deleted file mode 100644 index 37826128c..000000000 --- a/contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml +++ /dev/null @@ -1,120 +0,0 @@ -category: base -doc: | - Base class for method-specific conventions EBSD. - - Solves the key issue that currently conventions used for collecting and interpreting - EBSD data are not always explicitly communicating which limits interoperability and - reusability of EBSD data. -# symbols: -type: group -NXcoordinate_system_em_ebsd(NXobject): # move to the NXem_ebsd part of the NXem application definition - gnomonic_projection_reference_frame(NXcoordinate_system): - doc: | - Details about the gnomonic projection reference frame. - type(NX_CHAR): - doc: | - Type of coordinate system/reference frame used for identifying - positions in the gnomonic projection space Xg, Yg, Zg - according to DOI: 10.1016/j.matchar.2016.04.008. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of coordinate system. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Is the origin of the gnomonic coordinate system located - where we assume the location of the pattern centre. - This is the location Xg = 0, Yg = 0, Zg = 0 according to - reference DOI: 10.1016/j.matchar.2016.04.008. - enumeration: [undefined, in_the_pattern_centre] - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing "gnomomic" x-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - enumeration: [undefined, north, east, south, west, in, out] - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing "gnomomic" y-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing "gnomomic" z-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - pattern_centre(NXprocess): - doc: | - Details about the definition of the pattern centre - as a special point in the gnomonic projection reference frame. - x_boundary_convention(NX_CHAR): - doc: | - From which border of the EBSP (in the detector reference frame) - is the pattern centre's x-position (PCx) measured? - Keywords assume the region-of-interest is defined by - a rectangle. We observe this rectangle and inspect the - direction of the outer-unit normals to the edges of - this rectangle. - enumeration: [undefined, top, right, bottom, left] - x_normalization_direction(NX_CHAR): - doc: | - In which direction are positive values for PCx measured from - the specified boundary. Keep in mind that the gnomonic space - is in virtually all cases embedded in the detector space. - Specifically, the XgYg plane is defined such that it is - embedded/laying inside the XdYd plane (of the detector - reference frame). - When the normalization direction is the same as e.g. the - detector x-axis direction, we state that we effectively - normalize in fractions of the width of the detector. - - The issue with terms like width and height is that these - degenerate if the detector region-of-interest is square-shaped. - This is why we should better avoid talking about width and height but - state how we would measure distances practically with a ruler and - how we then measure positive distances. - enumeration: [undefined, north, east, south, west] - y_boundary_convention(NX_CHAR): - doc: | - From which border of the EBSP (in the detector reference - frame) is the pattern centre's y-position (PCy) measured? - For further details inspect the help button of - xaxis_boundary_convention. - enumeration: [undefined, top, right, bottom, left] - y_normalization_direction(NX_CHAR): - doc: | - In which direction are positive values for PCy measured from - the specified boundary. - For further details inspect the help button of - xaxis_normalization_direction. - enumeration: [undefined, north, east, south, west] - # distance_convention: - # doc: | - # How is the third of the three pattern centre parameter values, - # the (distance) parameter DD, normalized. Which convention - # is followed. We are aware that specifying one of the options here - # also implicitly comes with conventions for some of the parameter - # requested in this ELN. For now we would rather like to ask - # the users though to be specific also to learn how such an ELN - # will be used in practice. - # enumeration: [undefined, Bruker, JEOL, FEI, Oxford] diff --git a/contributed_definitions/nyaml/NXcrystal_structure.yaml b/contributed_definitions/nyaml/NXcrystal_structure.yaml deleted file mode 100644 index 796ac83d3..000000000 --- a/contributed_definitions/nyaml/NXcrystal_structure.yaml +++ /dev/null @@ -1,178 +0,0 @@ -category: base -doc: | - Base class to describe the atomic crystal structure of a phase. - - This base class contains key metadata that are relevant parameter to every - physics-based model to simulate radiation matter interaction. - - Examples where such base class is useful are kinematic or dynamic - diffraction simulations of e.g. (Kikuchi or other type of) patterns. -# The actual indexing of Kikuchi patterns may use different algorithms. -# Such are used within different workflows where simulated and measured -# Kikuchi pattern are compared to rate which phase and orientation is the most -# likely candidate describing the pattern measured at that each scan point -# respectively. If this evaluation yields scan points without any solutions, -# these are represented using the null-phase model phase0, aka n/a aka notIndexed. -# Traditionally, Hough transformation-based indexing has been the most frequently -# used algorithm. Dictionary-based alternatives are emerging. -symbols: - n_hkl: | - Number of reflectors (Miller crystallographic plane triplets). - n_pos: | - Number of atom positions. - d: | - Dimensionality of the lattice. -type: group -NXcrystal_structure(NXobject): - \@depends_on(NX_CHAR): - doc: | - Detail in which reference frame the unit cell is defined. - dimensionality(NX_POSINT): - doc: | - Dimensionality of the lattice. - enumeration: [1, 2, 3] - reference(NXidentifier): - doc: | - Reference to another resource that was used for - instantiating this structure model. - a_b_c(NX_NUMBER): - doc: | - Crystallography unit cell parameters a, b, and c. - unit: NX_LENGTH - dim: (d,) - # defined using which convention? - alpha_beta_gamma(NX_NUMBER): - doc: | - Crystallography unit cell parameters alpha, beta, and gamma. - unit: NX_ANGLE - dim: (d,) - area(NX_NUMBER): - doc: | - Area of the unit cell considering that d = 2. - unit: NX_AREA - volume(NX_NUMBER): - doc: | - Volume of the unit cell considering that d = 3. - unit: NX_VOLUME - crystal_system(NX_CHAR): - doc: | - Crystal system - enumeration: [triclinic, monoclinic, orthorhombic, tetragonal, rhombohedral, hexagonal, cubic] - # 2d - laue_group(NX_CHAR): - doc: | - Laue group using International Table of Crystallography Notation. - # add enumeration of all possible - point_group(NX_CHAR): - doc: | - Point group using International Table of Crystallography Notation. - # add enumeration all possible - # 3d - space_group(NX_CHAR): - doc: | - Space group from the International Table of Crystallography Notation. - # add enumeration of all possible - is_centrosymmetric(NX_BOOLEAN): - doc: | - True if space group is considered a centrosymmetric one. - False if space group is considered a non-centrosymmetric one. - Centrosymmetric has all types and combinations of symmetry elements - (translation, rotational axis, mirror planes, center of inversion) - Non-centrosymmetric compared to centrosymmetric is constrained (no inversion). - Chiral compared to non-centrosymmetric is constrained (no mirror planes). - is_chiral(NX_BOOLEAN): - doc: | - True if space group is considered a chiral one. - False if space group is consider a non-chiral one. - phase_identifier(NX_INT): - doc: | - Identifier for each phase. - - The value 0 is reserved for the unknown phase that represents the - null-model no sufficiently significant confirmation. In other words, - the phase_name is n/a, notIndexed. - - The phase identifier value has to match with the integer postfix of the - group name which represents that instance in a NeXus/HDF5 file, i.e. - if two phases were used e.g. 0 and 1, two instances of an - :ref:`NXcrystal_structure` named phase0 and phase1 - should be stored in the HDF5 file. - unit: NX_UNITLESS - # \@depends_on(NX_CHAR): - # doc: | - # Refers to the specific identifier_offset to consider. - # - # If not provided assume identifier_offset is 0. - phase_name(NX_CHAR): - doc: | - Name of the phase/alias. - - If the phase_identifier is 0 and one would like to use the field - phase_name the value should be n/a. - atom_identifier(NX_CHAR): - doc: | - Label for each atom position. - dim: (n_pos,) - atom_type(NX_UINT): - doc: | - The hash value :math:`H` is :math:`H = Z + N*256` with :math:`Z` - the number of protons and :math:`N` the number of neutrons - of each isotope respectively. Z and N have to be 8-bit unsigned integers. - For the rationale behind this `M. Kühbach et al. (2021) `_ - unit: NX_UNITLESS - dim: (n_pos,) - # atom_position(NXcg_point_set): - atom_position(NX_NUMBER): - doc: | - Atom positions. - dim: (n_pos, d) - unit: NX_ANY - \@depends_on(NX_CHAR): - doc: | - Reference to an instance of :ref:`NXcoordinate_system` - whereby the positions can be resolved. - # in addition we need to have a physical model e.g. kinematic or dynamical e-diffraction theory - # to describe the simulated Kikuchi pattern generated from such a model - atom_occupancy(NX_NUMBER): - doc: | - Relative occupancy of the atom position. - unit: NX_DIMENSIONLESS - dim: (n_pos,) - number_of_planes(NX_UINT): - doc: | - How many reflectors are distinguished. - - Value has to match value for symbol n_hkl. - unit: NX_UNITLESS - # Miller indices :math:`(hkl)[uvw]`. - miller(NX_NUMBER): - unit: NX_UNITLESS - doc: | - Miller indices :math:`(hkl)[uvw]` of the planes. - - The first triplet specify :math:`(hkl)` the second triplet :math:`[uvw]`. - Miller indices refer to the Cartesian right-handed coordinate system - of the unit cell. - dim: (n_hkl, 6) - dspacing(NX_NUMBER): - doc: | - Spacing between crystallographic planes as defined by field miller. - unit: NX_LENGTH - dim: (n_hkl,) - relative_intensity(NX_NUMBER): - doc: | - Relative intensity of the signal for the plane. - unit: NX_DIMENSIONLESS - dim: (n_hkl,) - number_of_scan_points(NX_UINT): - doc: | - In case the :ref:`NXcrystal_structure` base class is used - with analyzed orientation maps this field stores how many scan points - of the map were identified as that phase. - unit: NX_UNITLESS - ipfID(NXms_ipf): - pfID(NXms_pf): - odfID(NXms_odf): -# here the theoreticians expert (Marc deGraeff, Aimo Winkelmann, Peter Rez) -# can give some good suggestions on how to improve and ideally make even -# more general this section diff --git a/contributed_definitions/nyaml/NXcs_cpu_obj.yaml b/contributed_definitions/nyaml/NXcs_cpu_obj.yaml deleted file mode 100644 index 73097d5ca..000000000 --- a/contributed_definitions/nyaml/NXcs_cpu_obj.yaml +++ /dev/null @@ -1,12 +0,0 @@ -category: base -doc: | - Computer science description of a (central) processing unit (C)PU of a computer. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_cpu_obj(NXobject): - name(NX_CHAR): - doc: | - Given name of the CPU. Users should be as specific as possible. - (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_cpu_sys.yaml b/contributed_definitions/nyaml/NXcs_cpu_sys.yaml deleted file mode 100644 index 5eaf8f0ea..000000000 --- a/contributed_definitions/nyaml/NXcs_cpu_sys.yaml +++ /dev/null @@ -1,21 +0,0 @@ -category: base -doc: | - Computer science description of a system of classical central processing units. - - For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_cpu_sys(NXobject): - cpuID(NXcs_cpu_obj): - doc: | - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single CPU one - could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of - :ref:`NXcs_cpu_sys`. - A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` - inside one instance of :ref:`NXcs_cpu_sys`. - A server with two dual-socket server nodes one could describe - with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml deleted file mode 100644 index 04468b7b2..000000000 --- a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml +++ /dev/null @@ -1,12 +0,0 @@ -category: base -doc: | - Computer science description of a graphic processing unit (GPU) of a computer. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_gpu_obj(NXobject): # NXcircuit_board ? - name(NX_CHAR): - doc: | - Given name of the GPU. Users should be as specific as possible. - (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_gpu_sys.yaml b/contributed_definitions/nyaml/NXcs_gpu_sys.yaml deleted file mode 100644 index dee199330..000000000 --- a/contributed_definitions/nyaml/NXcs_gpu_sys.yaml +++ /dev/null @@ -1,20 +0,0 @@ -category: base -doc: | - Computer science description of a system of coprocessor or graphics processors. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_gpu_sys(NXobject): - gpuID(NXcs_gpu_obj): - doc: | - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single GPU one - could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of - :ref:`NXcs_gpu_sys`. - A desktop computer with two GPUs one could describe using two instances - of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. - A GPU server like nowadays used for artificial intelligence - one could describe as a system with n instances of :ref:`NXcs_gpu_obj` - in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_mm_obj.yaml b/contributed_definitions/nyaml/NXcs_mm_obj.yaml deleted file mode 100644 index d1fead8c8..000000000 --- a/contributed_definitions/nyaml/NXcs_mm_obj.yaml +++ /dev/null @@ -1,21 +0,0 @@ -category: base -doc: | - Computer science description of a memory in a memory system. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_mm_obj(NXobject): - technology(NX_CHAR): - doc: | - Qualifier for the type of random access memory. - # make an enumeration - max_physical_capacity(NX_NUMBER): - doc: | - Total amount of data which the medium can hold. - unit: NX_ANY - # NX_BIT - name(NX_CHAR): - doc: | - Given name to the I/O unit. - (NXfabrication): diff --git a/contributed_definitions/nyaml/NXem_adf.yaml b/contributed_definitions/nyaml/NXem_adf.yaml deleted file mode 100644 index c64af34d4..000000000 --- a/contributed_definitions/nyaml/NXem_adf.yaml +++ /dev/null @@ -1,19 +0,0 @@ -category: base -doc: | - Base class method-specific for annular dark field imaging. - - In the majority of cases simple d-dimensional regular scan patterns are used - to probe a region-of-interest (ROI). Examples can be single point aka spot - measurements, line profiles, or (rectangular) surface mappings. - The latter pattern is the most frequently used. - - For now the base class provides for scans for which the settings, - binning, and energy resolution is the same for each scan point. -type: group -NXem_adf(NXem_method): - (NXimage_set): - half_angle_interval(NX_NUMBER): - doc: | - Annulus inner (first value) and outer (second value) half angle. - unit: NX_ANGLE - dim: (2,) diff --git a/contributed_definitions/nyaml/NXem_base.yaml b/contributed_definitions/nyaml/NXem_base.yaml deleted file mode 100644 index 2de8081a8..000000000 --- a/contributed_definitions/nyaml/NXem_base.yaml +++ /dev/null @@ -1,297 +0,0 @@ -category: base -# template to be used for an application definition -doc: | - Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. - - This base class combines a method-specific and technical-design-level base class - instance to provide a template for storing parameterized descriptions of - pieces of information collected when performing electron microscopy research. - - The base class here shows all possible branches without making any statements - as to which of these have to be used in an instance. Thereby, the base class - provides a template how to name and structure concepts in a hierarchy - to support finding information and reducing the need for renaming and - restructuring information for a research field where many scientists perform - very specific research but who all also share commonalities like usage of - controlled electron beams, a focus on studies of electron beam matter interaction - to explore physical mechanisms and phenomena, or the desire to characterize materials - using electron microscopy. -# flesh out the description of that to read the docs, because currently the -# description on the NeXus front-page is overwhelming -# considering what we learned from the diataxis workshop we write here a -# specification neither a how to nor a tutorial which explains all the context -# because we address here developers of software -type: group -NXem_base(NXroot): - (NXprogram): - doc: | - A collection of all programs and libraries which are considered relevant - to understand with which software tools this NeXus file instance was - generated. Ideally, to enable a binary recreation from the input data. - - Examples include the name and version of the libraries used to write the - instance. Ideally, the software that writes these :ref:`NXprogram` instances - also includes the version of the set of NeXus classes i.e. the specific - set of base classes, application definitions, and contributed definitions - with which the here described concepts can be resolved. - - For the `pynxtools library `_ - which is used by the `NOMAD `_ - research data management system, it makes sense to store e.g. the GitHub - repository commit and respective submodule references used. - # each NeXus file instance should have a default plot - # however as there are cases when this cannot be assured we cannot - # make the default required, one example is e.g. a NeXus instance - # where scientists just store conventions without a default plot - cs_profiling(NXcs_profiling): - doc: | - The configuration of the I/O writer software (e.g. `pynxtools `_) - which was used to generate this NeXus file instance. - (NXentry): # means ENTRY(NXentry) - \@version(NX_CHAR): - doc: | - An at least as strong as SHA256 hashvalue of the file - which specifies the application definition. - definition(NX_CHAR): - doc: | - NeXus NXDL schema to which this file conforms. - enumeration: [NXem] - experiment_identifier(NXidentifier): - doc: | - Ideally, a (globally) unique persistent identifier - for referring to this experiment. - - An experiment should be understood in that this can be an experiment - in reality or a computer simulation because also the latter is an - experiment (see the Cambridge Dictionary experiment: - *a test done in order to find out something, eg if an idea is correct*). - - The identifier is usually issued by the facility, laboratory, - or the principle investigator. The identifier enables to link - experiments/simulations to e.g. proposals. - experiment_description(NX_CHAR): - doc: | - Free-text description about the experiment. - - Users are strongly advised to parameterize their description of the - experiment by using the respective base classes instead of writing prose - into this field. - - The reason is that such free-text field is difficult to machine-interpret. - The motivation behind keeping this field for now is to learn through - the information entered in this field in how far the current base - classes are incomplete. - start_time(NX_DATE_TIME): - doc: | - ISO 8601 time code with local time zone offset to UTC information included - when the microscope session started. If the application demands that time - codes in this section of the application definition should only be used - for specifying when the experiment was performed - and the exact - duration is not relevant - this start_time field should be used. - - Often though it is useful to specify a time interval via setting both - a start_time and an end_time because this enables software tools and - users to collect a more detailed bookkeeping of the experiment. - - The user should be aware that even with having both time instances specified, - it may not be possible to infer how long the experiment took or for how - long data were acquired. - - More detailed timing data over the course of the experiment have - to be collected to compute this. These computations can take - advantage of individual time stamps start_time and end_time - in :ref:`NXevent_data_em` instances. - end_time(NX_DATE_TIME): - doc: | - ISO 8601 time code with local time zone offset to UTC included when - the microscope session ended. See docstring of the start_time field - to see how the start_time and end_time should be used together. - (NXcite): - (NXprogram): - doc: | - The program and eventual software libraries used with which the - NeXus instance was created. For the NOMAD OASIS research data - management system e.g. pynxtools and eventually all modules - if desired. - # the above-description overwrites the default description of the NXprogram base class - # this is composed from the NXprogram base class - # program: - # \@version: - # \@url: - # NXnote and thumbnail dropped for the reason that these are - # arbitrary binary containers without any clear provenance. - (NXserialized): - doc: | - Possibility to store a collection of data artifacts - associated with the experiment. - # using NXserialized here instead of NXnote as the former is more specific - (NXuser): - doc: | - Contact information and eventually details of at least one person - who performed or was involved in the session. This can be the - principle investigator who performed this experiment or the student - who performed the simulation. - Adding multiple users if relevant is recommended. - name(NX_CHAR): - doc: | - Given (first) name and surname of the user. - affiliation(NX_CHAR): - doc: | - Name of the affiliation of the user at the point in time - when the experiment was performed. - address(NX_CHAR): - doc: | - Postal address of the affiliation. - email(NX_CHAR): - doc: | - Email address of the user at the point in time when the experiment - was performed. Writing the most permanently used email is recommended. - identifier(NXidentifier): - doc: | - Service as another mean of identification of a user than by the name. - Examples could be details about an ORCID or social media account of - the user. - telephone_number(NX_CHAR): - doc: | - (Business) (tele)phone number of the user at the point - in time when the experiment was performed. - role(NX_CHAR): - doc: | - Which role does the user have in the place and at the point - in time when the experiment was performed? Technician operating - the microscope, student, postdoc, principle investigator, or guest - are common examples. - sample(NXsample): - # NEW ISSUE: inject the conclusion from the discussion with Andrea - # according to SAMPLE.yaml 0f8df14 2022/06/15 - # ID: -> maps to name - # name: -> short_title - # user: -> not matched right now - # citation: doi ->why relevant, should be solved by RDMS - doc: | - A description of the material characterized in the experiment. - Sample and specimen are threaded as de facto synonyms. - Samples can be real specimens or virtual (see method). - method(NX_CHAR): - doc: | - A qualifier whether the sample is a real one or a - virtual one (in a computer simulation) - enumeration: [experiment, simulation] - # MK:: declared_by_vendor I would rather expect this for a substance - # COMPONENT.yaml - # SUBSTANCE: - # QUANTIFY - identifier(NXidentifier): - doc: | - Ideally, (globally) unique persistent identifier which distinguishes - the specimen from all others and especially the predecessor/origin - from where the specimen was cut. - - This field must not be used for an alias! Instead, use name. - - In cases where multiple specimens were loaded into the microscope, - the identifier has to resolve the specific sample, whose results are - stored by this :ref:`NXentry` instance, because a single NXentry should be - used only for the characterization of a single specimen. - - Details about the specimen preparation should be - stored in resources referring to parent_identifier. - parent_identifier(NXidentifier): - doc: | - Identifier of the sample from which the sample was cut or the string - *None*. The purpose of this field is to support functionalities - for tracking sample provenance via a research data management system. - preparation_date(NX_DATE_TIME): - doc: | - ISO 8601 time code with local time zone offset to UTC information - when the specimen was prepared. - - Ideally, report the end of the preparation, i.e. the last known time - the measured specimen surface was actively prepared. Ideally, this - matches the last timestamp that is mentioned in the digital resource - pointed to by parent_identifier. - - Knowing when the specimen was exposed to e.g. specific atmosphere is - especially required for environmentally sensitive material such as - hydrogen charged specimens or experiments including tracers with a - short half time. Additional time stamps prior to preparation_date - should better be placed in resources which describe but which do not pollute - the description here with prose. Resolving these connected pieces of information - is considered within the responsibility of the research data management - system. - name(NX_CHAR): - doc: | - An alias used to refer to the specimen to please readability for humans. - atom_types(NX_CHAR): - doc: | - List of comma-separated elements from the periodic table that are - contained in the sample. If the sample substance has multiple - components, all elements from each component must be included in - `atom_types`. - - The purpose of the field is to offer research data management systems an - opportunity to parse the relevant elements without having to interpret - these from the resources pointed to by parent_identifier or walk through - eventually deeply nested groups in data instances. - # NEW ISSUE: use Andrea and MarkusK groups for describing the geometry of the sample - thickness(NX_NUMBER): - doc: | - (Measured) sample thickness. - - The information is recorded to qualify if the beam used was likely - able to shine through the specimen. For scanning electron microscopy, - in many cases the specimen is typically thicker than what is - illuminatable by the electron beam. - - In this case the value should be set to the actual thickness of - the specimen viewed for an illumination situation where the nominal - surface normal of the specimen is parallel to the optical axis. - unit: NX_LENGTH - # \@units: nm - # NEW ISSUE: error estimates of the thickness and origin, i.e. how the value was obtained would be useful - # NEW ISSUE: error model - # NEW ISSUE: the KIT/SCC SEM, TEM schemata further qualify samples whether they are conductive e/ibeam sensitive - # etc. The problem with this is that beam sensitivity is too vague but spatiotemporal electron dose integral dependent - # KIT/SCC distinguish further conductivity and magnetic properties. While the motivation is clear, making - # it thus simple is likely problematic when the data entered in such fields remaining qualitative. - # what are good or bad properties, it would make sense though to quantify these values - # this includes the description of eventual plasma cleaning steps, - # just knowing that a sample was plasma cleaned is insufficient, maybe it was not cleaned long enough - # if plasma cleaning is done outside the EM than its certainly history, if it happens inside the EM - # are the ibeam description capabilities not sufficient enough? - density(NX_NUMBER): - # NX_MASS_PER_VOLUME - doc: | - (Measured) density of the specimen. - - For multi-layered specimens this field should only be used to describe - the density of the excited volume. For scanning electron microscopy - the usage of this field is discouraged and instead an instance of an - :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` - instances can provide a cleaner description of the relevant details - why one may wish to store the density of the specimen. - unit: NX_ANY - description: - doc: | - Discouraged free-text field to provide further detail although adding - parent_identifier and having a working research data management system - should provide this contextualization. - # (NXmonitor): - (NXdata): - (NXcoordinate_system_set): - # link to an instance of an NXinstrument but that is anyway specialized for EM - measurement(NXem_msr): - simulation(NXem_sim): - (NXroi): - doc: | - A region-of-interest analyzed either during or after the session - for which specific processed data generated from the measured or the - simulated data are available. - se(NXem_img): - bse(NXem_img): - ebsd(NXem_ebsd): - eds(NXem_eds): - adf(NXem_adf): - eels(NXem_eels): - correlation(NXem_correlation): - # cl(NXem_cl): diff --git a/contributed_definitions/nyaml/NXem_conventions.yaml b/contributed_definitions/nyaml/NXem_conventions.yaml deleted file mode 100644 index 7835d9a65..000000000 --- a/contributed_definitions/nyaml/NXem_conventions.yaml +++ /dev/null @@ -1,296 +0,0 @@ -category: base -# symbols: -doc: | - Conventions for rotations and coordinate systems to interpret crystal orientation - and other data and results collected with electron microscopy research. - - Documenting explicitly all used conventions and coordinate systems is - the decisive context whereby many results from electron microscopy are - at all interpretable. - -# This base class provides several sets of such assumptions and conventions. -# Further base classes should be defined when specific techniques and methods -# demand further specifications or have specialized demands. NXem_conventions_ebsd -# is an example for such method-specific base class to summarize key conventions -# for Electron Backscatter Diffraction (EBSD). - -# What is could be a best practice for application definition developers -# who would like to describe an electron microscopy case where multiple -# methods and/or detectors are used. In this case one should define a -# method-specific base class like the template NXem_conventions_ebsd. -# Even though this may come at a cost of some duplicated information where -# the same physical detector is used in different ways, i.e. the signal collect -# from the detector is interpreted in a different way. -# As in most cases established types of signal and thus detectors are used -# (secondary electron, backscattered electron, etc.) one could equally use -# just one NXem_conventions base class instance in an application definition -# and use detector_reference_frame as a template. For each method and detector -# one then creates one NXprocess group named detector_reference_frame1, -# detector_reference_frame2, detector_reference_frame3, and so on and so forth -# and adds inside that NXprocess and use the depends_on field. - -# What is considered best practice in an application definition with multiple -# NXentry instances? In this case each NXentry instance should have an own -# NXspecimen instance and thus the NXem_conventions instance should be place -# inside that NXentry. This enables to group multiple experiments on multiple -# samples together without setting a constraint that in all these instances -# the conventions have to be the same. - -# However, best practice is the conventions should be expressed explicitly -# and they should whenever possible be as simple as possible and as few -# as possible to support users with understanding the content of the application -# definition. -type: group -NXem_conventions(NXobject): - # mandatory information about used or - # assumed reference frame and rotation conventions - rotation_conventions(NXobject): - doc: | - Mathematical conventions and materials-science-specific conventions - required for interpreting every collection of orientation data. - rotation_handedness(NX_CHAR): - doc: | - Convention how a positive rotation angle is defined when viewing - from the end of the rotation unit vector towards its origin, - i.e. in accordance with convention 2 of - DOI: 10.1088/0965-0393/23/8/083501. - Counter_clockwise is equivalent to a right-handed choice. - Clockwise is equivalent to a left-handed choice. - enumeration: [undefined, counter_clockwise, clockwise] - rotation_convention(NX_CHAR): - doc: | - How are rotations interpreted into an orientation - according to convention 3 of - DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, passive, active] - euler_angle_convention(NX_CHAR): - doc: | - How are Euler angles interpreted given that there are several - choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of - DOI: 10.1088/0965-0393/23/8/083501. - The most frequently used convention is ZXZ which is based on - the work of H.-J. Bunge but other conventions are possible. - enumeration: [undefined, zxz] - axis_angle_convention(NX_CHAR): - doc: | - To which angular range is the rotation angle argument of an - axis-angle pair parameterization constrained according to - convention 5 of DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, rotation_angle_on_interval_zero_to_pi] - sign_convention(NX_CHAR): - doc: | - Which sign convention is followed when converting orientations - between different parameterizations/representations according - to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, p_plus_one, p_minus_one] - processing_reference_frame(NXcoordinate_system): - doc: | - Details about eventually relevant named directions that may - give reasons for anisotropies. The classical example is cold-rolling - where one has to specify which directions (rolling, transverse, and normal) - align how with the direction of the base vectors of the sample_reference_frame. - type(NX_CHAR): - doc: | - Type of coordinate system and reference frame according to - convention 1 of DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of coordinate system. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Location of the origin of the processing_reference_frame. - This specifies the location Xp = 0, Yp = 0, Zp = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] - x_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. rolling direction. - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing x-axis base vector of - the processing_reference_frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. - enumeration: [undefined, north, east, south, west, in, out] - y_alias(NX_CHAR): - doc: | - Name or alias assigned to the y-axis base vector, - e.g. transverse direction. - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing y-axis base vector of - the processing_reference_frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_alias(NX_CHAR): - doc: | - Name or alias assigned to the z-axis base vector, - e.g. normal direction. - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing z-axis base vector of - the processing_reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - sample_reference_frame(NXcoordinate_system): - doc: | - Details about the sample/specimen reference frame. - type(NX_CHAR): - doc: | - Type of coordinate system and reference frame according to - convention 1 of DOI: 10.1088/0965-0393/23/8/083501. - The reference frame for the sample surface reference is used for - identifying positions on a (virtual) image which is formed by - information collected from an electron beam scanning the - sample surface. We assume the configuration is inspected by - looking towards the sample surface from a position that is - located behind the detector. - Reference DOI: 10.1016/j.matchar.2016.04.008 - The sample surface reference frame has coordinates Xs, Ys, Zs. - In three dimensions these coordinates are not necessarily - located on the surface of the sample as there are multiple - faces/sides of the sample. Most frequently though the coordinate - system here is used to define the surface which the electron - beam scans. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of the coordinate system if it is a Cartesian. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Location of the origin of the sample surface reference frame. - This specifies the location Xs = 0, Ys = 0, Zs = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] - x_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. longest edge. - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing x-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - enumeration: [undefined, north, east, south, west, in, out] - y_alias(NX_CHAR): - doc: | - Name or alias assigned to the y-axis base vector, - e.g. long edge. - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing y-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_alias(NX_CHAR): - doc: | - Name or alias assigned to the z-axis base vector, - e.g. shortest edge. - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing z-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - detector_reference_frameID(NXcoordinate_system): - doc: | - Details about the detector reference frame for a specific detector. - \@depends_on(NX_CHAR): - doc: | - Reference to the specifically named :ref:`NXdetector` instance - for which these conventions in this :ref:`NXprocess` group apply - (e.g. /entry1/instrument/detector1). - type(NX_CHAR): - doc: | - Type of coordinate system/reference frame used for - identifying positions in detector space Xd, Yd, Zd, - according to DOI: 10.1016/j.matchar.2016.04.008. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of the coordinate system if it is a Cartesian. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Where is the origin of the detector space reference - frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] - x_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. longest edge as some landmark on the detector. - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing x-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - enumeration: [undefined, north, east, south, west, in, out] - y_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. long edge as some landmark on the detector. - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing y-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. short edge as some landmark on the detector. - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing z-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - # conventions specific for EBSD - (NXem_conventions_ebsd): \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml b/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml deleted file mode 100644 index 1ec180e23..000000000 --- a/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml +++ /dev/null @@ -1,125 +0,0 @@ -category: base -# symbols: -doc: | - Base class for method-specific conventions EBSD. - - This base class is expected to be used with :ref:`NXem_conventions`. - - This is the main issue which currently is not in all cases documented - and thus limits the interoperability and value of collected EBSD data. - Not communicating EBSD data with such contextual pieces of information - and the use of file formats which do not store this information is the - key unsolved problem. -type: group -NXem_conventions_ebsd(NXem_conventions): - gnomonic_projection_reference_frame(NXcoordinate_system): - doc: | - Details about the gnomonic projection reference frame. - type(NX_CHAR): - doc: | - Type of coordinate system/reference frame used for identifying - positions in the gnomonic projection space Xg, Yg, Zg - according to DOI: 10.1016/j.matchar.2016.04.008. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of coordinate system. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Is the origin of the gnomonic coordinate system located - where we assume the location of the pattern centre. - This is the location Xg = 0, Yg = 0, Zg = 0 according to - reference DOI: 10.1016/j.matchar.2016.04.008. - enumeration: [undefined, in_the_pattern_centre] - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing "gnomomic" x-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - enumeration: [undefined, north, east, south, west, in, out] - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing "gnomomic" y-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing "gnomomic" z-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - pattern_centre(NXprocess): - doc: | - Details about the definition of the pattern centre - as a special point in the gnomonic projection reference frame. - x_boundary_convention(NX_CHAR): - doc: | - From which border of the EBSP (in the detector reference frame) - is the pattern centre's x-position (PCx) measured? - Keywords assume the region-of-interest is defined by - a rectangle. We observe this rectangle and inspect the - direction of the outer-unit normals to the edges of - this rectangle. - enumeration: [undefined, top, right, bottom, left] - x_normalization_direction(NX_CHAR): - doc: | - In which direction are positive values for PCx measured from - the specified boundary. Keep in mind that the gnomonic space - is in virtually all cases embedded in the detector space. - Specifically, the XgYg plane is defined such that it is - embedded/laying inside the XdYd plane (of the detector - reference frame). - When the normalization direction is the same as e.g. the - detector x-axis direction, we state that we effectively - normalize in fractions of the width of the detector. - - The issue with terms like width and height is that these - degenerate if the detector region-of-interest is square-shaped. - This is why we should better avoid talking about width and height but - state how we would measure distances practically with a ruler and - how we then measure positive distances. - enumeration: [undefined, north, east, south, west] - y_boundary_convention(NX_CHAR): - doc: | - From which border of the EBSP (in the detector reference - frame) is the pattern centre's y-position (PCy) measured? - For further details inspect the help button of - xaxis_boundary_convention. - enumeration: [undefined, top, right, bottom, left] - y_normalization_direction(NX_CHAR): - doc: | - In which direction are positive values for PCy measured from - the specified boundary. - For further details inspect the help button of - xaxis_normalization_direction. - enumeration: [undefined, north, east, south, west] - - # distance_convention: - # doc: | - # How is the third of the three pattern centre parameter values, - # the (distance) parameter DD, normalized. Which convention - # is followed. We are aware that specifying one of the options here - # also implicitly comes with conventions for some of the parameter - # requested in this ELN. For now we would rather like to ask - # the users though to be specific also to learn how such an ELN - # will be used in practice. - # enumeration: [undefined, Bruker, JEOL, FEI, Oxford] diff --git a/contributed_definitions/nyaml/NXem_correlation.yaml b/contributed_definitions/nyaml/NXem_correlation.yaml deleted file mode 100644 index 2acf65ec8..000000000 --- a/contributed_definitions/nyaml/NXem_correlation.yaml +++ /dev/null @@ -1,191 +0,0 @@ -category: base -doc: | - Base class to combine different method-specific data in electron microscopy. - - This base class represent a template for documenting correlations - (spatial, temporal) between different method-specific results. -type: group -NXem_correlation(NXem_method): - (NXprocess): - doc: | - Details about processing steps. - sequence_index(NX_INT): - indexing(NXprocess): - doc: | - Details about correlated or logically connected EBSD datasets. - - One important class of such correlated experiments are the so-called - (quasi) in-situ experiments. In this case the same or nearly the same ROI - gets analyzed via a repetitive sequence of thermomechanical treatment, - sample preparation, measurement, on-the-fly-indexing. Phenomena - investigated are recrystallization, strain accumulation, material damage. - Post-processing is required to correlate and reidentify eventual - microstructural features or local ROIs across several orientation maps. - - Another important class of correlated experiments are the so-called - serial-sectioning experiments. Here the same sample is measured - repetitively after polishing each time, to create a stack of - orientation data which can be reconstructed to a - three-dimensional volume ROI. - - Data can be correlated in time, position (spatial), or both (spatiotemporal). - - Spatial correlations between repetitively characterized regions-of-interests - are typically correlated using image registration and alignment algorithms. - For this typically so-called landmarks are used. These can be grains with - a very large size or specific shape, i.e. grains which are qualitatively - different enough to be used as a guide how images are shifted relative to - one another. Other commonly used landmarks are fiducial marks which are - milled into the specimen surface using focus-ion beam milling and/or various - types of indentation methods. - - As far as the same physical region-of-interest is just measured several times, - the additional issue of the depth increment is not a concern. However, correct - assumptions for the depth increment, amount of material removed along the milling - direction is relevant for accurate and precise three-dimensional (serial-sectioning) - correlations. For these studies it can be tricky though to assume or estimate - useful depth increments. Different strategies have been proposed like - calibrations, wedged-shaped landmarks and computer simulation assisted - assumption making. - - Despite the use of landmarks, there are many practical issues which make the - processing of correlations imprecise and inaccurate. Among these are drift - and shift of the specimen, instabilities of the holder, the beam, irrespective - of the source of the drift, charging effects, here specifically causing local - image distortions and rotations which may require special processing algorithms - to reduce such imprecisions. - - Time correlations face all of the above-mentioned issues surplus the challenge - that specific experimental protocols have to be used to ensure the material state - is observed at specific physical time. The example of quasi in-situ characterization - of crystal growth phenomena, a common topic in engineering or modern catalysis research - makes it necessary to consider that e.g. the target value for the desired annealing - temperature is not just gauged based on macroscopic arguments but considers - that transient effects take place. Heating or quenching a sample might thus might - not have been executed under conditions in the interaction volume as they are - documented and/or assumed. - - These issue cause that correlations have an error margin as to how accurately - respective datasets were not only just synced based on the geometry of the - region-of-interests and the time markers but also to asssure which physical - conditions the specimen experienced over the course of the measurements. - - The fourth example of the em_om reference implementation explores the use of the - correlation group with a serial-sectioning datasets that was collected by the - classical Inconel 100 dataset collected by M. D. Uchic and colleagues - (M. Groeber M, Haley BK, Uchic MD, Dimiduk DM, Ghosh S 3d reconstruction and - characterization of polycrystalline microstructures using a fib-sem system data set. - Mater Charac 2006, 57 259–273. 10.1016/j.matchar.2006.01.019M). - - This dataset was specifically relevant in driving forward the implementation - of the DREAM.3D software. DREAM.3D is an open-source software project for - post-processing and reconstructing, i.e. correlating sets of orientation - microscopy data foremost spatially. One focus of the software is the - (post-)processing of EBSD datasets. Another cutting edge tool with similar - scope but a commercial solution by Bruker is QUBE which was developed by - P. Konijnenberg and coworkers. - - Conceptually, software like DREAM.3D supports users with creating linear - workflows of post-processing tasks. Workflows can be instructed via the - graphical user interface or via so-called pipeline processing via command line - calls. DREAM.3D is especially useful because its internal system documents all - input, output, and parameter of the processing steps. This makes DREAM.3D a - good candidate to interface with tools like em_om parser. Specifically, DREAM.3D - documents numerical results via a customized HDF5 file format called DREAM3D. - Workflow steps and settings are stored as nested dictionaries in JSON syntax - inside a supplementary JSON file or alongside the data in the DREAM3D file. - DREAM.3D has a few hundred algorithms implemented. These are called filters - in DREAM.3D terminology. - - Users configure a workflow which instructs DREAM.3D to send the data through - a chain of predefined and configured filters. Given that for each analysis - the filter is documented via its version tags surplus its parameter and setting - via a controlled vocabulary, interpreting the content of a DREAM3D HDF5 file - is possible in an automated manner using a parser. This makes DREAM.3D analyses - repeatable and self-descriptive. A key limitation though is that most frequently - the initial set of input data come from commercial files like ANG. - This missing link between the provenance of these input files, their associated - creation as electron microscope session, is also what NXem_ebsd solves. - - Nevertheless, as this can be solved with e.g. NXem_ebsd we are convinced that - the DREAM.3D and the em_om parser can work productively together to realize - RDMS-agnostic parsing of serial-section analyses. - - The internal documentation of the DREAM.3D workflow also simplifies the - provenance tracking represented by an instance of NXem_ebsd as not every - intermediate results has to be stored. Therefore, the fourth example - focuses on the key result obtained from DREAM.3D - the reconstructed - and aligned three-dimensional orientation map. - - Usually, this result is the starting point for further post-processing - and characterization of structural features. As here orientation microscopy - is insofar scale invariant using DREAM.3D, NXem_ebsd, and em_om should - be useful for different characterization methods, such as EBSD, Transmission - Kikuchi Diffraction (TKD), Automated Crystal Orientation Mapping (ACOM), - Nanobeam Electron Diffraction (using commercial systems like NanoMegas ASTAR) - or open-source implementations of these techniques (such as via pyxem/orix). - - The result of orientation microscopy methods are maps of local orientation - and thermodynamic phase (crystal structure) pieces of information. Virtually - all post-processing of such results for structural features includes again - a workflow of steps which are covered though by the NXms partner application - definition. The respective source of the data in an instance of NXms can - again be a link or reference to an instance of NXem_ebsd to complete the - chain of provenance. - (NXcrystal_structure): - roi(NXdata): - descriptor: - doc: | - Descriptor representing the image contrast. - # \@signal: # data - # \@axes: # [axis_y, axis_x] - # \@axis_x_indices: 0 - # \@axis_y_indices: 1 - # \@signal: - # \@axes: - # \@AXISNAME_indices: - # \@long_name: - title: - doc: | - Title of the default plot. - data(NX_NUMBER): - unit: NX_UNITLESS - doc: | - Descriptor values displaying the ROI. - dim: (n_z, n_y, n_x) - # n_0 slowest 3, n_1 slow 2, n_2 fast 1, rgb triplet is fastest 0 - # in axes fast to fastest - # while for _indices fastest to fast - \@long_name: - doc: | - Descriptor values. - axis_z(NX_NUMBER): - unit: NX_LENGTH - doc: | - Calibrated coordinate along the z-axis. - dim: (n_z,) - \@long_name: - doc: | - Label for the z axis - axis_y(NX_NUMBER): - unit: NX_LENGTH - doc: | - Calibrated coordinate along the y-axis. - dim: (n_y,) - \@long_name: - doc: | - Label for the y axis - axis_x(NX_NUMBER): - unit: NX_LENGTH - doc: | - Calibrated coordinate along the x-axis. - dim: (n_x,) - \@long_name: - doc: | - Label for the x axis - # NEW ISSUE: implement support for filters eventually many of them - # NEW ISSUE: for now only show that data from DREAM3D can be loaded. - # NEW ISSUE: how to handle landmarks - # NEW ISSUE: again an entire set of workflows such as rigid or non-rigid - # image registration etc. - # sequence_index(N0): diff --git a/contributed_definitions/nyaml/NXem_eels.yaml b/contributed_definitions/nyaml/NXem_eels.yaml deleted file mode 100644 index 89b9109bc..000000000 --- a/contributed_definitions/nyaml/NXem_eels.yaml +++ /dev/null @@ -1,42 +0,0 @@ -category: base -doc: | - Base class method-specific for Electron Energy Loss Spectroscopy (EELS). -symbols: - n_energy_loss: | - Number of electron energy loss bins. -type: group -NXem_eels(NXem_method): - # NXem_method also has an NXprocess which in this base class can be - # specialized to include EELS-specific post-processing - (NXspectrum_set): - doc: | - NXspectrum_set_em specialized for EELS. - # \@signal:, \@axes: \@energy_loss_indices \@axis_x_indices: - stack_oned(NXdata): - axis_energy_loss(NX_NUMBER): - unit: NX_ENERGY - dim: (n_energy_loss,) - \@long_name(NX_CHAR): - doc: | - Energy loss. - stack_oned(NXdata): - axis_energy_loss(NX_NUMBER): - unit: NX_ENERGY - dim: (n_energy_loss,) - \@long_name(NX_CHAR): - doc: | - Energy loss. - - summary(NXdata): - # \@signal: data_counts - # \@axes: [axis_energy_loss] - # \@energy_loss_indices: 0 - axis_energy_loss(NX_NUMBER): - unit: NX_ENERGY - doc: | - Energy loss. - dim: (n_energy_loss,) - \@long_name(NX_CHAR): - doc: | - Energy loss. - # collection if needed can be composed from NXspectrum_set diff --git a/contributed_definitions/nyaml/NXem_msr.yaml b/contributed_definitions/nyaml/NXem_msr.yaml deleted file mode 100644 index 16c349ca5..000000000 --- a/contributed_definitions/nyaml/NXem_msr.yaml +++ /dev/null @@ -1,63 +0,0 @@ -category: base -doc: | - Base class for collecting a session with a real electron microscope. - - For collecting data and experiments which are simulations of an - electron microscope use the :ref:`NXem_sim` base class. -type: group -NXem_msr(NXem_method): - em_lab(NXinstrument): - doc: | - (Meta)data of the microscope and the lab in which it stands. - - This em_lab group differs from potential em_lab groups inside - :ref:`NXevent_data_em` instances in that here the more static descriptions - are kept while changing, i.e. time-dependent pieces of information are - logged, via the em_lab group inside the desired number of instances - of NXevent_data_em. - - While using an :ref:`NXevent_data_em` instance, users should store only those - settings about a component which are relevant to understand the current - state of the component. Here, current means for the time interval which - the event covers (as it is detailed via start_time and end_time) timestamps. - - For example it is not relevant to store in each :ref:`NXevent_data_em` - electron_source group again the details of the gun type and the manufacturer - but only the high-voltage value and that only if it is different from the value - that is specified in the em_lab section for the static settings. - - In effect, this defines an information inference hierarchy which starts - in an individual :ref:`NXevent_data_em` instance followed by a probing of the - static section. - instrument_name(NX_CHAR): - doc: | - Given name of the microscope at the hosting institution. - This is an alias. Examples could be NionHermes, Titan, JEOL, - Gemini, etc. - location(NX_CHAR): - doc: | - Location of the lab or place where the instrument is installed. - Using GEOREF is preferred. - (NXfabrication): - (NXchamber): - (NXebeam_column): - (NXibeam_column): - (NXoptical_system_em): - (NXdetector): - doc: | - Description of the type of the detector. - - Electron microscopes have typically multiple detectors. - Different technologies are in use like CCD, scintillator, - direct electron, CMOS, or image plate to name but a few. - local_name(NX_CHAR): - doc: | - Instrument-specific alias/name - # it is unfortunate that for NXdetector there are already many places - # how one can specify details which could equally end up in fabrications - # we should give better guidance which option to use, pr to niac - # (NXfabrication): - (NXpump): - (NXstage_lab): - (NXevent_data_em_set): -# (NXevent_data_em): diff --git a/contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml b/contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml deleted file mode 100644 index d254cf51b..000000000 --- a/contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml +++ /dev/null @@ -1,10 +0,0 @@ -category: application -doc: | - Application definition for documenting results with GraGLeS. -# symbols: -type: group -NXmicrostructure_gragles_results(NXobject): - (NXentry): - definition(NX_CHAR): - enumeration: [NXmicrostructure_gragles_results] - \@version(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml b/contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml deleted file mode 100644 index b39f082f9..000000000 --- a/contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml +++ /dev/null @@ -1,46 +0,0 @@ -category: base -doc: | - Base class for describing a set of crystallographic slip systems. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. - n: | - Number of slip systems. -type: group -NXmicrostructure_slip_system(NXobject): - # number_of_objects(NX_UINT): - # identifier_offset(NX_UINT): - # identifier(NX_UINT): - lattice_type: - - # doc: Array of lattice types. - enumeration: [triclinic, monoclinic, orthorhombic, tetragonal, trigonal, hexagonal, cubic] - - # dimensions: - # rank: 1 - # dim: [[1, n]] - miller_plane(NX_NUMBER): - unit: NX_UNITLESS - doc: | - Array of Miller indices which describe the crystallographic plane. - dimensions: - rank: 2 - dim: [[1, n], [2, i]] - - # fastest changing dimension needs to be i because for instance for hexagonal hkil is needed - miller_direction(NX_NUMBER): - unit: NX_UNITLESS - doc: | - Array of Miller indices which describe the crystallographic direction. - dimensions: - rank: 2 - dim: [[1, n], [2, i]] - is_specific(NX_BOOLEAN): - unit: NX_UNITLESS - doc: | - For each slip system a marker whether the specified Miller indices - refer to the specific slip system or the set of crystallographic equivalent - slip systems of the respective family of slip systems. - dimensions: - rank: 1 - dim: [[1, n]] diff --git a/contributed_definitions/nyaml/NXms_ipf.yaml b/contributed_definitions/nyaml/NXms_ipf.yaml deleted file mode 100644 index 11bfc5983..000000000 --- a/contributed_definitions/nyaml/NXms_ipf.yaml +++ /dev/null @@ -1,299 +0,0 @@ -category: base -doc: | - Base class to store an inverse pole figure (IPF) mapping (IPF map). -symbols: - # how to make this optional - n_z: | - Number of pixel along the z slowest direction. - n_y: | - Number of pixel along the y slow direction. - n_x: | - Number of pixel along the x fast direction. - n_rgb: | - Number of RGB values along the fastest direction, always three. - d: | - Dimensionality of the mapping (either 2 or 3). -type: group -NXms_ipf(NXprocess): - \@depends_on(NX_CHAR): - doc: | - Reference to the coordinate system whereby the projection_direction is defined. - - If the field depends_on is not provided but a parent of the instance - of this base class or its specialization defines an :ref:`NXcoordinate_system_set` - and exactly one :ref:`NXcoordinate_system`, the reference points to this system. - - If nothing is provided and none of the above-mentioned references pointing - in a parent, McStas is assumed. - projection_direction(NX_NUMBER): - doc: | - The direction along which orientations are projected. - unit: NX_UNITLESS - dim: (3,) - input_grid(NXcg_grid): - doc: | - Details about the original grid. - - Here original grid means the one onto which the IPF map was computed - when exported from the tech partner's file format representation. - output_grid(NXcg_grid): - doc: | - Details about the grid onto which the IPF is recomputed. - - Rescaling the visualization of the IPF map may be needed to enable - visualization in specific software tools like H5Web. - The value specifies the fractional change of the spacing between - the original mapping and the scaled one. - interpolation(NX_CHAR): - doc: | - How where orientation values at the location of the output grid - positions computed. - - Nearest neighbour means the orientation of the closed (Euclidean distance) - grid point of the input_grid was taken. - enumeration: [nearest_neighbour] - map(NXdata): - doc: | - Inverse pole figure mapping. - - Default inverse pole figure (IPF) plot of the data specific for each - phase. No ipf_mapID instances for non-indexed scan points as these are - by definition assigned the null phase with phase_identifier 0. - Inspect the definition of :ref:`NXcrystal_structure` and its field - phase_identifier for further details. - - Details about possible regridding and associated interpolation - during the computation of the IPF map visualization can be stored - using the input_grid, output_grid, and interpolation fields. - - The main purpose of this map is to offer a normalized default representation - of the IPF map for consumption by a research data management system (RDMS). - This is aligned with the first aim of :ref:`NXms_ipf`, to bring colleagues and - users of IPF maps together to discuss which pieces of information - need to be stored together. We are convinced a step-by-step design and - community-driven discussion about which pieces of information should - and/or need to be included is a practical strategy to work towards an - interoperable description and data model for exchanging IPF maps as specific - community-accepted tools to convey orientation maps. - - With this design the individual RDMS solutions and tools can still continue - to support specific custom data analyses workflow and routes but at least - there is one common understanding which enables also those users who are - not necessarily experts in all the details of the underlying techniques - can understand and thus eventually judge if the dataset is worth to be - reused or repurposed. - # \@signal: data - # \@axes: [axis_y, axis_x] - # \@axis_x_indices: 0 - # \@axis_y_indices: 1 - data(NX_NUMBER): - # assume a mapping with step size 0.5 micron - # we need to distinguish - # pixel position, i.e. 0, 1, 2, 3, unit px - # answers in which pixel on the map but map is disconnected from sample surface context - # calibrated pixel position 0., 0.5, 1.0, 1.5, unit micron - # answers in addition physical dimensions (relevant to get crystal extent etc.) but still disconnected from sample surface context - # calibrated pixel position including the offset of the original coordinate system - # answers everything would enable one to point if still in the microscope where on the sample surface each pixel is located - # tech partners oftentimes do not report to more than calibrated pixel position - doc: | - Inverse pole figure color code for each map coordinate. - unit: NX_UNITLESS - dim: (n_y, n_x, 3) # | (n_z, n_y, n_x, 3) - axis_z(NX_NUMBER): - doc: | - Pixel center coordinate calibrated for step size along the z axis of the map. - unit: NX_LENGTH - dim: (n_z,) - # \@long_name(NX_CHAR): - axis_y(NX_NUMBER): - unit: NX_LENGTH - doc: | - Pixel center coordinate calibrated for step size along the y axis of the map. - dim: (n_y,) - # \@long_name(NX_CHAR): - axis_x(NX_NUMBER): - unit: NX_LENGTH - doc: | - Pixel center coordinate calibrated for step size along the x axis of the map. - dim: (n_x,) - # \@long_name(NX_CHAR): - # title: - legend(NXdata): - doc: | - The color code which maps colors into orientation into the fundamental zone. - - For each stereographic standard triangle (SST), i.e. a rendering of the - fundamental zone of the crystal-symmetry-reduced orientation space - SO3, it is possible to define a color model which assigns each point in - the fundamental zone a color. - - Different mapping models are used. These implement (slightly) different - scaling relations. Differences exist across representations of tech partners. - - Differences are which base colors of the RGB color model are placed in - which extremal position of the SST and where the white point is located. - - For further details see: - - * [G. Nolze et al.](https://doi.org/10.1107/S1600576716012942) - * Srikanth Patala and coworkers"'" work and of others. - - Details are implementation-specific and not standardized yet. - - Given that the SST has a complicated geometry, it cannot yet be - visualized using tools like H5Web, which is why for now the matrix - of a rasterized image which is rendered by the backend tool gets - copied into an RGB matrix to offer a default plot. - # \@signal: data - # \@axes: [axis_y, axis_x] - # \@axis_x_indices: 0 - # \@axis_y_indices: 1 - data(NX_NUMBER): - # hehe, but can be larger than one but could also be an NX_DIMENSIONLESS ! - doc: | - Inverse pole figure color code for each map coordinate. - unit: NX_UNITLESS - dim: (n_y, n_x, 3) - axis_y(NX_NUMBER): - doc: | - Pixel along the y-axis. - unit: NX_UNITLESS - dim: (n_y,) - # \@long_name(NX_CHAR): - axis_x(NX_NUMBER): - doc: | - Pixel along the x-axis. - unit: NX_UNITLESS - dim: (n_x,) - # \@long_name(NX_CHAR): - # title: - -# keep this for now for FAIRmat internal documentation -# It is important to mention that we cannot assume, at least for now, -# that the parser which writes to an NXem_ebsd-compliant file is also -# responsible or capable at all of computing the inverse pole figure -# color keys and maps itself. This cannot be assumed working because -# this mapping of orientation data uses involved mathematical algorithms -# and functions which not every tools used in the EBSD community is capable -# of using or is for sure not using in exactly the same way. -# -# Currently, we assume it is the responsibilty of the tool used which -# generated the data under on_the_fly_indexing to compute these -# plots and deliver these to the parser. -# -# Specific case studies have been explored by the experiment team of -# Area B of the FAIRmat project to realize and implement such mapping. -# -# The first case study uses the H5OINA format and the pyxem/orix library. -# As orix is a Python library, the coloring is performed by the em_om parser. -# -# The second case study uses MTex and its EBSD color coding model. -# As MTex is a Matlab tool, an intermediate format is written from MTex -# first which stores these pieces of information. The parser then pulls -# these data from the intermediate Matlab-agnostic representation and -# supplements the file with missing pieces of information as it is -# required by NXem_ebsd. -# -# The third case study shows how a generic set of Kikuchi pattern -# can be loaded with the em_om parser. The pattern are loaded directly -# from a ZIP file and mapped to an simulation image section for now. -# -# The fourth case study uses the DREAM.3D package which provides an own -# set of EBSD data post-processing procedures. DREAM.3D documents the -# processing steps with a pipeline file which is stored inside DREAM.3D -# output files. In this case study, the parser reads the DREAM.3D file -# and maps data relevant from the perspective of NXem_ebsd plus adds -# relevant IPF color maps as they were computed by DREAM.3D. -# Given that in this case the origin of the data is the DREAM.3D file -# again provenance is kept and more details can be followed upon when -# resolving origin. -# -# These examples offer a first set of suggestions on how to make EBSD -# data injectable into research data management system using schemes -# which themselves are agnostic to the specific RDMS and interoperable. -# Steps of collecting the raw data and post-processing these with custom -# scripts like MTex or commercial tools so far are mainly undocumented. -# The limitation is that a program which consumes results or dump files -# from these tools may not have necessarily all the sufficient information -# available to check if the injected orientation data and color models -# are matching the conventions which a user or automated system has -# injected into an electronic lab notebook from which currently the em_om -# parser collects the conventions and stores them into this NXem_ebsd instance. -# The immediate benefit of the here presented NXem_ebsd concept though -# is that the conventions and reference frame definitions are expected -# in an ELN-agnostic representation to make NXem_ebsd a generally useful -# data scheme for EBSD. -# -# Ideally, the em_om parser would load convention-compliant EBSD data -# and use subsequently a community library to transcode/convert orientation -# conventions and parameterized orientation values. Thereafter, convention- -# compliant default plot(s) could be created that would be truely interoperable. -# -# However, given the variety of post-processing tools available surplus -# the fact that these are not usually executed along standardized -# post-processing workflows which perform exactly the same algorithmic steps, -# this is currently not a practically implementable option. Indeed, first -# developers who wish to implement this would first have to create a library -# for performing such tasks, mapping generally between conventions, -# i.e. map and rotate coordinate systems at the parser level. -# -# The unfortunate situation in EBSD is that due to historical reasons -# and competitive strategies, different players in the field have -# implemented (slightly) different approaches each of which misses -# some part of a complete workflow description which is behind EBSD analyses: -# Sample preparation, measurement, indexing, post-processing, paper... -# -# The here exemplified default plot do not so far apply relevant rotations -# but takes the orientation values as they come from the origin and using -# coloring them as they come. It is thus the scientists responsibility to -# enter and check if the respective dataset is rotation-conventions-wise -# consistent and fit for a particular task. -# -# Ideally, with all conventions defined it can be possible to develop -# a converter which rotates the input data. This application definition -# does not assume this and users should be aware of this limitation. -# -# The key point is that the conventions however are captured and this is -# the most important step to the development of such a generic transcoder -# for creating interoperable EBSD datasets. -# -# Currently the conventions remain in the mind or manual lab book of the -# respective scientists or technicians instead of getting stored and -# communicated with research papers that are written based on -# specific dataset, i.e. database entries. -# -# The default gridded representation of the data should not be -# misinterpreted as the only possible way how EBSD data and OIM -# maps can be created! -# -# Indeed, the most general case is that patterns are collected for -# scan points. The scan generator of an electron microscope is instructed -# to steer the beam in such a way across the specimen surface that the -# beam illuminates certain positions for a certain amount time (usually -# equally-spaced and spending about the same amount of time at each -# position). -# -# Therefore, scan positions can be due to such regular flight plans and -# represent sampling on lines, line stacks, rectangular regions-of- -# interests, but also could instruct spiral, random, or adaptive scans -# instead of tessellations with square or hexagonal pixels. -# -# The majority of EBSD maps is though is reporting results for a regular -# grid (square, hexagon). What matters though in terms of damage induced -# by the electron beam and signal quality is the real electron dose -# history, i.e. for how long the beam exposed which location of the -# specimen. Especially when electron charging occurs (i.e. an excess -# amount of charge accumulates due to e.g. poor conducting away of this -# charge or an improper mounting, too high dose, etc. such details are -# relevant. -# -# Specifically, the default visualization is an inverse pole-figure (IPF) -# map with the usual RGB color coding. Different strategies and -# normalization schemes are in use to define such color coding. -# -# Finally, we should mention that each ipf_map represents data for -# scan points indexed as one phase. The alias/name of this phase should -# be stored in phase_name, the phase_identifier give an ID which must -# not be zero as this value is reserved for non-indexed / null model scan -# points. \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXms_ipf_set.yaml b/contributed_definitions/nyaml/NXms_ipf_set.yaml deleted file mode 100644 index a783655a2..000000000 --- a/contributed_definitions/nyaml/NXms_ipf_set.yaml +++ /dev/null @@ -1,9 +0,0 @@ -category: base -doc: | - Base class to group multiple :ref:`NXms_ipf` instances. - - A collection of inverse pole figure approximations. -# symbols: -type: group -NXms_ipf_set(NXprocess): - (NXms_ipf): diff --git a/contributed_definitions/nyaml/NXms_mtex_config.yaml b/contributed_definitions/nyaml/NXms_mtex_config.yaml deleted file mode 100644 index b8fee982d..000000000 --- a/contributed_definitions/nyaml/NXms_mtex_config.yaml +++ /dev/null @@ -1,187 +0,0 @@ -category: base -doc: | - Base class to store the configuration when using the MTex/Matlab software. - - MTex is a Matlab package for texture analysis used in the Materials and Earth Sciences. - See `R. Hielscher et al. `_ and - the `MTex source code `_ for details. -type: group -NXms_mtex_config(NXobject): - conventions(NXcollection): - doc: | - Reference frame and orientation conventions. - Consult the `MTex docs `_ for details. - x_axis_direction(NX_CHAR): - doc: | - TODO with MTex developers - # enumeration: - # check against v5.12 - z_axis_direction(NX_CHAR): - doc: | - TODO with MTex developers - # enumeration: - a_axis_direction(NX_CHAR): - doc: | - TODO with MTex developers - # enumeration: - b_axis_direction(NX_CHAR): - doc: | - TODO with MTex developers - # enumeration: - euler_angle(NX_CHAR): - doc: | - TODO with MTex developers - enumeration: [unknown, undefined, bunge] - plotting(NXcollection): - doc: | - Settings relevant for generating plots. - font_size(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY - inner_plot_spacing(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY - outer_plot_spacing(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY - marker_size(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY - figure_size(NX_NUMBER): - doc: | - TODO with MTex developers - show_micron_bar(NX_BOOLEAN): - doc: | - True if MTex renders a scale bar with figures. - show_coordinates(NX_BOOLEAN): - doc: | - True if MTex renders a grid with figures. - pf_anno_fun_hdl: - doc: | - Code for the function handle used for annotating pole figure plots. - color_map(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_UNITLESS - dim: (i, 3) - default_color_map(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_UNITLESS - dim: (i, 3) - # phase_color_order: - # doc: | - # TODO with MTex developers - # unit: NX_UNITLESS - # dim: (i,) - color_palette(NX_CHAR): - degree_char(NX_CHAR): - doc: | - TODO with MTex developers - arrow_char(NX_CHAR): - doc: | - TODO with MTex developers - marker(NX_CHAR): - doc: | - TODO with MTex developers - marker_edge_color(NX_CHAR): - doc: | - TODO with MTex developers - marker_face_color(NX_CHAR): - doc: | - TODO with MTex developers - hit_test(NX_BOOLEAN): - doc: | - TODO with MTex developers - miscellaneous(NXcollection): - doc: | - Miscellaneous other settings of MTex. - mosek(NX_BOOLEAN): - doc: | - TODO with MTex developers - generating_help_mode(NX_BOOLEAN): - doc: | - TODO with MTex developers - methods_advise(NX_BOOLEAN): - doc: | - TODO with MTex developers - stop_on_symmetry_mismatch(NX_BOOLEAN): - doc: | - TODO with MTex developers - inside_poly(NX_BOOLEAN): - doc: | - TODO with MTex developers - text_interpreter: - numerics(NXcollection): - doc: | - Miscellaneous settings relevant for numerics. - eps(NX_NUMBER): - doc: | - Return value of the Matlab eps command. - unit: NX_UNITLESS - fft_accuracy(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY # NX_LENGTH or NX_RECIPROCAL_LENGTH? - max_stwo_bandwidth(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY # radiant? - max_sothree_bandwidth(NX_NUMBER): - doc: | - TODO with MTex developers - unit: NX_ANY # radiant? - system(NXcollection): - doc: | - Miscellaneous settings relevant of the system where MTex runs. - memory(NX_NUMBER): - doc: | - TODO with MTex developers - open_gl_bug(NX_BOOLEAN): - doc: | - TODO with MTex developers - save_to_file(NX_BOOLEAN): - doc: | - TODO with MTex developers - path(NXcollection): - doc: | - Collection of paths from where MTex reads information and code. - mtex(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - data(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - cif(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - ebsd(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - pf(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - odf(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - tensor(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - example(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - import_wizard(NX_CHAR): - doc: | - Absolute path to specific component of MTex source code. - pf_extensions(NX_CHAR): - doc: | - List of file type suffixes for which MTex assumes - texture/pole figure information. - ebsd_extensions(NX_CHAR): - doc: | - List of file type suffixes for which MTex assumes EBSD content. - # version as an instance of (NXprogram) one for MTex one for Matlab diff --git a/contributed_definitions/nyaml/NXms_odf.yaml b/contributed_definitions/nyaml/NXms_odf.yaml deleted file mode 100644 index 92ad96589..000000000 --- a/contributed_definitions/nyaml/NXms_odf.yaml +++ /dev/null @@ -1,99 +0,0 @@ -category: base -doc: | - Base class to store an orientation distribution function (ODF) computation. -symbols: - n_varphi_one: | - Number of pixel per varphi section plot along the varphi_one fastest direction. - n_capital_phi: | - Number of pixel per varphi section plot along the capital_phi slow direction. - n_varphi_two: | - Number of pixel per varphi section plot along the varphi_two slowest direction. - k: | - Number of local maxima evaluated in the component analysis. -type: group -NXms_odf(NXprocess): - configuration(NXobject): - doc: | - Details about the algorithm used for computing the ODF. - crystal_symmetry_point_group(NX_CHAR): - doc: | - Point group of the crystal structure (International Table of Crystallography) - of the phase for which the here documented phase-dependent ODF was computed. - specimen_symmetry_point_group(NX_CHAR): - doc: | - Point group assumed for processing-induced *sample symmetries*. - (according to International Table of Crystallography). - kernel_halfwidth(NX_NUMBER): - doc: | - Halfwidth of the kernel. - unit: NX_ANGLE - kernel_name(NX_CHAR): - doc: | - Name of the kernel. - resolution(NX_NUMBER): - doc: | - Resolution of the kernel. - unit: NX_ANGLE - kth_extrema(NXobject): - kth(NX_UINT): - doc: | - Number of local maxima evaluated for the ODF. - unit: NX_UNITLESS - # value of kth should be k - location(NX_NUMBER): - doc: | - Euler angle representation of the kth-most maxima of the ODF - in decreasing order of the intensity maximum. - unit: NX_ANGLE - dim: (k, 3) - theta(NX_NUMBER): - doc: | - Disorientation threshold within which intensity of the ODF - is integrated for the component analysis. - unit: NX_ANGLE - volume_fraction(NX_NUMBER): - doc: | - Integrated ODF intensity within a theta-ball of SO3 about - each location as specified for each location in the order - and reported in the order of these locations. - unit: NX_ANY - dim: (k,) - phi_two_plot(NXdata): - doc: | - Visualization of the ODF intensity as orthogonal sections through Euler space. - - This is one example of typical default plots used in the texture - community in Materials Engineering. - - Mind that the Euler space is a distorted space. Therefore, equivalent - orientations show intensity contributions in eventually multiple - locations. - # \@signal: intensity - # \@axes: [varphi_two, capital_phi, varphi_one] - # \@varphi_one_indices: 0 - # \@capital_phi: 1 - # \@varphi_two_indices: 2 - intensity(NX_NUMBER): - doc: | - ODF intensity at probed locations relative to - null model of a completely random texture. - unit: NX_DIMENSIONLESS - dim: (n_varphi_two, n_capital_phi, n_varphi_one) - varphi_one(NX_NUMBER): - doc: | - Pixel center angular position along the :math:`\varphi_1` direction. - unit: NX_ANGLE - dim: (n_varphi_one,) - # \@long_name(NX_CHAR): - varphi_two(NX_NUMBER): - doc: | - Pixel center angular position along the :math:`\varphi_2` direction. - unit: NX_ANGLE - dim: (n_varphi_two,) - # \@long_name(NX_CHAR): - capital_phi(NX_NUMBER): - doc: | - Pixel center angular position along the :math:`\Phi` direction. - unit: NX_ANGLE - dim: (n_capital_phi,) - # \@long_name(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXms_odf_set.yaml b/contributed_definitions/nyaml/NXms_odf_set.yaml deleted file mode 100644 index 5ea1c4d6c..000000000 --- a/contributed_definitions/nyaml/NXms_odf_set.yaml +++ /dev/null @@ -1,9 +0,0 @@ -category: base -doc: | - Base class to group multiple :ref:`NXms_odf` instances. - - A collection of orientation distribution function approximations. -# symbols: -type: group -NXms_odf_set(NXprocess): - (NXms_odf): diff --git a/contributed_definitions/nyaml/NXms_pf.yaml b/contributed_definitions/nyaml/NXms_pf.yaml deleted file mode 100644 index 09ab12f78..000000000 --- a/contributed_definitions/nyaml/NXms_pf.yaml +++ /dev/null @@ -1,59 +0,0 @@ -category: base -doc: | - Base class to store a pole figure (PF) computation. -symbols: - n_y: | - Number of pixel per pole figure in the slow direction. - n_x: | - Number of pixel per pole figure in the fast direction. -type: group -NXms_pf(NXprocess): - configuration(NXobject): - doc: | - Details about the algorithm that was used to compute the pole figure. - crystal_symmetry_point_group(NX_CHAR): - doc: | - Point group of the crystal structure of the phase for which the - here documented phase-dependent pole figure was computed - (according to International Table of Crystallography). - specimen_symmetry_point_group(NX_CHAR): - doc: | - Point group assumed for processing induced *sample symmetries* - (according to International Table of Crystallography). - halfwidth(NX_NUMBER): - doc: | - Halfwidth of the kernel. - unit: NX_ANGLE - miller_indices(NX_CHAR): - doc: | - Miller indices (:math:`(hkl)[uvw]`) to specify the pole figure. - resolution(NX_NUMBER): - doc: | - Resolution of the kernel. - unit: NX_ANGLE - pf(NXdata): - doc: | - Pole figure. - # \@signal: intensity - # \@axes: [axis_y, axis_x] - # \@axis_x_indices: 0 - # \@axis_y_indices: 1 - intensity(NX_NUMBER): - doc: | - Pole figure intensity. - unit: NX_UNITLESS - dim: (n_y, n_x) - axis_y(NX_NUMBER): - doc: | - Pixel center along y direction in the equatorial plane of - a stereographic projection of the unit sphere. - unit: NX_ANY - dim: (n_y,) - # \@long_name(NX_CHAR): - axis_x(NX_NUMBER): - doc: | - Pixel center along x direction in the equatorial plane of - a stereographic projection of the unit sphere. - unit: NX_ANY - dim: (n_x,) - # \@long_name(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXms_pf_set.yaml b/contributed_definitions/nyaml/NXms_pf_set.yaml deleted file mode 100644 index afd785f15..000000000 --- a/contributed_definitions/nyaml/NXms_pf_set.yaml +++ /dev/null @@ -1,9 +0,0 @@ -category: base -doc: | - Base class to group multiple :ref:`NXms_pf` instances. - - A collection of pole figure approximations. -# symbols: -type: group -NXms_pf_set(NXprocess): - (NXms_pf): diff --git a/contributed_definitions/nyaml/NXms_recon.yaml b/contributed_definitions/nyaml/NXms_recon.yaml deleted file mode 100644 index bd6825bac..000000000 --- a/contributed_definitions/nyaml/NXms_recon.yaml +++ /dev/null @@ -1,315 +0,0 @@ -# position would need another depends_on the specific coordinate system used, currently we assume McStas -# roi1/ebsd/microstructure1 -category: base -doc: | - Base class to describe discretized (micro)structural features of a material. - - One instance of this base class can be used to describe the current configuration - the base class does not include time-dependent descriptions for the sake of - clarity and because of the fact that virtually all simulations or experiments - probe time by sampling. Therefore, time-dependent state descriptions should - be realized with creating a set of :ref:`NXms_snapshot_set` with instances of - :ref:`NXms_snapshot` using e.g. :ref:`NXms_recon` base class instances. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. - # in so-called linear intercept analysis we observe - # one-dimensional sections of either projections (see below) - # or true one-dimensional cuts across a volume of material - # n_icept: | - # The number of linear intercepts defined. - # n_c_one: | - # The number of crystal projections segmented by crossing (projected or real) interfaces - # n_i_one: | - # The number of crossings - # two-dimensional projections of characterized in reality three-dimensional objects - # using E. E. Underwood notation - # crystals/grains are projections that are delineated by projections of interface, i.e. interface lines which meet at projections of triple lines i.e. triple "points" - n_c_two: | - The number of crystal projections. - n_i_two: | - The number of interface projections. - n_t_two: | - The number of assumed triple junction projections aka triple points. - # three-dimensional real objects, volumetrically characterized - # crystals are delineated by interfaces that are delineated by triple lines that meet at quad junctions - n_c: | - The number of crystals. - n_i: | - The number of interfaces - n_t: | - The number of triple lines - n_q: | - The number of quadruple junctions. -type: group -NXms_recon(NXobject): - # as e.g. a result of one grain reconstruction with MTex or othe - # grain reconstruction software in commercial tools - # the idea is we may wish to run as many grain reconstructions as we want... - # add details about the processing - configuration(NXprocess): - doc: | - The configuration and parameterization of the reconstruction algorithm - whereby the microstructural features were identified. - # maybe a depends_on what was the input however if the group is injected - # in an roi1/ebsd instance isnt this information implicit? - dimensionality(NX_POSINT): - doc: | - Dimensionality of the analysis. - - This field can be used e.g. by a research data management system - to identify if the described feature set specifies a - one-, two-, or three-dimensional feature set. - unit: NX_UNITLESS - enumeration: [1, 2, 3] - algorithm(NX_CHAR): - doc: | - Which algorithm is used to reconstruct the features. - enumeration: [unknown, disorientation_clustering, fast_multiscale_clustering, markov_chain_clustering] - disorientation_threshold(NX_NUMBER): - doc: | - Threshold to define at which disorientation angle to assume - two crystalline regions have a significant orientation difference - which warrants to argue that there is an interface between the - two regions. - unit: NX_ANGLE - # the result of running one grain reconstruction - # ms_feature_set1 - # we could also enumerate instances ms_feature_setID here because configuration - # may specify a range of different parameter resulting in multiple ms_feature_sets - # dimensionality(N) composed from NXms_feature_set base: - # controlled vocabulary of base class instances to be used to inform about the - # discretization of these features instances to discretize the features - # wherever possible the computational geometry specific instances whose - # purpose is only to support/represent the discretization of the features should - # be separated out from the materials engineering interpretation of what these - # features are, i.e. a grain that is measured with a 2d section ends up - # modelled as an projection of that real 3d grain object - # the model is discretized usign a polyline which models the location of the - # interface at the required here coarse-grained continuum picture - points(NXcg_point_set): - lines(NXcg_polyline_set): - surfaces(NXcg_triangle_set): - volumes(NXcg_polyhedron_set): - - # domain-specific, i.e. microstructural features - # ONE DIMENSIONAL FEATURES - - # TWO DIMENSIONAL FEATURES - crystal_projections(NXms_feature_set): - doc: | - Projections of crystals on the sample surface as typically - characterized with optical or electron microscopy. - \@discretization(NX_CHAR): - doc: | - Reference to lines(NXcg_polyline_set) which supports the - discretized shape of each cross-sectioned crystal. - - Most microscopy techniques support to generate only a two-dimensional - representation (projection) of the characterized material. - - For true volumetric techniques use the specifically - specialized crystals :ref:`NXms_feature_set` instead. - See stereology literature for more details e.g. - E.E. Underwood's book entitled Quantitative Stereology - number_of_crystals(NX_UINT): - doc: | - Number of crystals. - unit: NX_UNITLESS - crystal_identifier_offset(NX_INT): - doc: | - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - unit: NX_UNITLESS - crystal_identifier(NX_INT): - doc: | - Identifier used for crystals for explicit indexing. - unit: NX_UNITLESS - dim: (n_c_two,) - number_of_phases(NX_UINT): - doc: | - How many phases are distinguished - unit: NX_UNITLESS - phase_identifier_offset(NX_INT): - doc: | - Integer offset whereby the identifier of the first member - of the set differs from zero. - unit: NX_UNITLESS - phase_identifier(NX_INT): - # \@depends_on(NX_CHAR): - doc: | - Identifier used for phase for explicit indexing. - unit: NX_UNITLESS - dim: (n_c_two,) - # properties of crystal_projections aka grain properties - boundary_contact(NX_BOOLEAN): - doc: | - True, if the crystal makes contact with the edge of the ROI, - false otherwise. - dim: (n_c_two,) - orientation_spread(NX_NUMBER): - doc: | - Average disorientation angle between individual orientation of the - crystal at probed positions (weighted by area of that position) versus - the average disorientation of the crystal. - unit: NX_ANGLE - dim: (n_c_two,) - (NXrotation_set): - area(NX_NUMBER): - doc: | - Calibrated area of surrounded by the polyline about each crystal. - unit: NX_AREA - dim: (n_c_two,) - interface_projections(NXms_feature_set): - # grain boundaries have a network of line-like defects, its explicit description - # often generates unnecessary information duplication and cluttering, - # therefore here a compact and suggestion how to store such data - doc: | - Projections of grain or phase boundaries as typically sectioned - with optical or electron microscopy characterization. - \@discretization(NX_CHAR): - doc: | - Reference to lines(NXcg_polyline_set) which supports the - discretized shape of each cross-sectioned crystal. - - Set of tuples of polyline segments which build the interface. - # topology - # i) Set of pair of crystals sharing an interface - crystals(NX_INT): - doc: | - Set of pairs of crystal_identifier resolved via depends_on which - are adjacent to each interface. - unit: NX_UNITLESS - dim: (n_i_two, 2) - \@depends_on(NX_CHAR): - doc: | - The specific crystal_projections(NXms_feature_set) instance - to resolve crystal identifier. - # ii) Set of pair of topologically connected triple points - triple_points(NX_INT): - doc: | - Set of pairs of triple_point_identifier which the interface connects. - For 2D projections of 3D microstructural features a triple point is - physically only the projection of a triple line. - unit: NX_UNITLESS - dim: (n_i_two, 2) - \@depends_on(NX_CHAR): - doc: | - The specific triple_line_projections(NXms_feature_set) instance - whereby to resolve triple_point identifier. - # alternatively which polyline of adjoining interfaces - # properties, descriptors - length(NX_NUMBER): - doc: | - The length of the interface. - - This is not necessarily the same as the length of the individual - polyline segments whereby the interface is discretized. - - The actual coordinate system whereby the geometry is calibrated - with real physical dimensions is typically documented by the - depends_on attribute of the respective NXcg_primitive_set. - This depends_on attribute should point explicitly to an - instance of a :ref:`NXcoordinate_system` to support users as - much as possible with interpreting how and where the lines are - located in the reference frame. - unit: NX_LENGTH - dim: (n_i_two,) - interface_identifier_offset(NX_INT): - doc: | - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - unit: NX_UNITLESS - interface_identifier(NX_INT): - doc: | - Identifier for each interface using explicit indexing. - unit: NX_UNITLESS - dim: (n_i_two,) - triple_line_projections(NXms_feature_set): - # only for 2D, quad junction is the equivalent for 3D is not a triple_line - # four alternative descriptors with different strength to specify spatial - # or logical information about the triple junction feature set. - # the explicit description often generating unnecessary information duplication - doc: | - Projections of triple lines as typically characterized with optical - or electron microscopy. - - Mind that most specimens are thermo-chemo-mechanically treated before - they are characterized. Therefore, the projected crystal defects are - have physically no longer the same structure as in the bulk. - - Examples are manifest as effects such as thermal grooving, or relaxation - effects of an intersection between a triple line that is cut - by the specimen surface as these defects are then exposed typically - to a different atmosphere and hence have different thermodynamic boundary - conditions than of their true volumetric defects in the bulk. - \@discretization(NX_CHAR): - doc: | - Reference to points(NXcg_point_set) which supports the - locations of these triple points. - # another view to describe a triple junction is via its topology/connection expressed either via - # i) triplet of interface identifier - number_of_triple_points(NX_UINT): - doc: | - Number of triple points. - unit: NX_UNITLESS - triple_point_identifier_offset(NX_INT): - doc: | - Integer offset whereby the identifier of the first member - of the set differs from zero. - - Identifiers can be defined either implicitly or explicitly. - For implicit indexing identifiers are defined on the interval - :math:`[identifier_offset, identifier_offset + c - 1]`. - unit: NX_UNITLESS - triple_point_identifier(NX_INT): - doc: | - Identifier for each triple point using explicit indexing. - unit: NX_UNITLESS - dim: (n_t_two,) - location(NX_INT): - doc: | - Set of triple point identifiers. - unit: NX_UNITLESS - dim: (n_t_two,) - \@depends_on(NX_CHAR): - doc: | - The relevant points(NXcg_point_set) instance whereby to - resolve interface identifiers. - interfaces(NX_INT): # aka topology or interfaces - doc: | - Set of triplets of identifier of line-like features. - Each triplet resolves which three interface projections - the triple point connects. - unit: NX_UNITLESS - dim: (n_t_two, 3) - \@depends_on(NX_CHAR): - doc: | - The specific interface_projections(NXms_feature_set) - instance whereby to resolve interface identifiers. - # ii) a triplet of line segment identifier whereby the point-like features - # is assumed discretized via three polylines representing interfaces - polylines(NX_INT): - doc: | - Triplet of identifier of polyline segments. Each triplet resolves - which three segments of polyline segments the triple junction connects. - unit: NX_UNITLESS - dim: (n_t_two, 3) - \@depends_on(NX_CHAR): - doc: | - The specific lines(NXcg_polyline_set) instance to resolve - polyline segments. - # the difference in the interpretation of interfaces and polylines - # is that the interface resolves interface (e.g. phase boundary names) - # while polylines resolves segments within the set of named geometric primitive - # instances! - # add all sort of other qualitative or quantitive descriptors (triple junction - # energy, volume etc), i.e properties of that triple point diff --git a/contributed_definitions/nyaml/NXroi.yaml b/contributed_definitions/nyaml/NXroi.yaml deleted file mode 100644 index a8ba2426a..000000000 --- a/contributed_definitions/nyaml/NXroi.yaml +++ /dev/null @@ -1,9 +0,0 @@ -category: base -doc: | - Base class to describe a region-of-interest analyzed. -type: group -NXroi(NXobject): - (NXprocess): - doc: | - Details about processing steps. - sequence_index(NX_INT): diff --git a/requirements.txt b/requirements.txt index b274b11d1..ba1f751d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,4 +14,4 @@ pytest # Code style and auto-formatting black>=22.3 flake8>=4 -isort>=5.10 \ No newline at end of file +isort>=5.10 From 06cb9b80c3eec8fdc0715fd25d0121fb43ed7ca2 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:54:07 +0200 Subject: [PATCH 124/136] improvments according to code review: replace xxx in attrib.keys() and attrib[xxx] == yyy by attrib.get(xxx) == yyy --- dev_tools/tests/test_nxdl_utils.py | 165 +++++++++++++++++++++++++++++ dev_tools/utils/nxdl_utils.py | 22 +--- 2 files changed, 170 insertions(+), 17 deletions(-) diff --git a/dev_tools/tests/test_nxdl_utils.py b/dev_tools/tests/test_nxdl_utils.py index 7b10494bf..7b3953847 100644 --- a/dev_tools/tests/test_nxdl_utils.py +++ b/dev_tools/tests/test_nxdl_utils.py @@ -5,6 +5,7 @@ import os import lxml.etree as ET +import pytest from ..utils import nxdl_utils as nexus @@ -48,11 +49,175 @@ def test_get_node_at_nxdl_path(): ) assert node.attrib["name"] == "long_name" + # nxdl_file_path = os.path.join(local_dir, "../../applications/NXem.nxdl.xml") + # elem = ET.parse(nxdl_file_path).getroot() + # node = nexus.get_node_at_nxdl_path( + # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/end_time", elem=elem + # ) + # assert node.attrib["name"] == "end_time" + + # node = nexus.get_node_at_nxdl_path("/ENTRY/measurement", elem=elem) + # assert node.attrib["type"] == "NXem_msr" + + # node = nexus.get_node_at_nxdl_path( + # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/IMAGE_SET/image_3d", + # elem=elem, + # ) + # assert node.attrib["type"] == "NXdata" + + # node = nexus.get_node_at_nxdl_path( + # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/IMAGE_SET/image_3d/AXISNAME_indices", + # elem=elem, + # ) + # assert node.attrib["name"] == "AXISNAME_indices" + + # node = nexus.get_node_at_nxdl_path( + # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/IMAGE_SET/image_3d/axis_j", + # elem=elem, + # ) + # assert node.attrib["type"] == "NX_NUMBER" + + # node = nexus.get_node_at_nxdl_path("/ENTRY/coordinate_system_set", elem=elem) + # assert node.attrib["type"] == "NXcoordinate_system_set" + + nxdl_file_path = os.path.join( + local_dir, "../../contributed_definitions/NXiv_temp.nxdl.xml" + ) + elem = ET.parse(nxdl_file_path).getroot() + node = nexus.get_node_at_nxdl_path( + "/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", elem=elem + ) + assert node.attrib["name"] == "voltage_controller" + + node = nexus.get_node_at_nxdl_path( + "/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller/calibration_time", elem=elem + ) + assert node.attrib["name"] == "calibration_time" + def test_get_inherited_nodes(): """Test to verify if we receive the right XML element list for a given NXDL path.""" local_dir = os.path.abspath(os.path.dirname(__file__)) + nxdl_file_path = os.path.join(local_dir, "./NXtest.nxdl.xml") elem = ET.parse(nxdl_file_path).getroot() (_, _, elist) = nexus.get_inherited_nodes(nxdl_path="/ENTRY/NXODD_name", elem=elem) assert len(elist) == 3 + + nxdl_file_path = os.path.join( + local_dir, "../../contributed_definitions/NXiv_temp.nxdl.xml" + ) + + elem = ET.parse(nxdl_file_path).getroot() + (_, _, elist) = nexus.get_inherited_nodes( + nxdl_path="/ENTRY/INSTRUMENT/ENVIRONMENT", elem=elem + ) + assert len(elist) == 3 + + (_, _, elist) = nexus.get_inherited_nodes( + nxdl_path="/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", elem=elem + ) + assert len(elist) == 4 + + (_, _, elist) = nexus.get_inherited_nodes( + nxdl_path="/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", + nx_name="NXiv_temp", + ) + assert len(elist) == 4 + + +@pytest.mark.parametrize( + "hdf_name,concept_name,should_fit", + [ + ("source_pump", "sourceType", False), + ("source_pump", "sourceTYPE", True), + ("source pump", "sourceTYPE", False), + ("source", "sourceTYPE", False), + ("source123", "SOURCE", True), + ("1source", "SOURCE", True), + ("_source", "SOURCE", True), + ("same_name", "same_name", True), + ("angular_energy_resolution", "angularNresolution", True), + ("angularresolution", "angularNresolution", False), + ("Name with some whitespaces in it", "ENTRY", False), + ("simple_name", "TEST", True), + (".test", "TEST", False), + ], +) +def test_namefitting(hdf_name, concept_name, should_fit): + """Test namefitting of nexus concept names""" + if should_fit: + assert nexus.get_nx_namefit(hdf_name, concept_name, name_partial=True) > -1 + else: + assert nexus.get_nx_namefit(hdf_name, concept_name, name_partial=True) == -1 + + +@pytest.mark.parametrize( + "hdf_name,concept_name, score", + [ + ("test_name", "TEST_name", 9), + ("te_name", "TEST_name", 7), + ("my_other_name", "TEST_name", 5), + ("test_name", "test_name", 18), + ("test_other", "test_name", -1), + ("my_fancy_yet_long_name", "my_SOME_name", 8), + ("something", "XXXX", 0), + ("something", "OTHER", 1), + ], +) +def test_namefitting_scores(hdf_name, concept_name, score): + """Test namefitting of nexus concept names""" + assert nexus.get_nx_namefit(hdf_name, concept_name, name_partial=True) == score + + +@pytest.mark.parametrize( + "better_fit,better_ref,worse_fit,worse_ref", + [ + ("sourcetype", "sourceTYPE", "source_pump", "sourceTYPE"), + ("source_pump", "sourceTYPE", "source_pump", "TEST"), + ], +) +def test_namefitting_precedence(better_fit, better_ref, worse_fit, worse_ref): + """Test if namefitting follows proper precedence rules""" + + assert nexus.get_nx_namefit( + better_fit, better_ref, name_partial=True + ) > nexus.get_nx_namefit(worse_fit, worse_ref) + + +@pytest.mark.parametrize( + "string_obj, decode, expected", + [ + # Test with lists of bytes and strings + ([b"bytes", "string"], True, ["bytes", "string"]), + ([b"bytes", "string"], False, [b"bytes", "string"]), + ([b"bytes", b"more_bytes", "string"], True, ["bytes", "more_bytes", "string"]), + ( + [b"bytes", b"more_bytes", "string"], + False, + [b"bytes", b"more_bytes", "string"], + ), + ([b"fixed", b"length", b"strings"], True, ["fixed", "length", "strings"]), + ([b"fixed", b"length", b"strings"], False, [b"fixed", b"length", b"strings"]), + # Test with nested lists + ([[b"nested1"], [b"nested2"]], True, [["nested1"], ["nested2"]]), + ([[b"nested1"], [b"nested2"]], False, [[b"nested1"], [b"nested2"]]), + # Test with bytes + (b"single", True, "single"), + (b"single", False, b"single"), + # Test with str + ("single", True, "single"), + ("single", False, "single"), + # Test with int + (123, True, 123), + (123, False, 123), + ], +) +def test_decode_or_not(string_obj, decode, expected): + # Handle normal cases + result = nexus.decode_or_not(elem=string_obj, decode=decode) + if isinstance(expected, list): + assert isinstance(result, list), f"Expected list, but got {type(result)}" + # Handle all other cases + else: + assert result == expected, f"Failed for {string_obj} with decode={decode}" diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 74f5d7863..d5ced922e 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -310,9 +310,7 @@ def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): return True if not hdf_name: # search for name fits is only allowed for hdf_nodes return False - name_any = ( - "nameType" in child.attrib.keys() and child.attrib["nameType"] == "any" - ) or ( + name_any = child.attrib["nameType"].get("nameType") == "any" or ( get_local_name_from_xml(child) == "group" and "nameType" not in child.attrib.keys() and "name" not in child.attrib.keys() @@ -325,9 +323,7 @@ def belongs_to_capital(params): """Checking continues for Upper case""" (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params # or starts with capital and no reserved words used - name_partial = ( - "nameType" in child.attrib.keys() and child.attrib["nameType"] == "partial" - ) or ( + name_partial = child.attrib["nameType"].get("nameType") == "partial" or ( get_local_name_from_xml(child) == "group" and "nameType" not in child.attrib.keys() and "name" not in child.attrib.keys() @@ -352,10 +348,7 @@ def belongs_to_capital(params): and "nameType" not in child2.attrib.keys() and "name" not in child2.attrib.keys() ) - name_partial2 = ( - "nameType" in child2.attrib.keys() - and child2.attrib["nameType"] == "partial" - ) + name_partial2 = child2.attrib.get("nameType") == "partial" if name_partial2 or name_any2: fit2 = get_nx_namefit( chk_name, @@ -849,17 +842,12 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): if get_local_name_from_xml(child) == nexus_type and ( nexus_type != "group" or get_nx_class(child) == hdf_class_name ): - name_any = ( - "nameType" in child.attrib.keys() and child.attrib["nameType"] == "any" - ) or ( + name_any = child.attrib.get("nameType") == "any" or ( nexus_type == "group" and "nameType" not in child.attrib.keys() and "name" not in child.attrib.keys() ) - name_partial = ( - "nameType" in child.attrib.keys() - and child.attrib["nameType"] == "partial" - ) + name_partial = child.attrib.get("nameType") == "partial" if name_partial or name_any: fit = get_nx_namefit( hdf_name, From 0ab1efb625eba099b6d4c7790b5b407c9c5f3e58 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:16:42 +0200 Subject: [PATCH 125/136] remove changes to manual --- .../container/ComplexContainerBeampath.png | Bin 7089 -> 0 bytes .../container/ComplexExampleContainer.png | Bin 25103 -> 0 bytes .../optical-spectroscopy-structure.rst | 199 ------------------ .../container/ComplexContainerBeampath.png | Bin 7089 -> 0 bytes .../container/ComplexExampleContainer.png | Bin 25103 -> 0 bytes .../container/ComplexContainerBeampath.png | Bin 7089 -> 0 bytes .../container/ComplexExampleContainer.png | Bin 25103 -> 0 bytes .../ellipsometry-structure.rst} | 78 +++---- .../contributed_definitions/em-structure.rst | 2 + 9 files changed, 34 insertions(+), 245 deletions(-) delete mode 100644 manual/source/classes/applications/container/ComplexContainerBeampath.png delete mode 100644 manual/source/classes/applications/container/ComplexExampleContainer.png delete mode 100644 manual/source/classes/applications/optical-spectroscopy-structure.rst delete mode 100644 manual/source/classes/base_classes/container/ComplexContainerBeampath.png delete mode 100644 manual/source/classes/base_classes/container/ComplexExampleContainer.png delete mode 100644 manual/source/classes/contributed_definitions/container/ComplexContainerBeampath.png delete mode 100644 manual/source/classes/contributed_definitions/container/ComplexExampleContainer.png rename manual/source/classes/{base_classes/optical-spectroscopy-structure.rst => contributed_definitions/ellipsometry-structure.rst} (72%) diff --git a/manual/source/classes/applications/container/ComplexContainerBeampath.png b/manual/source/classes/applications/container/ComplexContainerBeampath.png deleted file mode 100644 index 597cee834c0426bd0e60b1afbf6554a5f3b04a99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7089 zcmbVxgT!j8lW(I7CP9R3l4E<2>J5 z)AI_IpP{<#g$8#av2ACx&qHz?7*6{wc9+~vb1nw=8zsvCGZ@1U!ma35{YCTeb^go#}G;SGXdmMbu z&k(dLz+>M0rk*>Sf)`6r0rqXS-WdWA6B8%4ZJE%EdqQPyjwzkRB;aOHTl>4)o5x|d zk^nCj4;eIl%(n^F+aGp�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®w_`d`gV3yjY{|b6NDG+(F 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 dialect -of `Lark `_, which is a parsing toolkit for python. -It is easily translatable to general EBNF and other parser generator dialects. -`Here `_ is a reference implementation in Rust/Python with a -`grammar `_ -written in `lalrpop `_. - -.. code-block:: - - ?assignment: "eps" "=" kkr_expression -> eps - | "n" "=" kkr_expression -> n - - ?kkr_expression: expression - | "" "+" "1j" "*" term -> kkr_term - - ?expression: term - | expression "+" term -> add - | expression "-" term -> sub - - ?term: factor - | term "*" factor -> mul - | term "/" factor -> div - - ?factor: power - | power "**" power -> power - - - ?power: "(" expression ")" - | FUNC "(" expression ")" -> func - | "sum" "[" repeated_expression "]" -> sum_expr - | NAME -> single_param_name - | SIGNED_NUMBER -> number - | BUILTIN -> builtin - - ?repeated_expression: repeated_term - | repeated_expression "+" repeated_term -> add - | repeated_expression "-" repeated_term -> sub - - - ?repeated_term: repeated_factor - | repeated_term "*" repeated_factor -> mul - | repeated_term "/" repeated_factor -> div - - ?repeated_factor: repeated_power - | repeated_power "**" repeated_power -> power - - ?repeated_power: "(" repeated_expression ")" - | FUNC "(" repeated_expression ")" -> func - | SIGNED_NUMBER -> number - | NAME -> param_name - | BUILTIN -> builtin - - FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" - BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" - - %import common.CNAME -> NAME - %import common.SIGNED_NUMBER - %import common.WS_INLINE - - %ignore WS_INLINE - diff --git a/manual/source/classes/base_classes/container/ComplexContainerBeampath.png b/manual/source/classes/base_classes/container/ComplexContainerBeampath.png deleted file mode 100644 index 597cee834c0426bd0e60b1afbf6554a5f3b04a99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7089 zcmbVxgT!j8lW(I7CP9R3l4E<2>J5 z)AI_IpP{<#g$8#av2ACx&qHz?7*6{wc9+~vb1nw=8zsvCGZ@1U!ma35{YCTeb^go#}G;SGXdmMbu z&k(dLz+>M0rk*>Sf)`6r0rqXS-WdWA6B8%4ZJE%EdqQPyjwzkRB;aOHTl>4)o5x|d zk^nCj4;eIl%(n^F+aGp�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®w_`d`gV3yjY{|b6NDG+(F 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�Z2d70QK#NZGhGGt4!*DVv+aK@%#_`tEYYN5riu(%l4#$J*D7^Wj?wMl{e?}qh~ zY>s%K&(C)zD>TXgDhM0}O&=C2r+yy#K3pp3G_SZgw*E;r78oa{=-eoZRr2X4M1X%T zpwKhuUnefLT1P?+p*cUDbF;27;urNXIdV3GP9r`-Tm1Iz!5axr2q&_2aKHv)6R*sV zoC86Z4ZQcMBBg7vGph*EBH-3c92|H`VKT=wJcAF`QUTL~RppiMF@&7l+%|jh=q_Yl zl(4Ai%5;s*CbbwAZH2$YiG@Y5cQ^ujWfjnl_}!#bRb1n>F}OTlrVE!&9&uFk^!!4^ z;FHzbDye5^Xk#UxwXh=zxB3+h)q$p^rRmjVynV~|G~Rjyp=(MM0mu_vg>= zxp&taB#b47RTc~^Sn`WBaGB9RJ~<@SMf)iaypK+F>MgC7zsG<%r}Pqabh%S?=ZlnO z^3i`NU#PHfxzukcD5suN`yh?Xm0-C9poTO!`bZon&_&qD+`{Bx!n8>beH987Qkx%6 zRNOt{;*|T%y-h7HKpqjqJ|6|a$DY4jlDeCYdZAn2&+t{t*H<)>RWW_m=_B!yXoyoi~j%|VXyXk z04CaDLB0Woc^Km9>6tgSGvc<^MsnrPilHHjLv>{cIk;b)x=dF3^O!*;WI(#z7`=S_P(B*fsh&^#>LCqbFwo<4%S1-m5+rtCdO_86H82|ZC-J$ z^0QbYQ`^F#vI*`-R!K??acY7!^%XsR4*+eK%Hj)EVh@1o1ZacHTr3XZeXE%-cJZ^~ z?igTnbhO%Wgc-Tl^we?eguId(P0owu>bd@t3XpYIWGuOgQ3;QMy?OJ-3M_sY35mfq zuL>o*x~!TS!N0WzGR3%G{DKF@zLYPS60_t>W-)`#e=IG9h1bEVcPafZw@P#@ERv6p zy`y8B4KrpKCaWw_2M6wwSG%=MfhV6$c;?N^>W7f6Z-J zDZ9VEuFcES$qeV@;ra2!?iU#qRgB+afU-yn!0$B5%45;`0FQ+Jpvg1>NBLMTz?jA| z)(osl*JpZq(Vf!EzRs{Z#ZpRbFK?ztkBILl;4p?=3tZpa=+|-|^w7C6v9sgywH;Fs z5D@4!^2MZlIShqt{M-5$5}9@b3BTNuH88kO!XO#foj}bZFw%z41MhYee!kk11Oklz z`dh>Fa}3e4#Q&K^U0w$2y?M`4s?}sm*A~AeYh%N5dpXtdeQ1dE*Lyz0`5f+^M4G6z zHCqtGR@VAntA~)o{%h9k?(R;MI#dUbIHEcyL@Z3EPxQq*VzL9^&^mv_@!);Obxb`s0N9NAtehd-L8uV}6C42C7z=Ib>PI6$H_DA_up%NN{Fh^> z@6}Hj#FD_{!Tfx_zu5NJ|A5Ka53{$5E!*l!AM|fiPAus(m+^;m79F8dyynf(?=1rH zL1Z)>HwZHN>dAH-*ru$A9m`(xn;An7#+IpHMW`trs;7o`dodKo%*qNKlD;Z0@SS}M zHU)v8)BotDgVO^R+R17TGolBVnK8I7s(9m@l)VE3NI5x(eSbQnP-m9fpg%(h52&{L zb-y_Dz`Ik#*O}nHg zNlM)8!9#x}(&v1I@WQ?csp#Kj<(@;5C9WOi9N+_lr(szFV>MwNGCcRs0*lZ|JIVP9 zA=!WCs+T1Mg;0=m61V*fl8wT){%kq|Mn?2fwDZ(fo$MHgwK`?lUyM`_1(0Ukfxp`(RR^z-IUr-0Hi-PWow{Cu;JB3(UcuYs*w zS4*6aR_LvhhkwGVo|nTL3j)wU85OH)F@&*_VhEf6T494$f9%^o{wW)R-E2MjvGeza zFSC{4jJ5&0C5fpaM@X8+x{0vKT$s9P6dx_!2}!7${-?<)v7eVYfycvLXmo&twy8~2 zSzgxcRWV?%+mDKmCxGJOHY}zf zBEzVtsQQD4x4pr}DhW>kTOQr`_F+|Id_uJWpE4krDs1n$j^ z4~#^#*Vo<6%_-@S^o6&xx9o;ptbyqcres_rlnA$?e4mR+7B4CynP7Ygfwge$eLz}V zGHzyvt(_DOG`TG4bC_tSFx*_?tgdwH@@G^c9{#)#bZ|j__6fymYZZ3A(t^oZFRLDJ z<|7pqNdZ|D!)U?g&d%b-{%;MSR7p(6^ymT)h)QkekSh-{N&J1hTjn*>H)-(^OFEn3 zfYf#FlAvDXSZH;}`L!fzojkUZ-u6h1~<|ldl38{cs(Tz z^yf0hlCvn;jF)zoekSZnWBb{^yuUDabL6)Zuf3|k>+R2D zMvZ^Gh-lu&y-J9rKP7y=AV`reWqLvN9_W;5A}8f@GEIFJ>MP(|aY1j>ljymVg<{x4 zjTFww#AKCVyAHqe?wr(PU0Yvgn<*~*(cO)Zkf1efbUo?C5fXKog#!N9hvflQ_Ei@1S=cn*o&~0NkFVWeV!*?(Mf@_YaIXRWBoSN8N{9R{?_E)?I0Pl)- zSk3-lc6VCwGx2l6)(wj|_KY$|AtH*hpC?w_!mj9Eym)c1V@Ac9UMldOv9Ym=hDLYW znZ#o0TO2BlDK1H~Tb&O}SYUmu{fUFUp;BFPRH*QlWfB*sA(cD;7K8SsKm<0T%Jh2< zl25-sW)G5-%1!FyUy%-yRq84#LT$7pDM1{kASaKA|J*&W{>_j1Bet3!Q3ERr3${`r zxt8<=t9tQd$(x@834HBwAge03Xrmn&8TmB#UY;zXJtTXHv-mT3HX4_wdxXvk*q_u~ zB^KOt1>j_xQ&o(Mfjf`PTK&m~q|UNl_(H6f+C%*J+s^o{zeB+URn(uW&@u3)lKb|J z;p;&>2N*w%=;1HNUykTZO0!8|{kbxXs;a8Jy}g~u@F#jT#yUC?U%fU8K$QTFg)4oE z%_J{+UxjhaAyD}a+Cs@wwyCv08}-sKhMprLBO|M=zF~n3htt&!q@|o7$!ghePmm7z z=+^r^QYn-8Z8ux1OeYQ)J;h$WBE@i|1QQu8Z9J*;IbdgJ7r&Ia))|34-QYs^?AbGZ z=Sd!<%U1ubM*O7q$3I697l{b1@r}c zb#YGrIZ^e>4+;7>IyR=G?@1{o-#w>byhE2awIfv-SjnB5>qWm1bS$f`p7=skW1XFT zab*!&nTEAa*pl^45h`few>x}ywmtEbT}whUI9L)~CN=kUf=-|A2g^ng;RDWaM3N{S zftMEMw&v9*0uNO={Kbrmkq%3Z5NXTI?3koyUB@P}H98^f}=x3TKl?q2}O2mR_|A|nL zG%`hFHXWWohRc4KLB~t}UJ|dtfA+lL(mfBsorQsVS4B-NvMQG`*|mrnY;qfg*hFN{ zAVt)=7mvOnW!V#zSZ;&1_0}9V3d%PhmV*IWUO1bT7+5{`@uWt=L$Aen^UF!p7wjLOt42~RsEI<~v438pG3D_0z4+^UFEz|`) zvuD@Lii^O;!@>~8S9gxNMoiLx4hhjF6<`Q53Q7mdctdkR2MJQ(Hb3194@9I}(Z6jDB zJ-!i-Y^d~bBcC&hzN{R&7{>TGfa3hb5Hl;n^pGGf31?*`JccmBb>U5|n<%zhE5z0o zFs#D*K1$Z!-dX3=Ia(A>%e}X|NL+4)pCwH^KJlswMT6a+iTAMxVxlBhGDD=E4w!Xl zR`oTwY|rFK!#R0fgRZJNaIvu794Qm5yb=~B`#Y=?lD|D9mB+$H zGGJ}T z>oxbA*&q6uHWjLhk7x@@K%-tEY!@WtNf=nyYKLH|PiyahN^|b2kcg7p`!3!)O1;1M zD8B@WA@E4Zz66RO5QvrA8XNqw&$>ONTwlKIRz-bacHh*#f`TAOsjnZcp1tkwDX9tt zZ{qN8LFksZFmv_H?%aH{-5m}-3H#ct$VIS<=6#fu9l;H<{q^2lw`hBNw4T9Fhg>pw z-#_9?|jjKcL2)~hIOYm38(_cRw(@DuF$S@N9u3V*z!Az)-2&b_hHdUq^ z3xAG=x_$BS|6XF^xpYf4D&8f*`ZGCZZ*GH5cAFtri0_{bBW7wN&i!X;U;vBKFoUaB z6dC4ff2%rVim5w%$osJCH6|G^oQf{XGA&-h3Vz9;(IbvVh*_!@a$6 zyTloD+(iBw#EpzJ3i{pq)k`)&d?7g=D>&G!kx|lUUOLEtfpK)Sl+m;S2)lf}(;y}2HdDyC+iQAu1*gEi}#v~#)tauKr>f77x zt6>sJhdB3RN6g7o#Nn!O5c2@$o2<(txGSh4PEM)$;^+L99-&Aj;AE5vj1>sQN8#5B zF>QemN{)ubKP~$|T#CZT>1e}^Yd5Ps9XV5SNamaJ%QYO<)?X+s!HDn+>w zgkDCoQRbQqMq)6TbMKLEM=HzKk<4|35{?o}k|!F4XAzn)`Jp=2rzD#7Y<@KZ9_6xr z9pG^flGkOg=6S@9K%*$XI8h=F4-3p?WM;QM;o1v@ECrnoCksU7yJVMox*z0C<2SkI zpI;8id|nc0`Y*%L>%eNNE3z$!^6!M<_Bk7b8p6h(>7>O`A0 z<+Zv*G%oobe{*ED{dM1NZ?PGvV#``j4cAc7NNPgGz!Dkv{TaS@;b(}yo^=0#PGFJz zZnL536YPaW4f$FI*7aZ8k+WfKpLp58WA|%}Q@wZTZb|N&MlBd(NM`?fsxmB0elg5a zyhTfzYtn^Y>O}{*Xk9rgF>z5nn_pVy(}ezLUu)}VJ-yP^B{+!VuV+ohkm{K0X1(jcKbDH?b&>a_(vxDPrweFG!4ZAQaM@IzzoNjj}rA zDd{kJNtN8Ib6~C!yRUCI`0r^kQiz=V_+lWl4sGU=mKMH|Lz&xg`au%S7JWZM-(ZyC zY#>w0b+bZ4{R69Ou8h`8GW{N}ZKwn{hbDlMWY(nFn;@L7Cww3hUttM6+E&%TSqy$H zO&vQlZoeprsc76h-5UFw_||P67JNj!psA8~0(<040j;#8ZhWd1PAZ)@XY#1pN)8>I z64k46S?F;kD#aHQ)0rptsTt&LEW5MFr}iV=DwtlH#MuJc^?~}{NW{(*GKiKKp`5JJSn=tL zWw`ym#rh3c5D}+>zU7-!QKX}9Q^r3wOy16eEhKnz|J>v1gl6sbZ`IcmKef_PdcMtKNSG<9Xx4}|=|E$9hEynSWZfFpV5_G*B%drKT zf{p37pZB$gbas&@46(47YZbb@8iCPEJw!2f+^TU{;OoX*ofcVd4Ci}K&W{udOOZ=t z#S%e0z1B4hVGwq$;tgot*W3B8oi}G=XMrnFctcBY#-FJdPMc3$vx24TVrm__`JV{r zWa$;L>gx-iP}rwlo)7P^BtBUGJ-T&NRCFAm0y}ZW$gYQY;R;z9O3Hq_ZqLg}D}5gC-$dChBeP#=_&Wpc z6)^{U=SlU}^T*LAGHTrz*Ap~tFkB5b#KBBH*19n!!Q|!N93nX5?j!e>NF|R`ZpIhF zfmx@Ej=QHU&3KG@J$PDno7xgmx2veFAUE;jl8Mo>b>~UIVQ`vsRSAk>_BorqYgesWGUr@`D=W&OA`>A)AQ05o^3v}i5Lh$_1g0Db0lX8X^R58= zdf_PfS`7(&c_EpEf#a8U@*f-_5PbCK9~ip&QWWqep_7c3ld7$mldF+~Da6&)mG!fY zrK7QtohhrW!>5!(VIl~G0`gi~Ld`98f5FvDO??sJ_>&oD^1wR}x|gq!KA*>kW5EVw zuUbm{adpZ^)|#v<)Y9k-VZzhDP{*;_)>cuIo~8+KLbAq6P{#TvKm7Nd=TnVILXyxI zl%HESKB7158}lhreFI-Shi*ud+gI%T>QLF(*pdb}OAZlKLK#?DW!>D|G+hJ3hT`Qk zUH!BpqoSlOEG)n~d3pyk6^H@?0(uLmRDw!Sw1tuBKgK6BpE8`C`NC!=5?;L}APMt; zaR+}E78d4#hJZ*#MU@cM>JN@+jO{4EQ73XtfufD`t#80g8K5T(wmmSFzPQ|niIO#% zUOgN34?|k1wVv~&`)qK;1#&U|SUpzI;H)JFc+BQ?Po4OrOMFz>WFf8o z9?c@2ej~~&m*e?<85w(3)Uwse+1)OJ5mUdcTO9zA|L5vGqJP89V4Q zLZPB^_-L2eM9r>zZP#fA*Ywo1dUUg(N4JSGKmb1D~NPY=dncQ+j0(tM>i z71eHtTc`hR$-q0qBmFFo^&dP6g{;}xe&oJ58oC&mDk$LbTt#kZ%08?1cO#%9_&ha! z=6r>TS=o|>yj!oBigB55F8cCxgpz^-)9q%XWDg%xg|BN_+0eZBF}=T!_U223F&dv=VeyWm~`2Y7bj>l_ksTBB;}*4 z>ovbvbPPNMuVab10~F*RHt0m-_7C7u{h#Nam|r;$`Vz9_J>_!8qVvNhmTZCJc^C9eHBn(jF{TXU6 z?l($^k2k|5du(8~I>BrOzJGatj(yyL-BO_5hBy24PUxp~61hoX@4Ez(1+<<+#b!p43p z8BdoPDYKhnsF1fTi;HMzYZKAFOY%b{=1pDjr_WytMKR6p?dJ8bS?k)$j!QJG(4eesX z6PgCmwT@dZ*IPU0OI~NFi|$)#Xivgd3$Em>_50=ErSy0;2miqUYVn7Zd;qA)nY?!`;cw*oY5aGy9sqo=jkm9DvOR~@huRbmO4pY=SL?N zwlDEmw1Z?K@tmh`_-q%W@>PGkOy7iu{a7RU|6maK?^q;UR|f|S^2I<3A38CgjnzfX zf=y_ziKMr;NV?DMXXX#(KT$lUf}Z179x*)wgM_|*`W)}X#6;RS@f5$B#Q(fyCqIW^ z5HS5JEvMQ({`u=MzhXxrBt*Qkv!gdsIQgGoS_f0Cv3Dw9V6ddPAMQy~@P8o84&)RH zJ@4z52KTcv`?W5O*tr82g6J;R?Rfs@$ewMJ`Sa%scXxNag=k*;ynz1$@jtfY5CR+y zjOA2GaOcO*7d7oG;w~<{|Hj7ZGc`d}2mZ$yPP=$=!?CHUDQz12>VIba##{F9%&VUPR2&MNw#8UcrRPQcZL zn4j+>uW%t_Q9vFL@KtZ2QV~QJX=(4-d{xxvo65?fel%`8Zh=$DKA0>fjtWD<9p7zg zEb)8Z8@H(wg>V0SR>kGyvW&~HbrAJA>4aeoY;W=39op5e{!a+-9@4SJHM+YLq@gX~ z_@v1H@85m=kKKMd3Yh0OaY4kxqhYn69a&VQ9TY@wzvLaCeX!`s_R`2G9SQY7=L~xm z?my?5XZY&Ju;>I$pdq4dr>PUM)wE2R+7a-+n+q4&*L&U$d2*gN8(*etE70QO8Ff9a zk>0<*k4spMjHhm_ud{5#dcKVFTeAvMA=gPtt_nP&Xp*Z%CZ7w#i2~^t@a`0}U4>sf zr}>@@My2|spG|$bp_Yh{kZ1Z&4w_j7`ysnk(j>T}$PZ0CLG1rrj95w39XeMv(Kb8` zr~3Prnr8z2^JgCdvBlqo^|GJXpDz?@+0-2P`#02ek&t!va3gVT`JlL^%xE#;(lv9a z`+25GKX%6mS}p2E4-62QnDHJQu{-5~`^djO*&AT}CtwK7DI3lH>A@YWhW~qp_U%zo z`L~v{Oa30L&l^tAGC0`G#B`#~%yBt4MN(#tSqBd#`CZ=c%u&1ftctH*$1p`aJfto@ z&nH``x>S)pJ=mg_mj}gS(+xoUI;1Q6m+e-9AJb+!$!rg1E6cQ)i^*L1NqUBcWIa6U zex8x|ZW1OTBhS`*Dn8rJc<#-aWBfODxLVz$oMW*kY$r3z&uBt_@rx&&dEWlFD|$ZB zTUY%X?uQRNBYOumkGB}3yh_5DsG)F4+`afdK3;p&yLh{eL$JmfQqYMpE^umQ&lKc}o?D z5U>_18IE(-a%HA(c_0*wZ-R+!kT%NT{*!`?M{*w?DeGBx4kSxtTOT%yAz#gpq37o} z%`f>65e33kzE@R+%NgB1y(uVQ{8XQifR%Wl#)u0G3p?BB>#bmI%>qRT?B8NyVoE!h z_ZAZt5y2$r=^t!VP>9C$y;s>IahYz?n_i+6)j#0m*R>D6UUNFM;zh(k{-Eiaqsq>& z%oK^w*0noPIA>LD(u)NmOUK3;m)Sr|hzpUyUjO6cRkQI#fx2~-=k-eH$#FY+y_cwn z2x$tRtxb2jimTm0WoVgw4#uXpH*S*P1o`LBZI5W&HQqNH z5^hfqKT8fj{sz;Sn7iQ3w2s^U9sEdX1l`W5Y;)P>w)ym zTNYMJs)4jQbWL5%pugN=Q1YP%(xJq57%gTrH;)Jd5dtwEzIU|sXFggr z(!igi(JX|4xbSH*4r{E{;)seu(bi}6Y?(v(XXemt4+ovr0_nkyWZ-1D{Zl{viL z?0&xEi=5GzgE>oJJ7BXDJ@5GfMy8J+8|?O{;j_DSJ&UgyksOAts*Im}L>wHVMs}c| zM5B5Jd6sXs*6fzNi>r^n_xj-*L`jMJAtoen%fET=+W#xRphunnjWnR$B3Pj`v`xVq zDZl8`_m7N$frP*%)I~Ct@Gq0NC>L&kU76@9l!{n50h0{Pc0@ltQveTFeb)32;rysn z@=XMJTf2x}x+=4>6JJ43uIP``(@av)`-Y)Ue949kY={tgDamIqBiR4Pm^PK)sB67< zRbsiMzRe!EJm5gvlQ=|K*%DRXR#x)vFBzbxDb{$5xZzT=4TnV&%Z2$gBBH6SC4c%j ztSc}=K`DV+S?3ycmY1EKT3uLeC2+K?Ty2a<^68C{CnsGvw} zgqWD=^o&2~JqDurB93mv+eQN3yn5_v^6`eZsoN<#YYGj8!XdaBbw!EisjaT`kEw>x zrHAdrHM#ISeIB#BpZNp>p-cBfTXCI-3632W$T*r-RT8lEj3w;{E@&LnY)~-Fwpj#K zyap-?ypKTms0|_=N1d{UnS_hW*aTdfqE@Bdea*{n-x#tTk!cmrJ5M+4hujhE?JelP zd0$yXKYe8wfs#Snv!u-FS!5n_VyTQa`WywPdhrdUFLD)z?y~siK`9~a#9B~L#P2c? zq>|Ghlaay0L=cGZIqt`9$|g!s`&as#L@-_tp3Cdr^Tz&1Zql&=noZ=nNxEs zbew(I#CyS^WV=f$3kUI3_$-o#0q_t%RokZU5Y^upPq%x@7m1h7!ayxGy_DtaiyK3pK{5MSHP;e``f}&!@^S6bfvVUuxnfjPS4Ba&~A=A)Wu$#y2{XoQ~yZyM@aaa-T z^yvqmEg7%P{PeDU{la0@k5c+%=KucbPnr_OuYRp0u9Ukk8a zM-c`Zi9NiC<@)9ac17Os*q${#J-gAi^2x>F&d%fUX@U?F=Vj*uDH=KNau23dVIAUH z_uXA`1aSm`2f9HB!KG~3-OafJfK=f&_0$1{lPe{J^m0F6&aMorvvakO^stVJ z#B~98vA1#G3l+75iB{jC*9UAamqm2s_f!n8qvNSNx7;9YWpK_MwInN!n-u5Yb(BvY zuIQic9mj3v5FCxN%pHR@P@2!3Ug&#qwAnP`l2P5wfzYdx;c&Ge*zn{tW@gyh`eq=N zp~$67oAmg2d!gc_SOc-V;(|qknftNc&WI-6*T-+${^|Y`GY&EZ!|T8fX`X<9q2hZ1 zXVls^!Eu(QGCh@3un=ZbQ()b}m32gDg}7w?{>ljOtz67d&R=&&EFcD5FuDlYtp>gP z^JlgFAobUcUW@F*^s!HT8P*%DP)WP_e9gJ#y}aNZ|LsM>(; zs@#|WdWnaNOF1Glb|FI|UAD`~t^pl=@5RY2~Z}&w5Kh5F1E4t;aq(r#7Hc_)* zF8%_s-pAdboThKXas2MtxHoPu@`ifErR+JZDl3)UJf#SUkdNZ2SHw(_8|0!ByhIT~ z6~87Xh8{IPEm{+&42Co`2p92J=udw0JZi*`aGXE=kw@KdcUV8Ncfp#mRPiacA}u!M zv>H@61QYu*McHku4#Fb58uU!5-#0_Y)x@Gm=NzwG>6t1FuMX?X3h{z`BO?a*oy=3W zP~wVGT{_gi8M!c5&#=#9Z*k4TOsZoshU888hF%Iu6@;IT&Wcaym`)d>=Nd3E^O ziaq>=zWq+(yf|fnEB{XIIZ1S=bt6E6o-a?pVNEFOMtS4wBelmU}{rukC-1=+%M|t zy5tFclG@v^hk(w6LZaY;0o&~)8RBS)5n?5XZ)l|rt^L>GsXI z0?dYj+NSU)nxA4q60m@`S!dRQ4EM;t(DSM7KjY$e^6y!fhbD8br^YPYuWVi(KvjhP z-C8a@S`qJ=DBtl*XUsij5J9@xt+kQ9v!+cRT)Eo0UKq}luU#Lv=f2AD_a_@#c@fx( zP+WCkABbql?q+wSvm%jJy55ei0)ix@g-e*^Z(6o`KQ+QrC(~$bIdYii2j6g`b;B<43G;rQVb`dh7~OOKOg=H{$6Hx6IDZyAcz)$?X+;-7Do z*tzQWoKy6^nFk)0?QLY)XVI;x)} zJVV|dQoCroQn#m#uR^t3V&&{SG`AZRR3W;^rJILg;aKta2Y8Hm?aBfICJmg`p7>k} z44j|RZz9+V3X74T`}c{MUwUImg?6aSOblE@#}-w}qCnaF^9V)s_KWUI6V92H z6-w*{+m&m3Y+9woy@sO|N-5n`eAZeTjM34O>V`v>U%BDBDl&3XxoT}je=_&ahB4h{ zOcP>@m#Wbb($FBwTsEowF2H|#$Mu?YXZV7e&hEO53?3d^I+PTTEvD_?FH%htd4pF{ zkF2j;9xz@mixz3~V3amL(t+Yu*u-d{m4&QJWz5Ff>$b!!he7 z@MeR^{?*mj($c@)hai&gv)z)YDE*qS&=cL-+he*B=6JeB1S5dmcOhw7K^R|jCBJ=o zI2yV^QFIZCs;$ktz0f4_Jrv*uxHbf-`N73J6wTQk)TP;?KeO8c+Cx!mwzI{5=H61V zC`>O&{IbaS<5M_8UO(lz`gI8Iw-a*eKle<2Isbx>0-|}0p_9$dZt|(-t!Ymsft{(b zJm?Q7Y)#j|rRe=*eW2Wpy#M`9VjGn&bH8GExok%Hde*WmRWy2?>+U^w-`(9({MB+G z3)vYVAKD3%W}S#wAe;*NrwT#kvbiwoWDk;F?&WJAYW=BK60GGjqas)5?QOyFTRdW| zdYv78syl8gr@2}1&B{Vl304FmW6;Rg2${}yNHJ9_|2(7lYihB?KZg#dQS7216zib` zXOKr|7Q;f^Iy?T_nAp}z3!dku#MM~f;@FgU0oF)bWU`9Q^0p*Imluf*33P;FLW^5qfw zMikkK6p7R)X|5QYp1ctnMShyPspeb?@3HRxjbU=QvNp)Yes{6}Q%+WpI}kB%jX?8m zghD_)QsT2Vc-7Lcqs?D7Ly}iqNl77oZ)$k5nloLNh2>ZFl>=1O9L8SH$>;-4LxU34 z1MkU!XL#Nj{JWG8zt3Z-GFcEqD;HiI3!bm7t#R&E=~Lr);665++bTJZZ+GQxS?dT)ki5#8Nobsb()G(Bi|VF7opQgb$BNAoH_ zJ}%Q=w*3d9w1`FphxkQ{|CTf3^M#kUGMG*lJzqV8RIgtLo}JY2vu$6j`mQiF{?JEa zHbX2zMa%QeBn@zLcUsPZXd~u1N+NKOLx{g=02hvFc{&HuHyl?hNPvSd*`y>=O1Ecqy?6;HI zmYjVIp=mdf-5|D6jm?Lo?VCm~(Kf$4Wv`o!LIQr}1Bcj`RJ(J`8ynBLc0 zqD514`%v1&bd7zDc~&-XLhZ%XA+6nVFpY}{wYs!*O95G3A-{ib2puu0a|Y4nu|Haf zNuz4i?uY)?#0v;Sq!gIBxPL*lE3)fyD7~R1)~c%&7LrY+#mJ~V;Ar>j&-eD;jeeCn zkIFN9Q#|r?6Cm)1*4hRfnN{;k6`&}4J9@UF}Hh#bglo3a7d7+K{ zF)nuL5x(hT3iDaV1nYC@vK+T&6uIPJ%`vT=&q;VG>4eDYaH&AKVi6xDS#dFp3q1R?VKN0#KEW~hhW*O z4FA>qp+LfyZ@yHcuD{dA@MPrsI|3^bx#cQLJ!&27CeSgVX18f>8`Y!n)-)7 z9?s$0U$AMfKeoL%A*}`VB+j>Q#nn$xsM>1PTt{M%^_)he^_+!FM*YL3-6*n4W2LW- z=&7W)>7H$YYvzLKM&rEo8yvD9NE9!aG{3jB=j4kWEQlE*@D>#X%;#(fG{WJ^H!FB~ z`yTSbIaIy;0>iS&WOwhztWiY2ANS~euEIb>R3a{rT}JjhE%vSr?z4F#Di?*WNRLGS zD_ITxICSa~X(TiWbV5I7wKek!mqld?1Pf{L;7AN4+#gN0!SV=pEW9>F!P>=Lmj{*8 zO^tYe{^&o$)}uaFvue=~cY87!DPm%6G9R|t?@wJ=geQu9b3+x*WY5{zM$aBjUEslX z9|%dNXNEfZh|SjfcE_d|vJXg`X5sB={%xQUw9=k+o3777+xz}4z1Ed4hQ$BO(Y51h z$|OBd6{4~B_3VVetrm*rsS@f;Z+%fi!ud6|wvS>{HfW71Oi6yA(;R|*JZ=12TUgXs zHnSf;ovn$!y+FM)dw9WKt|oFBBT$LF5LS6&H`#MB#)*(b)cx;^5F%o~xp>W~^9S>z zM^aHMaqoqLyizy~wg=0nT>#K3kzIsj<(~8@2>Z!gZxXkdGuvD}*4_$ug3Xv{>lG`i z?f2uyr1w!+Df!(L$HUz+9C~8witg=IFWoP##=46=d7TH(eJDtiEPf`AJ3WMUbZxpT@!m~ZEM z;unukEgsuykQP>T~owx~fV!b^JNW%yzAE|Uy=)0eW9*8`B z<^x%Ds#+>OM4w#V-!9m9lWH{zV)s|wBgZz6b6lzQV{%E}D->jp1oTO+u&sV#t0QU; zg|4!+Sp@^+?$M$(VMxS^5 zY8Z}VPr4Uu7akHHXO{72Z(UWkGZ6PRR=jTN&rTlOuKoZxdLYfyvHq&`=HK+@>gqTW zDlWP9EFe%cEcYspNKY<|p9FJ#;SdWjvHtly^!IaRH#A&)Yp%NeJw^zkdF-}*^yXkn zXf!cjmB+kIb-OutHX#3it<$7?>@rkueQsS5?~D~&Jx?^qrlp44T>UtWiqO;8kO@T% zzUqlT&ftUx*)Cdai}>r`=KzJOzbPE!(X?$ktns9_`&E58tj=#oN8g9G6ekG@W%p^| zYiQ_LqL|C^6(?KmF3dVlc)UQ0cuz(D<{JJRlhg4Py49Iu#_*M9)`$e0EsglB)d~f@ zPU8(<9dcF;au$0_2uohqBbOtwg;8fHe=xc|@)R|6Ds#tTLWw^*tp=yXyx~~#WeD^{ z=6yn$WZS~~!h+8Q-8hxh^7VSOXqKtKThcHfGm>BelkqC!XH8G07Ahuy@cQ$AU6rFUC>*&%v? zb1QaDF*`e#{)IaH$EdjfTg;%h!%zjamH_GzDMS&3EK`DQbhaRB^3F2DJq;0`yW*jn z`I9wl4AKQbr{qDGq(QXn+Xw?%8Y&C)N}cMDOXoXf^$es7sSAeUk4sN6x88T`+iS54 zA&7u6;tR->M!t`y;k z&S~UOfAsS;!Fey;aYXp%i6JIlyobk2zVo}eCA(X(r`Gs6n?Qxq?vqa$GS{T8Efof0 zqX5;wNUJ7d{(yz->+8!;(gH@X)umzF^_OJvnL<5kOnf0uuRuz67(TCS6dS=|+|ez* zxBC~;)X|WK9VUM&2@)sFa7JmG{5XD1znI3xrpy@tc8PzK?L ze+1V6Q()Cas&Dl>WowpRZ@h}A+PLJGK9Hw{3qhOsxY&SH^nnX$XJ_@TRDT~c0jCM# z>gwZj6j4z#2~qrnp{L6FMF8RzS;N6N{{2Jz#b=&L7N*WUzO)uV&=o8B$ePB(qn&g@ zrN`eUqo5cu(nBE9Ec(n0+}sgKV&tG$hJo-960**nM8K)w+wqgQt;d_2m`xgvDXgjlf{qbgvQ`Y)No@ax{p!dt{0Lu)$< zt4!qET|^aS!>&;B?}q2*_F;`_}& z!ly?8%xGAQ%__l^ckYk3C+Rc89Ip}>^kT{=v%DvuMgA2+)cbl=RJ;l}{Gpdl2+&A( zX2sOFwILzrnw?zbB0VAb^O}GE5MI2XU)kC55x~QARzkBJ!}>IQd<0c$h|0}OJLB${wn6#oF_w;K!>iw(sgHj&7 z?0cPQWtxt6Z8@<`2jyDmkb!h>B;R|=uLFv2-e=^$&1zk4CHncRmQ~`d^g{Qh9t*%F%shk7>e6!|=2irsw`A zNoS|A-Q9s41oCj}zIrjW#^LGGxH>_`P zF|gPm@A#6$;5uY_SU0UqA}b0Z4mKx#qb7VPR8W)*&cG8@4xbHy1a16iG5VCP$sCtN zvGK;N(3pC282_@+F0j=<4<9A=sv|r0*7%7HpVGYrUaNfF+r&f-kl~Zo?v`JAS?f~r zas1<5UdToq*-X=O55=6%DbNq8WNw$i)-k{G^M|BMxz{S56GV3UM26FKoVxyf0M(B`hqW$p#;KOk%{^d?Y|PM7M0e#ZeGld`kJHqk+1By z$D0#_(Bpna1#nt%n-a`=mkEKyAI*0*A0x9r4C3Pbz$DDKu(TmiDP3RL3e7_#Ge4QW zo}WJx+HxmVkZx3TC`VZG75m%SL=3bBp|Wc>*V)EP$sjR*t{%6%0b4zY1R_B309P{^1j~K@PNm}_Mzm10xVT=i5R{wj+t5B@; z-9y#F)^@3opcj>M58@D`@Es6Tx1A8~A3ZB80yh7ChIz(DwmE()@`x9HYafnfD;&Q7 z^n;V*W~SA_EbrWp(=+?iPJERrGt>l)QrVWjpKa#O=u*RGqu<%c{G&lhpyi1ktD9xo z`l{&vJNE^Jz(l~h8jA3QC}ha`rMai)X>aZ?OQ5eh{aJQUTR+&0$0i!V*32yDRzrt{ ztuyqy=KeHuXqz{F%s?t|z8_`x+AS|TCo3W%pty-_^9vmaoPM=s7!X5N#B+&_qh(&PI-e^iw0Di!?s-9+zAXg1b84Z=$j)K>vHGi=Ee^(97y6AnzJd^f-$LV;KWBYd^DJwfa8a5pR&P@ zR0OmeJVRIaZqEps$J7|m^#SJ6ZZh|JHPT~iWC&Q8vjFDVwhA=@^cYK$@It%l)?>@M zbb7i%RG-Tn1K^H9zlsJ-i4j6$%y{AW<{@9dyErR>-j7f?J1&8@QH8I*gT-=P%$EY% zn)mO$I6fyB#HL5_TYTlyD6uNY{LDTbpJM5!_^Bi4<*MZ|pmOEqr_q#@j0(>;J-vVa zye=WHRsTixYzCs8?J{H)6g{z|lrb zE$dcqMV;7h_w=CB(~DX1zR1A9-?kZ-RaN-x9do)HDEqU4?+!y!%2Qh~PG+tg1e||g zCIx_6mG7IMBIEW-zIYWqE=z!P17c1n{ut4km9xHyoMm*h_@BXz-CvpQsx2qH9lB8) z`;D0S(}e0-xYd(qf7p1k68b7hY{{G9U@_Z3OsV1YjjFpfh~Evul+rYG^-Z(vKKC|i z8rm4ddlT8Lozs6r34|su?2w&{M|5l?M)yi{cB_}-u3F&2JRjYAgcpXr^Ox%J5ld?k zfJ7m#7sKJ8l68)g|8I2&g5k!S6}F#U%}K(-kiyEh^)ll*+~{b=-BtYz#7we_&WY^J z**~SHV0;UU+Bld9}?N!X~Lgn4Kw9RZ#^!!|0szBmseUE33w9)mo`O295qReeACQcT5zqN zO>7$-@q6Gh%k=2S`&3y4W-t)I0srw@=?;$mgj{|B0lD2aweSQy$k+W4(RMp^@dp?;$~aOHRIzXnXDkPWNuA=Eqm~CBpMwT*r%^dUI^q z>A5EnQpy;1Xk6{XQ|g-VIdy`#o|of7p?u}#7G=hAq&78_f5+~|NP9L~{(~#DcrQey z*dWV%%%1%q;RwnrNSk8e%*?80Y+oPq@o^j_dz|g-gHGQ*oG8$IRabu~InfpEw}4g( z11CLak&s|0=mG`sNzAlq|18PmvTJ_h%^lp^?~q7*l7AMstFjgC5Vw z4g2vx-;>d{Z3mL!y1d~eb7nMtt>Z7XzSOtWV-Kr25Y|EGud3%a&x};s%KY`e6`;BhXMEKeT>Ysec z|2K6KTF$83^J&yo<(QAv7XGpS1+cti4hTUeNE49 zpUw7O^}%i{Z6z#XH$`R+gw7=X(TCHi&ttHL6)#(v>AJ&;n2j>fgC!9HDHYC>faVZ* z< z*$rxPvO=}DmtP*eQGV{mz#}>$8d5)x*rQfn;=f>!%j&ng-w2(mfqA-}hpYm)dY-eB2xWN}H>B zZBo7b<#0MfMtbo!9b2GDRzW|RdNts>06*^-TUM8CAN(%_wdMXs+$hV=w-uH`gmimK z={_~BV@lH>C}lfdB_f&rBqk!6t}H}r4~?9P;CJZo)6{1G6uO-$m1xtIQr*|KIUWDe zoJJ0hzk9PdQX%Gl-0Xi=@OJVorG`8VnD-2&<;VmE®w_`d`gV3yjY{|b6NDG+(F z+Dfp*;kmaQ( zgpwxhnx_R<$?z+(zcBOG)xj(O-onKv&u}*Y!5QxL?cP`t?_fsj3Ui*C1C%hkGmf%^ z$sYlM5zvGrsp|LslzMZq9neG{PhO9SWE6y`=nDqj z1!%~VaeKI+f{24Yh5YfiTrykv1_s2|_N4heH8s^wYtsen8*a~)!^|IO3%vpGm`S1{nVrYa5Y=)!`dfCh0Rn_j zm(8`DmU7cSLw9JQWpjCopTxDauI}8wxVyF3n_>Ml8_BFdMt#r0e~v37)8hNY#B3_$ zfiq(6_mhS~fUxGc4Uesct@)l)-)3G`xg!LX*ly=n;_61Ce%o{7)XTJ^xpdD%0pY88 zN1%RdaOcWZOpDk`_r^Qh929y|N=iX#IE}EoixKkU;>s85%vWuxvKDu*Wq)CRHfT+r zGsd%^_-41J$(cGl94Iq+59(F4XZ=7A0hE}QjKol{eFad^uSSB(p%@Qe|YfeXzUdkFO8W_f}7`qNU|fp^x<*l}Vf9 z+x02ZF!KF&Fc*A>P3K}`N6!dbQY%|?u*bB|Ug&g&f1a-@{yN-FhZW!F`(0)kyOOSB z^qwFm@QUH4{V{Onv#wIpE&b^DdN^PK5W*Kt=Ch=>ysY-QhX2llv}W;fB?rB-yu0EP z!NZ`?HO(u*do2H}?Vn1ryc+5MDIF%=Eqm|wt=`ej?-WTXO#&|2>5S}b*t}wRpL@)j z(>GHG35bU|Ug1ztpIgzuFOQy>l zZ<11~->-5khf1P!O3D!^VSpbBTM(z(Eg3Tut#Kydl|mLJ6|7d}8?C3syj)qg74JK1 zqvgZ=-$6!^ufNp&tRL@uyoS4;YObq7cMxFrU zy=`(ee)9{8O^Y-aD0ZEByyvqX2J_rCP`)Xl7=tPHpceiW#~_Mi2NgY5RGB@$`p=xo z`J@hit(U+6ol>0*-51L12quiX^RW>$^2N>1gd`q?-giNn5G1yO6h63@FIncUZ(wYj z7@}UW8L%>c(y1vk?KRjX-rWT%GF%^oy4kmEFwIY_1A6?<$ONJ!0QNE5Rij{6){+33 zr$QDC2C|Hdoa=`~Pa*)daLWfu1nRPl>NGdOUM;chr({kr0@elnxsL`&wEuEHk*SVl zmI8e>KffhjfzQpagDx~gMc+FXMm{U?)7eU-&m^o){;gTn7ESH5|9%xqNjVOSGU+*JN?!^@FQXL%yo@TU$)hH`Q zs~s^1%AqYXb{luqdc%Pp&49gR9VTAk=PqFSe)*uNT8qN@>`>y z!!$xH_uUC11dA9x~48ZFS z`0DB)!=iXv2~`1*Gp=>N3>n~XA=J4u7)Bd1ePBJn+b-COB zOAF9)ePUf*n*X_O@THk|H`sJ*F7-P*Ee}^Hnt63_l|*j$_C{nwCu@>%^eniSe+YP? zVNv_LWS0!c!9|17zndPaV9~`=(IH4^8iIv7xw*)=cmhh?(Uu*gdWqHR$=mxmU+WEDh<=CA(S=MtUcBI}$q(dspoKg__2F0wzUgL@8?t=7 zV&8x~8uHxV_^-y)iwhKvpify|Ny+w%Wby~mv%DL~#P&*fr2@aa3t5j9>zWKh0(w*M z0cb3<0bS0_{V)9N*Mb%h^RGM~E^=$xfhrUOd#v&yi;Rt5%WElG?5RlVeS(`g5V;s# z9SR=S!_*XYpg@|MN?bo!52-0bx|3fI!KnUDpV-n233?7ayH|(7E6Wmz2iIt$Q`U0` z4Hw^mV?#{$ZL++RN~0F4|17yu^r7t=Vz$d<%~42wBVW^XHWYB%5b*yd7QK&zPet9%Octy%~{j4aaLGWQ&Ab33uzBsp*D@t z;ff|UalgK+w`yM=(cIX8;W9&7n}e{MgeeOocrEV#+^YpCrV8YQVoCY_GEp`1ki--x){S~laCA$%ViX;?S7!J_$ zZDQ9+65(mndK-T12*LRn(zb8GZIUZK4(05V#b)J47ohds?SNMv&TO6y_p>{i@dgBxvwK}DGV3NqJ_`|hzicY*f4-toWyBP=#DhG`^_1(( zqJOUK(_*6yrn4~jA_53Gx4#NZ+#tFbL^T&;YTEW-)E>lh*XZ28fkq_<&+Uc+rxKJ| zau}ud?OPj=B1q9AZJHsfWgl8y?qf8Z$O@Ycqe+1J#kSEInQy^~V03g&S=n%R_t3dE z?B*=3+VQZ7*c|{W{X1i}#`Omz8CfPMe>Y#vg5&nY>nl zTYMj>zosAhn{X0B{%-kVyaGuHB5i zmo!D14NAFtI2+ zxFf<(WH5s2{ny15IOxE`BS8(j5di{x$m#u1@>(O;QR7vxV^C-{?DsU+Th&s15f!xr zhy*{NQ&_CR|dJ2w--ev$C&PANTG!2#n;bM z%myW%Fm)x-gDEk?A)YQVh`NJrOoNE!IBYwj1Me7*-lflkHB1B>e=d? zJOY?+_uk87q6Aq-RU;(ZOe5%VgwPVj!ik3junQg=P5YgMUcM1@ z-6dnUgT%b*f@q&jto)@R?|eX9&FGYg{sCKQ!SiM)L#}tG;==aLuQEbmf+`=M3pUX0 zgL?2NFI{Xl$*lMLqm>oMP%4AOyC|C_)O;NIx5S~M-cYvg`46v6IH55S0b}PoH5DK& zQ=xCQLn$7gC9*LxI@Ybl(l|UETuf=rVj8pXhez3!3JiuXv!@=(d@AJHTWS_VGe@UD zcU=x>8Z;Q`D^T{={n=_ZP0q2K6Klso^TM^%V2bVM1g~IoN}ON)R0-u)BwI%{i{}NF z4(;xvI+S3fZsqV-q7!j4&(^leavS`@NfcpA7-rp?{hD?utMtLZ@Gzc_Pu)iO-sM7A zBvV&sq^UwkNK_Q#*RN`>ySQw6TSLKn^R;;mj)=duhNZrI2`oq@5ibmW_bXtq%*ZZ@ zJxhiq3yP*UlVZF39TUNcixz;wNj&`x&K5G1l#~F=r(QkrO^WV3c)YK;CYuOA@V#y) zH{3WxYrb~V{lSY0u1efIBEDPNHy|ycfrpGnhO<;rRvCQI6JN)QW?(???Pa)kguc^w z_^SM4@aGLYwi0wS$1MkY`dx>2Gp=xuD%)Yu0mHD`MC=@?Dst>+{d>-}y};I>k%#OM zF;Gg=c{A#<4w}N}nm+=8jO8i>7QRLASoigxk-S3;UAu;AeAjSW4X1-_-y+J9iN!F* zibk}xhwAvWFTqFrDCflK?v_gX`a--KGx{%f>}$$hD>4uH;I_7==h?binmVe_Qq!h* z^$Nnu>cBNMBK&_9_MPEyebKu|?>)LO(Sm5vJHsfE5TZtn7NSQ&ln~t@TBIYo45B4O zH%b_Sh~7IfdWjbGzvuow-RHUG>zO(G?0xpyYrU(zhlQiAXw;@SQ+a*?|7~eV{7v}qdubVtvZOoa?Bd{ndDwe!0eQ!ch@8{y2L#knCEQ_T850aAfExCG-WWT~ z+(g!$3XPCeBS^iJcDiLhonQ^wo?s%8%1xPl2yyu~#L46lRtB7{KfM>jT7+J=0H zV7AeTEZZiMQ^fG7qIchpXV6)4)a6t-99VK#xE}9}6yH`fZ}7jFjcnkx^8zC;s&p3emI!it_H1c;GA3Lj=C|9ty1%gP zjBCXEt*&@6{3MkkMNWmG=LfL0NdCK~c6*M~#D+vf!^k8tEua)Y8=<$Kj0!)XLc-Tx z`(EdzRy?d;Vwz?}(jJP}n;26hctgWUE84~lh2W2{^p_KM_sHHq@Yu5eyM}t^HC>zr zx(SZ|OnQln!e}pr$S`c1N!WWxbVitt8-y}<; zqSr=h-B~z!={v2hZ@Ns%Ubp)c5Uxib079D)RV z$s&lUTB|S5iPBf5Qa5w3iE zIjFxzh?mbSsy4q#b$RT6d~wXPp_Qc7@uyc#(Hlk&8a$nhZfh{m0f3i4^}4Can}VY4 zefK-N^%atX1omTjSTnZLhnQqd0)zxAcw9;Lyh(24(eU6oTP!!N>ii&IZL8rsi>n58 zyXhh0_Y$vNV+lBubEKwD=ulePn!fS2kb?Hmp+j7a*08?3yjr_&A|DHM{8#o;nKMPe zV3gmJsme9GeaUH|$#)_6kAa$pyfxT8(wAx0A%EZQiVmoG#!yFm6R>FY+%P}RR3Ivz zXXZY3Oev>EH+&sxm; z0wE+?jpdZrX;(bvI-{5`_bG4A#%lPVtbVr450TM`Zocec9i!y@5|sPBK8Kqx-|#+w z|Ew@1%K8e20x#!{wGb6n&|Yi(Dl?O-)TTbp%qD=SIuAW((xu@~V<(psfeM=!G{mp0 ziDY?>T&Y0NBW-zOcJ~MGE}kT;zn5^*EgtCus`9wKy#*{~x3O-ET;n4pZJ#R5(tEEM z1MW2i<5d1w)zm3mwX@%!$21m{j9 zLtr*bZ6{o4AkWMot2Z3M4L2~L9VxYrk7c<2{r>sVuU{+y8!V+gA0k>ovTf^=vbSyB z5LP$$F~YbTLR> z2JB1S>^JQR54UHNdV20`%rvqG9c{HAMA~{6N@)q_RvOwjH{TF2^qKXujh zoYGEn7ii1`KCM$`(^&p=^2pDQRi(U-u-=4kx|L8v}joqoNh) zL0(k#k|WqAkW5}=YPR+9&nu){&qMj3q4Se#4&6-Y2ZvgK7%W#pq{Kt$4q_Tm5%^jr zCML3|JeRYwvg)yBRO4=Grec5K=2#`;5JH@Mve&(%>_d2nhet_^7?yIt$%+Zc$otyiZk_-)*WoonH$6EB z2-`3y6Fw`R661ix@XjDt<1efi2MJwVGWvL5@fTQSTfSI7~7u`w~-#dQ%Qt5Hd<4~PjH=i9KQCC5XJf+LHr6qyjM;06mHjV6= zV$AxrelTi_Io(EkeP01VHU_{0_M`)JF`d09k9lLQVu2An+hfP0feJF%~7!Fw*k!a&gP6 zfF}<|iXRsj*TcjCH4hFl`1$#5URX6kyB+KYc-%@HoHtCtzWBm{Ua@a!Y0+7QdIyBw zkS}&5XgqydIlcy1YQjn^s}~m9;|&Up!Qi!p;St#&#nXQME;pY9{fEhF9=8>JV$vK@ zqyu;f!*WW;FfC3+V)T0!IpD4IY)<+*z(Dv=hL7)0DJNYO{&$cxC@!X;rLu&n=iM_V z_&wD`wZHLbONhQ-**>0tu8OsSXkqEr($Q)JEA;C6o#q5k@~G+awYFFrafG9HnMeou ztc5>4Ew`a7czAW9FIyrW2hXd6Dd+>TIpjpICbSiF)VjTNOOBA}+WKPBW6$3(+^@Ke zpU40=1Cb<0r(Vw{r+x@F4*@o>)14zcd@g8-^vvD?2&DqqFTh&#?a6yNx+d+!EICo? z!jzQGlVbd(C?dKhoA+7>L+4Hw?8kbBAPK*20L$6SE|gC7^=J zq3*U@KpbYiGBPZ>|T|wp#rD>obwtk6v(N$q76)(%3n5U)9eFa_NmxRV{5^u zuWyZ7ROL+kXUGLBM4SAYaQ))E*NR7iv0ey?>aO5YDnJr|L*r zDrOEHC<~XTesyIGVUr~OM?x*d$_A+c#J^9Y`a|B!Yw5-1`T27)#8oCsAcx&wX(%JN zX;ib8_8*;#zPz3piTU}4ze+97Yb`a+IWho*48ZSEZ5t{K)9u0SX`yl>rcw@ z4Z)`nT+P>zuJl(1MJ88BsE}NZ2pW;&hwCe~w#kJ+2U6!uWBoW}Xl;&MGAaJ?cP5_6 z4nzx+C&pNWK@A^0upa~my=lKqO}Te#SH%BJNGAqmiAGs7B8EJMh)BW0aC#jaX2fU| zuy(}t;yz8s_|p0Lb#9oXn4^vay=Y>{;NW-CDqXle-lGeSv5$6r#2bxkzl>j12+j&aMaf?fBHny;`_#^Z3^0p zOBZz1J82OYQBYhn5r94Oi{3;TVt3!6o9$W&BSuY~oELwc96-%Q1hvI(#h~%D4VUh-X@d;?mq@>W+5+fjwnn?ecxFgklNg$^ z_S=(hN9(|32lixoRo=mEx0rcogBM!*xK`mN9e7PJfJXN%YG}_#OCow&;AJoQWtppI zgPEZRt7~x|2k!AkM!{1v%gjp82KWGKqex=BF<14FN@#Gvd$|H*5O~oLQX9{la(Xb@ zIaAA^LPDc%|ETct-*WfD-wjNn=IXz{H5K01B0sWK+|l%rh|^D3J0am}J|8xluktJD z-;TIx0)mdDRGRbiZNz9*O-$mo&CTkYJF}Nsea@e1S5^$VaYRnTU%6zd!QRHMD1Y+D zuYM~M@jVCs&FX5++#*5Ja(6%INoP7dJUZj>aN-L|lOl6MpA$pLosQm=WMTHrkPaic zab7_V&~GNJtf4U2lSvtHiE^quyDNwZgIOGLD_bpy2SEicNn+q#y-rso0b2~gJT@)H z64;`amb)Jxo%rf_xIb9grumS|6SufvU~NnY8bt%IJd<$`Jsrr`QxS7mH=P!H3J(od zgE+WCSnj#GUBPtZz!ccj^{57B0x5StFNW^Y*}L|=OkP(H#3v)&XZ!boeLuF{7qc2Zsi zXC#Lo=UMEWA3f&b#)k~ve27gGYmCg}yZt~lL@6Ek*$z6S?&oI~m3#9UFV1gMQjOTy zumtQ2d}(ah|LJl=C>bakPxKKd1OpbNUrd5tLR&lH=!;t|w)O$u3Hr3O1~SpRMJC$! zDItg9Is}36oUvRN80dX;+&dz%5GhsOjbvd1en&^Lb^QZLN2E;!P;`ia zSA4WmY`kSwWT(x|Zdd6cuJ;zu78M&l-{XDt z4p1rPYA?S2CMgOE`S)p5)Rr?8duJqp>Dl$iZcQhs6J(uIOs;1<`_bq6v)eG_ps4>; z;Z8b=f`H1jq_Vs^W^~ePl$o9oVEvbNL5Ij}JcyTxiKWuFc` zq@d8r)Vr;c68Dtu+I;W928W1w&8mRy1~etpQ*%$S2Du>20gkaOfc7{h z<(Mtd+Dd0A8K{kT(6ii)Jv~Be{8<{p{#{$JUji69EuMMtWeka^URrcL85!|*ehDfR z_@aTJ?F1ZPn$z9IwCANiTJb^PYau}I{)hg+K(BH9SgRRqaD9L7!NbTJ^obDf*AA** zK==gMC|#t!8@@Nr7N6kmUukDk$x;>f|KE__{5c_3RFJYRlJ_9)e{go!$&)V$evbwA8w- zmG<5Ew}f9T6(GVowBxNA)lC>nRZoS1NHz!j>3O(q8L&dV#m}pj z@tzb|DFO6Tvi9BG-!qLj-qKZ0@RwC@j1OYT-%weyQ2HherA$o7SeikAM@81Mz>d@~ zt)@2s=qp!Of>#Jp%;t;B`f)d4o@`!BA#T%DapDf%DeQ?)_1E^^E$O zrPu01S(mDss;7eK&OI(?x2*yBxO#YaySHuMTJrHPwV{f+ zmAYfOiM;@FA|U^a8u%slwZMQ_QIf&CK1e2P+u7l@gYKTI(&WDeKl1?L1j^fO;M-)X z;GiK99Hn~GZdgxEmKf21$o@^iRp8<}LiWFw#ZBOOxqZ1XvbP*+8V^j!OT4N&?}AgZpye1q&=$Khe-I|zw;0~CUjzpDwdFz&^RwIs~~Tw ziD@!t1bD{?1o0RNA+mQJgf_5DN)m>80kty{T{00Q@fgkPcjGVsHn37r0dWC-EOJF; zTr9VQkyFLJk_b_3I@*_)tg|n3A))mLYmR;x0n2J`_8COKYj`e?Q-R=svTs~ukF*1; z>lo^LdEuQQsjY;Td7<)C%+~Wz0iFxr`|7kH77$e}yP=gpuL|O+SCT~19yRsNR8gq= zR{7fuhK09H7n`+Hl~Hz$eI+uve;BM0j(C!_gQk90vM`igJ}NE z2FL6tu*-L3U&UEM>Fin6OEL;YMJSYCj7Ak$C!p&oMJ4h~iVb~Eq(aCj5hpQRaoa(q zR)wH{ z^n3uin$*Mu1lEZ-MwpGTi>Q$7STl6{Fz;ksr-nXgL@e1QN>a?~JcU;l8x){uaN|=aZsOKA!Xr=&M_~-3G|(=@>c$fuUlB0Nx#_L)dBV2K(LV8W_blN@@fVJ_p&b)x3flVFDI~)w`FB1 z$7>nP{`7mA$@uC<&uGJ-w&lji+FnSF(r3LgSdqoD=#%w(LUi-1&ZtpGAn ztD`_Kup2SDYuiG9eOVs;g833>)skAV!tA)$k z6K()EIg{BY)Tzt{f<{#@?^n;iMuZpj+}RDL$iK&7Rp|bk$Q~K|AgiY4RYiu<8;zK_ zqu1=LVlbmZ@uk$e-a*p}IP*3@!JGvw8ow_KInV)G!m$uMjq}tCN@{^Z7NrGdbn2S4L7i+}z$vohe#9SBJ;J zrw3ec-w4=ttFk~1yE-~K*&VD6Bi+mYqU3k3Ta$eAS=N1G7KXgTYg7mpzjdl|@5T+C zk}nq7T7P&_x+j&6b%aF{JiiQ&J2^RB6BO*48g^lFHo Date: Fri, 4 Oct 2024 15:18:25 +0200 Subject: [PATCH 126/136] remove docs build of nxdl groupings --- dev_tools/docs/nxdl_index.py | 38 ++---------------------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index e3f9c9371..bcb8ac666 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -66,22 +66,13 @@ def nxdl_indices() -> Dict[str, dict]: else: file = "" print("---------++++++++-", section) - if file.endswith(("applications/index.rst", "base_classes/index.rst")): - rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") - rst_lines.append(f"{indentation}mpes-structure\n") - rst_lines.append(f"{indentation}apm-structure\n") - if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") + rst_lines.append(f"{indentation}ellipsometry-structure\n") rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") - rst_lines.append(f"{indentation}sts-structure\n") rst_lines.append(f"{indentation}cgms-structure\n") - rst_lines.append(f"{indentation}icme-structure\n") - rst_lines.append(f"{indentation}sample-prep-structure\n") for cname in sorted(classes): rst_lines.append(f"{indentation}{cname}\n") @@ -119,18 +110,6 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: *might* be used in an instance of that class. Consider the base classes as a set of *components* that are used to construct a data file. - -Some contributions are grouped together: - :ref:`Optical Spectroscopy ` - - :ref:`Multi-dimensional Photoemission Spectroscopy ` - - :ref:`Atomprobe Microscopy ` - - :ref:`Electron Microscopy ` - -and others are simply listed here: - """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "applications": """ @@ -159,19 +138,6 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: In application definitions involving raw data, write the raw data in the :ref:`NXinstrument` tree and then link to it from the location(s) defined in the relevant application definition. - -Some contributions are grouped together: - :ref:`Optical Spectroscopy ` - - :ref:`Multi-dimensional Photoemission Spectroscopy ` - - :ref:`Atomprobe Microscopy ` - - :ref:`Electron Microscopy ` - - -and others are simply listed here: - """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "contributed_definitions": """ @@ -194,7 +160,7 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: and acceptance as either a base class or application definition. Some contributions are grouped together: - :ref:`Optical Spectroscopy ` + :ref:`Optical Spectroscopy ` :ref:`Multi-dimensional Photoemission Spectroscopy ` From 00bf64c88f2b12e3a51623c4d42bcbf1b8f19303 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:18:49 +0200 Subject: [PATCH 127/136] implement review suggestions --- dev_tools/docs/nxdl.py | 9 ++++++--- dev_tools/tests/test_nxdl_utils.py | 31 ------------------------------ 2 files changed, 6 insertions(+), 34 deletions(-) diff --git a/dev_tools/docs/nxdl.py b/dev_tools/docs/nxdl.py index 31015016a..a6aaf25af 100644 --- a/dev_tools/docs/nxdl.py +++ b/dev_tools/docs/nxdl.py @@ -311,9 +311,12 @@ def _get_doc_blocks(ns, node): return out_blocks def _handle_multiline_docstring(self, blocks): + link_pattern = re.compile(r"\.\. _([^:]+):(.*)") + links = [] docstring = "" expanded_blocks = [] + for block in blocks: expanded_blocks += block.split("\n") @@ -321,11 +324,11 @@ def _handle_multiline_docstring(self, blocks): if not block: continue - link_match = re.search(r"\.\. _([^:]+):(.*)", block) + link_match = link_pattern.search(block) if link_match is not None: links.append((link_match.group(1), link_match.group(2).strip())) else: - docstring += " " + re.sub(r"\n", " ", block.strip()) + docstring += " " + block.strip().replace("\n", " ") for name, target in links: docstring = docstring.replace(f"`{name}`_", f"`{name} <{target}>`_") @@ -338,7 +341,7 @@ def _get_doc_line(self, ns, node): return "" if len(blocks) > 1: return self._handle_multiline_docstring(blocks) - return re.sub(r"\n", " ", blocks[0]) + return blocks[0].replace("\n", " ") def _get_minOccurs(self, node): """ diff --git a/dev_tools/tests/test_nxdl_utils.py b/dev_tools/tests/test_nxdl_utils.py index 7b3953847..10e17ab9c 100644 --- a/dev_tools/tests/test_nxdl_utils.py +++ b/dev_tools/tests/test_nxdl_utils.py @@ -49,37 +49,6 @@ def test_get_node_at_nxdl_path(): ) assert node.attrib["name"] == "long_name" - # nxdl_file_path = os.path.join(local_dir, "../../applications/NXem.nxdl.xml") - # elem = ET.parse(nxdl_file_path).getroot() - # node = nexus.get_node_at_nxdl_path( - # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/end_time", elem=elem - # ) - # assert node.attrib["name"] == "end_time" - - # node = nexus.get_node_at_nxdl_path("/ENTRY/measurement", elem=elem) - # assert node.attrib["type"] == "NXem_msr" - - # node = nexus.get_node_at_nxdl_path( - # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/IMAGE_SET/image_3d", - # elem=elem, - # ) - # assert node.attrib["type"] == "NXdata" - - # node = nexus.get_node_at_nxdl_path( - # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/IMAGE_SET/image_3d/AXISNAME_indices", - # elem=elem, - # ) - # assert node.attrib["name"] == "AXISNAME_indices" - - # node = nexus.get_node_at_nxdl_path( - # "/ENTRY/measurement/EVENT_DATA_EM_SET/EVENT_DATA_EM/IMAGE_SET/image_3d/axis_j", - # elem=elem, - # ) - # assert node.attrib["type"] == "NX_NUMBER" - - # node = nexus.get_node_at_nxdl_path("/ENTRY/coordinate_system_set", elem=elem) - # assert node.attrib["type"] == "NXcoordinate_system_set" - nxdl_file_path = os.path.join( local_dir, "../../contributed_definitions/NXiv_temp.nxdl.xml" ) From 84959792545fe7db7b2a8ac393cc879e52ead8de Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:00:24 +0200 Subject: [PATCH 128/136] simplify nxdl_utils.py --- dev_tools/utils/nxdl_utils.py | 82 +++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index d5ced922e..6110872a6 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -46,7 +46,7 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): try: return elem.decode(encoding) except UnicodeDecodeError as e: - raise ValueError(f"Error decoding bytes: {e}") + raise ValueError(f"Error decoding bytes: {e}") from e return elem @@ -153,19 +153,22 @@ def get_nx_namefit( ) -> int: """ Checks if an HDF5 node name corresponds to a child of the NXDL element. - A group of uppercase letters anywhere in the name is treated as freely choosable - part of this name. - If a match is found this function returns twice the length for an exact match, - otherwise the number of matching characters (case insensitive) or zero, if - `name_any` is set to True, is returned. - All uppercase groups are considered independently. - Lowercase matches are independent of uppercase group lengths, e.g., - an hdf_name `get_nx_namefit("my_fancy_yet_long_name", "my_SOME_name")` would - return a score of 8 for the lowercase matches `my_..._name`. - All characters in `[a-zA-Z0-9_.]` are considered for matching to an uppercase letter. - If you use any other letter in the name, it will not match and return -1. - Periods at the beginning or end of the hdf_name are not allowed, only exact - matches will be considered. + Groups of uppercase letters anywhere in the name are treated as freely + choosable parts of this name. + + If a match is found, this function returns twice the length of the + name for an exact match. If there is no exact match, the function + returns the number of matching characters (case insensitive). If + `name_any` is set to True, it returns zero instead of a count of + matches. All uppercase groups are considered independently, and + lowercase matches do not depend on uppercase group lengths. For example, + calling `get_nx_namefit("my_fancy_yet_long_name", "my_SOME_name")` + would return a score of 8 for the lowercase matches `my_..._name`. + + All characters in `[a-zA-Z0-9_.]` are considered for matching to an + uppercase letter. Any other character in the name will result in + a non-match and return -1. Periods at the beginning or end of the + `hdf_name` are not allowed; only exact matches will be considered. Examples: @@ -183,6 +186,11 @@ def get_nx_namefit( name_any (bool, optional): Accept any name and return either 0 (match) or -1 (no match). Defaults to False. + name_partial (bool, optional): + If set to True, the function will return the total length of the name + plus the number of matching characters, minus the count of uppercase + letters in the concept name. This allows for partial matches to + contribute to the score. Defaults to False. Returns: int: -1 if no match is found or the number of matching @@ -297,6 +305,24 @@ def get_node_name(node): name = name[2:].upper() return name +def is_name_type(child, name_type_value: str) -> bool: + """ + Determines if the child XML element's nameType attribute is equal to + the specified value or if the child is a group without nameType and name attributes. + + Args: + child: The XML element to check. + name_type_value (str): The nameType value to compare against ("any" or "partial"). + + """ + return ( + child.attrib.get("nameType") == name_type_value or + ( + get_local_name_from_xml(child) == "group" and + "nameType" not in child.attrib and + "name" not in child.attrib + ) + ) def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): """Checks if an HDF5 node name corresponds to a child of the NXDL element @@ -310,24 +336,10 @@ def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): return True if not hdf_name: # search for name fits is only allowed for hdf_nodes return False - name_any = child.attrib["nameType"].get("nameType") == "any" or ( - get_local_name_from_xml(child) == "group" - and "nameType" not in child.attrib.keys() - and "name" not in child.attrib.keys() - ) - params = [act_htmlname, chk_name, name_any, nxdl_elem, child, name] - return belongs_to_capital(params) - + name_any = is_name_type(child, "any") -def belongs_to_capital(params): - """Checking continues for Upper case""" - (act_htmlname, chk_name, name_any, nxdl_elem, child, name) = params # or starts with capital and no reserved words used - name_partial = child.attrib["nameType"].get("nameType") == "partial" or ( - get_local_name_from_xml(child) == "group" - and "nameType" not in child.attrib.keys() - and "name" not in child.attrib.keys() - ) + name_partial = is_name_type(child, "partial") if (name_any or name_partial) and name != "doc" and name != "enumeration": fit = get_nx_namefit( chk_name, act_htmlname, name_any=name_any, name_partial=name_partial @@ -343,11 +355,7 @@ def belongs_to_capital(params): ): continue # check if the name of another sibling fits better - name_any2 = child2.attrib.get("nameType") == "any" or ( - get_local_name_from_xml(child2) == "group" - and "nameType" not in child2.attrib.keys() - and "name" not in child2.attrib.keys() - ) + name_any2 = is_name_type(child2, "any") name_partial2 = child2.attrib.get("nameType") == "partial" if name_partial2 or name_any2: fit2 = get_nx_namefit( @@ -356,8 +364,8 @@ def belongs_to_capital(params): name_any=name_any2, name_partial=name_partial2, ) - if fit2 > fit: - return False + if fit2 > fit: + return False # accept this fit return True return False From 7d851fba47265c09c988e9f70ee19c5e1ded0721 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:38:30 +0200 Subject: [PATCH 129/136] minor fixes from review --- dev_tools/utils/nxdl_utils.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 6110872a6..cc11f8146 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -46,7 +46,7 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): try: return elem.decode(encoding) except UnicodeDecodeError as e: - raise ValueError(f"Error decoding bytes: {e}") from e + raise ValueError(f"Error decoding bytes") from e return elem @@ -850,11 +850,7 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): if get_local_name_from_xml(child) == nexus_type and ( nexus_type != "group" or get_nx_class(child) == hdf_class_name ): - name_any = child.attrib.get("nameType") == "any" or ( - nexus_type == "group" - and "nameType" not in child.attrib.keys() - and "name" not in child.attrib.keys() - ) + name_any = is_name_type(child, "any") name_partial = child.attrib.get("nameType") == "partial" if name_partial or name_any: fit = get_nx_namefit( From 301582d2b571563af7f92aaf30fa720067bf26ff Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:50:08 +0200 Subject: [PATCH 130/136] black formatting --- dev_tools/utils/nxdl_utils.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index cc11f8146..931c67e7c 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -46,7 +46,7 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): try: return elem.decode(encoding) except UnicodeDecodeError as e: - raise ValueError(f"Error decoding bytes") from e + raise ValueError("Error decoding bytes") from e return elem @@ -305,6 +305,7 @@ def get_node_name(node): name = name[2:].upper() return name + def is_name_type(child, name_type_value: str) -> bool: """ Determines if the child XML element's nameType attribute is equal to @@ -315,15 +316,13 @@ def is_name_type(child, name_type_value: str) -> bool: name_type_value (str): The nameType value to compare against ("any" or "partial"). """ - return ( - child.attrib.get("nameType") == name_type_value or - ( - get_local_name_from_xml(child) == "group" and - "nameType" not in child.attrib and - "name" not in child.attrib - ) + return child.attrib.get("nameType") == name_type_value or ( + get_local_name_from_xml(child) == "group" + and "nameType" not in child.attrib + and "name" not in child.attrib ) + def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): """Checks if an HDF5 node name corresponds to a child of the NXDL element uppercase letters in front can be replaced by arbitraty name, but From 1063abe1c03320ef7421fdbff58a5f196e056e9b Mon Sep 17 00:00:00 2001 From: Rubel Date: Thu, 17 Oct 2024 14:08:27 +0200 Subject: [PATCH 131/136] Name type. --- dev_tools/utils/nxdl_utils.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 931c67e7c..25bd00804 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -46,7 +46,7 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): try: return elem.decode(encoding) except UnicodeDecodeError as e: - raise ValueError("Error decoding bytes") from e + raise UnicodeDecodeError(f"Error decoding bytes: {e}") return elem @@ -316,11 +316,19 @@ def is_name_type(child, name_type_value: str) -> bool: name_type_value (str): The nameType value to compare against ("any" or "partial"). """ - return child.attrib.get("nameType") == name_type_value or ( - get_local_name_from_xml(child) == "group" - and "nameType" not in child.attrib - and "name" not in child.attrib - ) + if (child.attrib.get("nameType") == name_type_value): + return True + + + if name_type_value == "any" and( + get_local_name_from_xml(child) == "group" and + "nameType" not in child.attrib and + "name" not in child.attrib): + return True + return False + + + def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): @@ -850,7 +858,11 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): nexus_type != "group" or get_nx_class(child) == hdf_class_name ): name_any = is_name_type(child, "any") +<<<<<<< Updated upstream name_partial = child.attrib.get("nameType") == "partial" +======= + name_partial = is_name_type(child, "partial") +>>>>>>> Stashed changes if name_partial or name_any: fit = get_nx_namefit( hdf_name, From fdf6c055d792885004094e3dc6cbc0b8e57df234 Mon Sep 17 00:00:00 2001 From: Rubel Date: Thu, 17 Oct 2024 14:12:23 +0200 Subject: [PATCH 132/136] fix conflict. --- dev_tools/utils/nxdl_utils.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 25bd00804..32d09cbff 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -858,11 +858,7 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): nexus_type != "group" or get_nx_class(child) == hdf_class_name ): name_any = is_name_type(child, "any") -<<<<<<< Updated upstream - name_partial = child.attrib.get("nameType") == "partial" -======= name_partial = is_name_type(child, "partial") ->>>>>>> Stashed changes if name_partial or name_any: fit = get_nx_namefit( hdf_name, From 485cd0aa5c66aa73929e8187ecce9cec9ed3a044 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:18:44 +0200 Subject: [PATCH 133/136] black formatting --- dev_tools/utils/nxdl_utils.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 32d09cbff..013a43ec7 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -316,21 +316,18 @@ def is_name_type(child, name_type_value: str) -> bool: name_type_value (str): The nameType value to compare against ("any" or "partial"). """ - if (child.attrib.get("nameType") == name_type_value): + if child.attrib.get("nameType") == name_type_value: return True - - if name_type_value == "any" and( - get_local_name_from_xml(child) == "group" and - "nameType" not in child.attrib and - "name" not in child.attrib): + if name_type_value == "any" and ( + get_local_name_from_xml(child) == "group" + and "nameType" not in child.attrib + and "name" not in child.attrib + ): return True return False - - - def belongs_to(nxdl_elem, child, name, class_type=None, hdf_name=None): """Checks if an HDF5 node name corresponds to a child of the NXDL element uppercase letters in front can be replaced by arbitraty name, but @@ -858,7 +855,7 @@ def get_best_child(nxdl_elem, hdf_node, hdf_name, hdf_class_name, nexus_type): nexus_type != "group" or get_nx_class(child) == hdf_class_name ): name_any = is_name_type(child, "any") - name_partial = is_name_type(child, "partial") + name_partial = is_name_type(child, "partial") if name_partial or name_any: fit = get_nx_namefit( hdf_name, From 7e40c0d9d9d7c6fd89635338cb99345b2749d96a Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:00:17 +0200 Subject: [PATCH 134/136] refactor to use pathlib.Path(), add to UnicodeDecodeError --- dev_tools/tests/test_nxdl_utils.py | 19 +++++++------------ dev_tools/utils/nxdl_utils.py | 5 +++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/dev_tools/tests/test_nxdl_utils.py b/dev_tools/tests/test_nxdl_utils.py index 10e17ab9c..b246e4a82 100644 --- a/dev_tools/tests/test_nxdl_utils.py +++ b/dev_tools/tests/test_nxdl_utils.py @@ -2,8 +2,7 @@ """ -import os - +from pathlib import Path import lxml.etree as ET import pytest @@ -33,8 +32,8 @@ def test_get_nexus_classes_units_attributes(): def test_get_node_at_nxdl_path(): """Test to verify if we receive the right XML element for a given NXDL path""" - local_dir = os.path.abspath(os.path.dirname(__file__)) - nxdl_file_path = os.path.join(local_dir, "./NXtest.nxdl.xml") + local_dir = Path(__file__).resolve().parent + nxdl_file_path = local_dir / "NXtest.nxdl.xml" elem = ET.parse(nxdl_file_path).getroot() node = nexus.get_node_at_nxdl_path("/ENTRY/NXODD_name", elem=elem) assert node.attrib["type"] == "NXdata" @@ -49,9 +48,7 @@ def test_get_node_at_nxdl_path(): ) assert node.attrib["name"] == "long_name" - nxdl_file_path = os.path.join( - local_dir, "../../contributed_definitions/NXiv_temp.nxdl.xml" - ) + nxdl_file_path = local_dir.parent.parent / "contributed_definitions" / "NXiv_temp.nxdl.xml" elem = ET.parse(nxdl_file_path).getroot() node = nexus.get_node_at_nxdl_path( "/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", elem=elem @@ -66,16 +63,14 @@ def test_get_node_at_nxdl_path(): def test_get_inherited_nodes(): """Test to verify if we receive the right XML element list for a given NXDL path.""" - local_dir = os.path.abspath(os.path.dirname(__file__)) + local_dir = Path(__file__).resolve().parent + nxdl_file_path = local_dir / "NXtest.nxdl.xml" - nxdl_file_path = os.path.join(local_dir, "./NXtest.nxdl.xml") elem = ET.parse(nxdl_file_path).getroot() (_, _, elist) = nexus.get_inherited_nodes(nxdl_path="/ENTRY/NXODD_name", elem=elem) assert len(elist) == 3 - nxdl_file_path = os.path.join( - local_dir, "../../contributed_definitions/NXiv_temp.nxdl.xml" - ) + nxdl_file_path = local_dir.parent.parent / "contributed_definitions" / "NXiv_temp.nxdl.xml" elem = ET.parse(nxdl_file_path).getroot() (_, _, elist) = nexus.get_inherited_nodes( diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 013a43ec7..403b3eabc 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -29,7 +29,7 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): If `decode` is False, always returns the initial value. Raises: - ValueError: If a byte string cannot be decoded using the provided encoding. + UnicodeDecodeError: If a byte string cannot be decoded using the provided encoding. """ if not decode: return elem @@ -46,7 +46,8 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): try: return elem.decode(encoding) except UnicodeDecodeError as e: - raise UnicodeDecodeError(f"Error decoding bytes: {e}") + e.add_note(f'Error decoding bytes object: {elem}') + raise return elem From 12017488b63a8d40af53eaab9ababbcb58be31a1 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:01:41 +0200 Subject: [PATCH 135/136] formatting --- dev_tools/tests/test_nxdl_utils.py | 8 ++++++-- dev_tools/utils/nxdl_utils.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/dev_tools/tests/test_nxdl_utils.py b/dev_tools/tests/test_nxdl_utils.py index b246e4a82..d751cbe65 100644 --- a/dev_tools/tests/test_nxdl_utils.py +++ b/dev_tools/tests/test_nxdl_utils.py @@ -48,7 +48,9 @@ def test_get_node_at_nxdl_path(): ) assert node.attrib["name"] == "long_name" - nxdl_file_path = local_dir.parent.parent / "contributed_definitions" / "NXiv_temp.nxdl.xml" + nxdl_file_path = ( + local_dir.parent.parent / "contributed_definitions" / "NXiv_temp.nxdl.xml" + ) elem = ET.parse(nxdl_file_path).getroot() node = nexus.get_node_at_nxdl_path( "/ENTRY/INSTRUMENT/ENVIRONMENT/voltage_controller", elem=elem @@ -70,7 +72,9 @@ def test_get_inherited_nodes(): (_, _, elist) = nexus.get_inherited_nodes(nxdl_path="/ENTRY/NXODD_name", elem=elem) assert len(elist) == 3 - nxdl_file_path = local_dir.parent.parent / "contributed_definitions" / "NXiv_temp.nxdl.xml" + nxdl_file_path = ( + local_dir.parent.parent / "contributed_definitions" / "NXiv_temp.nxdl.xml" + ) elem = ET.parse(nxdl_file_path).getroot() (_, _, elist) = nexus.get_inherited_nodes( diff --git a/dev_tools/utils/nxdl_utils.py b/dev_tools/utils/nxdl_utils.py index 403b3eabc..13f3ee5f9 100644 --- a/dev_tools/utils/nxdl_utils.py +++ b/dev_tools/utils/nxdl_utils.py @@ -46,7 +46,7 @@ def decode_or_not(elem, encoding: str = "utf-8", decode: bool = True): try: return elem.decode(encoding) except UnicodeDecodeError as e: - e.add_note(f'Error decoding bytes object: {elem}') + e.add_note(f"Error decoding bytes object: {elem}") raise return elem From bdf0ed8b29cb26ecbff495dc28051e9cc2996b3b Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:05:28 +0200 Subject: [PATCH 136/136] isort --- dev_tools/tests/test_nxdl_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev_tools/tests/test_nxdl_utils.py b/dev_tools/tests/test_nxdl_utils.py index d751cbe65..2f7e67768 100644 --- a/dev_tools/tests/test_nxdl_utils.py +++ b/dev_tools/tests/test_nxdl_utils.py @@ -3,6 +3,7 @@ """ from pathlib import Path + import lxml.etree as ET import pytest

yZj4a z+&Sp*Aa2!ph6crB)@h1>vb*{8)k7m%G`F~$i&PBD)HnyI}%JeO1C57J8z zf%F1G^LT$~hhee=afXy$sk0e_`V&n+rBL9L58F)-RKkI5ye^aL;O3lNaD*=`{MTa1 z1urur5Wm4nuY>57V5$;lhLnc!r3MaG;ouK3!!L~jjyckxN#)?Uy%`Q%({eOMJr8(h zZWm`(H;Nwh>n1FN;Bd5RNxgAoQXlG_unHUo9K$Y!0_#wdQ6E}Wd1^488HuL1AOg#R zev@GrwWMqA@CWK`NVk6O1q_NbMFD>AEkem1_GJu#gz65BERwn<5I0 OdyC(8-{OtzqyGX}z-~YQ literal 0 HcmV?d00001 diff --git a/manual/source/index.rst b/manual/source/index.rst index bb4717055..25f293f57 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -1,35 +1,40 @@ -.. image:: img/NeXus.png - :width: 40% - ======================================= User Manual and Reference Documentation ======================================= +Welcome to the user manual of the NeXus for FAIRmat project. + https://www.nexusformat.org/ .. toctree:: :maxdepth: 2 - :numbered: 4 - - user_manual - examples/index - ref_doc - napi - community - installation - utilities - history - docs_about + + fairmat-cover + nexus-index + em-structure + mpes-structure + ellipsometry-structure + apm-structure + transport-structure + stm-structure + cgms-structure + laboratory-structure + north-structure + + ----------- .. rubric:: Publishing Information -This manual built |today|. +| This commit time code <>. +| This commit identifier <>. +| This manual built |today|. + .. seealso:: - This document is available in these formats online: + The extended NeXus documentation: :HTML: https://manual.nexusformat.org/ @@ -46,11 +51,14 @@ This manual built |today|. :PDF: https://manual.nexusformat.org/_static/NXImpatient.pdf -.. Suggestions for adding to this manual: + FAIRmat website: + + ``_ + + NOMAD website: + + ``_ + + + - Look for some other "section" such as "introduction.rst" and act similarly. - Any examples go as text files in the examples/ subdirectory and are pulled into - Sphinx inside a :directive:`literalcode` directive. Look for the pattern - or wing it. If you are ambitious, add index entries. Many examples of the - constructs you might use are already in the manual. - diff --git a/manual/source/laboratory-structure.rst b/manual/source/laboratory-structure.rst new file mode 100644 index 000000000..05523bcbf --- /dev/null +++ b/manual/source/laboratory-structure.rst @@ -0,0 +1,25 @@ +.. _Lab-Structure: + +================== +Sample preparation +================== + +.. index:: + Draft classes + +.. _LaboratorySteps: + +Virtually all experiments require a preparation of the sample. As most techniques +are surface-sensitive or probe exclusively the surface, the use of careful preparation +techniques is the key to successful experiments. Unfortunately, the quality of +such processes is often difficult to reproduce. Nevertheless, documenting how samples +are prepared is relevant. The classes here provide minimal examples how descriptions +of the sample preparation steps can be interfaced to NeXus. +Currently, we consider these drafts to work towards harmonization with the +specific examples developed by the team of area A of FAIRmat. + + :ref:`NXlab_sample_mounting`: + An application definition to document how a sample was mounted. + + :ref:`NXlab_electro_chemo_mechanical_preparation`: + An application definition to document how a sample was prepared. diff --git a/manual/source/nexus-index.rst b/manual/source/nexus-index.rst new file mode 100644 index 000000000..1e9bf529a --- /dev/null +++ b/manual/source/nexus-index.rst @@ -0,0 +1,20 @@ +.. _NexusIndex: + +======================================= +NeXus Documentation +======================================= + +Welcome to the user manual of the NeXus. + +https://www.nexusformat.org/ + +.. toctree:: + :maxdepth: 2 + + user_manual + examples/index + ref_doc + community + installation + utilities + docs_about \ No newline at end of file diff --git a/manual/source/sed/entry-page.html b/manual/source/sed/entry-page.html new file mode 100644 index 000000000..b7c84946c --- /dev/null +++ b/manual/source/sed/entry-page.html @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/manual/source/stm-structure.rst b/manual/source/stm-structure.rst new file mode 100644 index 000000000..944c26203 --- /dev/null +++ b/manual/source/stm-structure.rst @@ -0,0 +1,32 @@ +.. _Stm-Structure: + +============================= +Scanning Tunneling Microscopy +============================= + + +.. index:: + IntroductionStm + StmAppDef + StmNewBC + + +.. _IntroductionStm: + +Introduction +############## +TBD + + +.. _StmAppDef: + +Application Definitions +####################### +TBD + + +.. _StmNewBC: + +Base Classes +############ +TBD From fbdb30e905fc8cba4d2ccca7d40c6c98c7a0debc Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Wed, 19 Jul 2023 13:04:03 +0200 Subject: [PATCH 002/136] restore further pages for FAIRmat proposal site --- manual/source/apm-structure.rst | 90 ++++++++++++++ .../container/ComplexContainerBeampath.png | Bin 0 -> 7089 bytes .../container/ComplexExampleContainer.png | Bin 0 -> 25103 bytes manual/source/mpes-structure.rst | 111 ++++++++++++++++++ 4 files changed, 201 insertions(+) create mode 100644 manual/source/apm-structure.rst create mode 100644 manual/source/classes/contributed_definitions/container/ComplexContainerBeampath.png create mode 100644 manual/source/classes/contributed_definitions/container/ComplexExampleContainer.png create mode 100644 manual/source/mpes-structure.rst diff --git a/manual/source/apm-structure.rst b/manual/source/apm-structure.rst new file mode 100644 index 000000000..11ef11f39 --- /dev/null +++ b/manual/source/apm-structure.rst @@ -0,0 +1,90 @@ +.. _Apm-Structure: + +========================= +B5: Atom-probe tomography +========================= + +.. index:: + IntroductionApm + ApmAppDef + ApmBC + ApmRemovedBC + ApmFurtherDefs + + +.. _IntroductionApm: + +Introduction +############## + +Set of data storage objects to describe the acquisition/measurement side, the reconstruction, and the ranging for atom probe microscopy experiments. The data storage objects can be useful as well for field-ion microscopy experiments. + +.. _ApmAppDef: + +Application Definitions +####################### + +We created one new application definition whose intention is to serve both the description of atom probe tomography and field-ion microscopy measurements: + + :ref:`NXapm`: + A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes (ranging). + +.. _ApmBC: + +Base Classes +############ + +We developed new base classes to structure the application definition into lab experiment and computational steps: + + :ref:`NXchamber`: + A base class to describe a component of the instrument which houses other components. A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. + + :ref:`NXcoordinate_system_set` + A base class to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. + + :ref:`NXion`: + A base class to describe charged molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with which all possible isotopes can be described. + + :ref:`NXfabrication`: + A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. + + :ref:`NXpeak`: + A base class to describe peaks mathematically so that it can be used to detail how peaks in mass-to-charge-state ratio histograms (aka mass spectra) are defined and labelled as iontypes. + + :ref:`NXpump`: + A base class to describe details about a pump in an instrument. + + :ref:`NXpulser_apm`: + A base class to describe the high-voltage and/or laser pulsing capabilities of an atom probe microscope. + + :ref:`NXreflectron`: + A base class to describe a kinetic-energy-sensitive filtering device for time of flight (ToF). + + :ref:`NXstage_lab`: + A base class to describe the specimen fixture including the cryo-head. This base class is an example that the so far used :ref:`NXstage_lab` base class is insufficiently detailed to represent the functionalities which modern stages of an + atom probe microscope or especially an electron microscope offer. Nowadays, these stages represent small-scale laboratory platforms. Hence, there is a need to define their characteristics in more detail, especially in light of in-situ experiments. We see many similarities between a stage in an electron microscope and one in an atom probe instrument, given that both offer fixture functionalities and additional components for applying e.g. stimuli on the specimen. For this reason, we use this base class currently for atom probe and electron microscopy. + +Microscopy experiments, not only taking into account those performed on commercial instruments, offer the user usually +a set of frequently on-the-fly processed computational data. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. + +.. _ApmRemovedBC: + +.. Removed base classes +.. #################### + +.. _ApmFurtherDefs: + +Further data schemas for atom probe +################################### + +We have also developed a collection of application definition which exemplify how data post-processing workflows +with typical steps specific for atom probe and reconstruction of microstructural features can be described with NeXus. +These application definitions and base classes have an own section in the proposal which you can find on the landing +page by inspection the section on computational geometry and microstructures. + +Furthermore, we are working with the NFDI-MatWerk consortium to explore how tools from the FAIRmat and the NFDI-MatWerk +consortium can be used to describe research, data, metadata, and workflows. This work is organized in the infrastructure +use case IUC09 within the NFDI-MatWerk project. One example how NeXus could be used to describe processing of +atom probe data with a tool which was developed by Alaukik Saxena et al. at the Max-Planck-Institut für Eisenforschung GmbH +in Düsseldorf is available as the so-called :ref:`NXapm_composition_space_results` application definition. + diff --git a/manual/source/classes/contributed_definitions/container/ComplexContainerBeampath.png b/manual/source/classes/contributed_definitions/container/ComplexContainerBeampath.png new file mode 100644 index 0000000000000000000000000000000000000000..597cee834c0426bd0e60b1afbf6554a5f3b04a99 GIT binary patch literal 7089 zcmbVxgT!j8lW(I7CP9R3l4E<2>J5 z)AI_IpP{<#g$8#av2ACx&qHz?7*6{wc9+~vb1nw=8zsvCGZ@1U!ma35{YCTeb^go#}G;SGXdmMbu z&k(dLz+>M0rk*>Sf)`6r0rqXS-WdWA6B8%4ZJE%EdqQPyjwzkRB;aOHTl>4)o5x|d zk^nCj4;eIl%(n^F+aGp�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®w_`d`gV3yjY{|b6NDG+(F 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 4 degrees of freedom, + cryogenic cooling and other advanced features. + +We developed three base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: + + :ref:`NXcalibration`: + A base class to describe the 1D calibration of an axis, with a function mapping a raw data scale to a calibrated scale with the same number of points. + + :ref:`NXdistortion`: + A base class to describe the 2D distortion correction of an axis, with a matrix mapping a raw data image to a undistorted image. + + :ref:`NXregistration`: + A base class to describe the rigid transformations that are applied to an image. May be redundant as they can be described with :ref:`NXtransformations`. + +.. _MpesCommonBC: + +Common Base Classes +################### + +We developed two classes that are common to other techniques: + + :ref:`NXlens_em`: + A class to describe all types of lenses. Includes electrostatic lenses for electron energy analysers. + + :ref:`NXdeflector` + A class to describe all kinds of deflectors, including electrostatic and magnetostatic deflectors for electron energy analysers. + +.. _MpesExtendedBC: + +Base Classes Extended in Application Definitions +################################################ + +We use existent base classes in application definitions and add descriptors: + + :ref:`NXaperture` + Added fileds to describe analyser apertures and slits. + + :ref:`NXbeam` + Adedd fields to describe utrafast laser beams. + + :ref:`NXdetector` + Added fields to describe electron detectors (MCP+Phospor screen, delay lines etc.). + + :ref:`NXentry` + Added fields to describe an experiment. + + :ref:`NXprocess` + Added subclasses and collective processing descriptors. + + :ref:`NXsample` + Added descriptors specific to photoemission experiments. + + :ref:`NXsource` + Added descriptors for laboratory sources (X-ray, UV lamps) but mostly for ultrafast lasers with complex time structures. + + :ref:`NXinstrument` + Added descriptors for the overall resolutions of the experiment (energy, momentum, angular, spatial, temporal). From 402740b4e7bda9d05966364089a3849ad1c70400 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Wed, 19 Jul 2023 16:44:40 +0200 Subject: [PATCH 003/136] adding old FAIRmat task pages back --- manual/source/apm-structure.rst | 22 +- manual/source/cgms-structure.rst | 284 +++++++++++++++++++++++ manual/source/ellipsometry-structure.rst | 157 +++++++++++++ manual/source/em-structure.rst | 151 ++++++++++++ manual/source/index.rst | 6 +- manual/source/mpes-structure.rst | 22 +- manual/source/north-structure.rst | 264 +++++++++++++++++++++ manual/source/transport-structure.rst | 26 +++ 8 files changed, 909 insertions(+), 23 deletions(-) create mode 100644 manual/source/cgms-structure.rst create mode 100644 manual/source/ellipsometry-structure.rst create mode 100644 manual/source/em-structure.rst create mode 100644 manual/source/north-structure.rst create mode 100644 manual/source/transport-structure.rst diff --git a/manual/source/apm-structure.rst b/manual/source/apm-structure.rst index 11ef11f39..01be214ac 100644 --- a/manual/source/apm-structure.rst +++ b/manual/source/apm-structure.rst @@ -1,25 +1,25 @@ -.. _Apm-Structure: +.. _Apm-Structure1: ========================= B5: Atom-probe tomography ========================= .. index:: - IntroductionApm - ApmAppDef - ApmBC - ApmRemovedBC - ApmFurtherDefs + IntroductionApm1 + ApmAppDef1 + ApmBC1 + ApmRemovedBC1 + ApmFurtherDefs1 -.. _IntroductionApm: +.. _IntroductionApm1: Introduction ############## Set of data storage objects to describe the acquisition/measurement side, the reconstruction, and the ranging for atom probe microscopy experiments. The data storage objects can be useful as well for field-ion microscopy experiments. -.. _ApmAppDef: +.. _ApmAppDef1: Application Definitions ####################### @@ -29,7 +29,7 @@ We created one new application definition whose intention is to serve both the d :ref:`NXapm`: A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes (ranging). -.. _ApmBC: +.. _ApmBC1: Base Classes ############ @@ -67,12 +67,12 @@ We developed new base classes to structure the application definition into lab e Microscopy experiments, not only taking into account those performed on commercial instruments, offer the user usually a set of frequently on-the-fly processed computational data. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. -.. _ApmRemovedBC: +.. _ApmRemovedBC1: .. Removed base classes .. #################### -.. _ApmFurtherDefs: +.. _ApmFurtherDefs1: Further data schemas for atom probe ################################### diff --git a/manual/source/cgms-structure.rst b/manual/source/cgms-structure.rst new file mode 100644 index 000000000..cb32812b3 --- /dev/null +++ b/manual/source/cgms-structure.rst @@ -0,0 +1,284 @@ +.. _CgmsFeatures-Structure1: + +========================= +Geometry & Microstructure +========================= + +.. index:: + IntroductionCgms1 + PhysicsCgms1 + CgmsAppDef1 + CgmsBC1 + IcmeMsModels1 + + +.. _IntroductionCgms1: + +Introduction +############ + +The computational-geometry/microstructure-modeling-based part of the proposal +has the following aims: + +First, we would like to contribute to efforts on standardizing a controlled +vocabulary, definitions for these terms, and relations between the terms, for +computational-geometry-based descriptions of the microstructure of materials +and atomic configurations used when characterizing materials in experiments +and computer simulations. + +As far as NeXus is concerned, the here proposed distinct sets of simple +geometric primitives and shapes offer a complementary alternative to the +already existent base classes in NeXus for constructive solid geometry +such as :ref:`NXcsg`, :ref:`NXoff_geometry`, or :ref:`NXquadric` to name but a few. + +Second, we would like to explore with this proposal how we can harmonize terms +frequently used by materials scientists in the field of condensed-matter physics +with definitions and terms offer by the NOMAD MetaInfo description. + +Third, the proposal should yield a substantiated set of arguments and suggestions +how descriptors for the structure and atomic architecture of materials can be +harmonized. With this we especially would like to reach out and intensify the +cooperation between the materials-science-related consortia of the German +National Research Infrastructure, specifically, FAIRmat, NFDI-MatWerk, NFDI4Ing, +NFDI4Chem, NFDI4Cat, MaRDi, and DAPHNE. + +.. The proposal reaches out to our colleagues in the materials engineering-based +.. consortia to document that there is value in discussing about controlled vocabulary. + +.. _PhysicsCgms1: + +Physics background +################## +Microstructural features or crystal defects are spatial arrangements of atoms. +Given their specific atomic arrangement and composition, such features have +specific constraints on the degrees of freedom how atoms can arrange. This causes +that these defects have specific properties. +Provided well-defined coarse-graining procedures are used and regions-of-interest +and/or regions-of-applicability are defined, microstructural features are often +characterized and modelled to have associated thermodynamic descriptors. + +Another motivation for the proposal was the observation that frequently the design +of file formats for simulation software in the computational materials science especially +those tools at the interface between condensed-matter physics and materials engineering +are frequently reimplementing the wheel (at least partly) when it comes to decide how to store +e.g. atom and feature positions or shape of regions-of-interest, grids, crystals, +grains, precipitates, and dislocations. + +Maybe this is a historical burden given the large set of technical terms and jargon +in place, which then motivated pragmatic solutions that resulted in many research groups +have developed similar formats using similar descriptions. + +We see this work on base classes and application definitions not primarily an +effort to improve and extend NeXus for now. Rather this part of the proposal +is an effort to support activities in materials science to work towards +common terminology and using controlled vocabularies more frequently. +These are the foundation for more sophisticated thoughts about practically +useful ontologies. + +Defining crystal defects is a question of how to coarse-grain a given spatio- +temporal set of atoms, each having a nuclid type and position/trajectory. +In most cases, such a coarse-graining is an ill-posed task because different +mathematical/geometrical methods exists how a point, a line, a surface, or a volumetric defect +can be described and be spatio-temporally constrained through a geometrical model +with defined geometric primitives and associated coarser-scale properties. + +The key motivation to such coarse-graining is to reduce the complexity of the +description. On the one hand to support visualization and scientific analyses - not only +of crystal defect arrangements. On the other hand it is the hope that using descriptors +at a coarser level, i.e. nanometer, micrometer, and larger, it is still possible +to find sufficiently accurate and precise descriptors which avoid that one has +to account for the dynamics of each atom to predict or understand the properties +of defects and their dynamics. + +Nevertheless, experience has shown that computational-geometry-based descriptions +when combined with hierarchical clustering/labeling methods, applied on set of +atoms and features turn out to yield useful descriptors. Examples include point, +line, surface defects, such as vacancies, solute cluster, dislocations, +disconnections, interfaces to name but a few. + +.. _CgmsBC1: + +Base Classes +############ + +We propose the following base classes, starting with a set of descriptors +for frequently used shapes and geometric primitives: + + :ref:`NXcg_sphere_set`: + A description for a set of possibly dissimilar spheres. + + :ref:`NXcg_ellipsoid_set`: + A description for a set of possibly dissimilar rotated ellipsoids. + + :ref:`NXcg_cylinder_set`: + A description for a set of possibly dissimilar rotated cylinders. + + :ref:`NXcg_point_set`: + A collection of points with labels or mark data. + + :ref:`NXcg_polyline_set`: + A collection of lines and linearized segments. + + :ref:`NXcg_triangle_set`: + A collection (or soup) of triangles. + + :ref:`NXcg_parallelogram_set`: + A collection of possibly dissimilar parallelograms. + + :ref:`NXcg_triangulated_surface_mesh`: + A mesh of triangles. + + :ref:`NXcg_polygon_set`: + A collection (or soup) of polygons. + + :ref:`NXcg_polyhedron_set`: + A collection (or soup) of polyhedra. + + :ref:`NXcg_roi_set`: + A container to host a number of different types of primitives. + + :ref:`NXcg_tetrahedron_set`: + A collection (or soup) of tetrahedra. + + :ref:`NXcg_hexahedron_set`: + A collection (or soup) of hexahedra with capabilities to represent + also simpler (bounding) boxes for e.g. binary trees. + +These base classes make use of new base classes which describe data structures: + + :ref:`NXcg_face_list_data_structure`: + In essence, the usual way how polygon/polyhedra data are reported: + Via a list of vertices and faces with identifier and properties. + + :ref:`NXcg_half_edge_data_structure`: + A half-edge data structure is a useful complementary descriptor for + polygon/polyhedra which enables topological analyses and traversal + of the graph how polygons and polyhedra can alternatively be described. + + :ref:`NXcg_unit_normal_set`: + As an additional structuring element especially for meshes, well-documented + normal information is crucial for distance computations. + + :ref:`NXcg_geodesic_mesh`: + Geodesic meshes are useful for all applications when meshing the surface + of a sphere. + + :ref:`NXcg_alpha_complex`: + Alpha shapes and alpha wrappings, specifically the special case of the + convex hull, are frequently used geometrical models for describing + a boundary or edge to a set of geometric primitives. + +Furthermore, we propose a few base classes for operations when working with +discretized representations of material (area or volume) which can be useful +not only for stencil-based methods: + + :ref:`NXcg_grid`: + A grid of cells. + + :ref:`NXisocontour`: + A description for isocontour descriptions. + + :ref:`NXcg_marching_cubes`: + An approach to store metadata of a specific implementation of + the Marching Cubes algorithm, whose sensitivity to specific topological + configurations is known to result in different triangle soups. + + :ref:`NXdelocalization`: + An approach to document procedures whereby a scalar field + is smoothened in a controlled manner. + +Assuming that these base classes can serve as building blocks, we would like +to test with the proposal also how these base classes can be applied in base +classes for specific types of microstructural features and/or utility classes +to hold metadata for these features: + + :ref:`NXsimilarity_grouping`: + An alias for NXclustering. + + :ref:`NXclustering`: + A description for clustering of objects (such as atoms or features). + + :ref:`NXorientation_set`: + A set of rotations to describe the relative orientation of members of a set of features/objects. + + :ref:`NXslip_system_set`: + Metadata to a set of slip system/slip system family for + a given crystal structure. + + :ref:`NXms_feature_set`: + Generic base class to describe any nested set of features + of a microstructure at the continuum-, micron-, nano-scale, or + to represent a topology of molecules and atoms. + + :ref:`NXms_snapshot`: + A container to describe the state of microstructural features + at a given point in time. + + :ref:`NXms_snapshot_set`: + The corresponding class to hold a set of :ref:`NXms_snapshot` objects. + + :ref:`NXchemical_composition`: + (Chemical) composition of a sample or a set of things. + +Furthermore, we found that it can be useful to have a set of base classes with +which software documents it state and gives a summary for users about the performance +and elapsed time measured while processing data. These utility classes include: + + :ref:`NXprogram`: + A named and version of a program of library/component of a larger software framework. + + :ref:`NXcs_filter_boolean_mask`: + A boolean mask. + + :ref:`NXcs_prng`: + Metadata of a pseudo-random number generator (PRNG) algorithm. + + :ref:`NXcs_profiling`: + A structuring group holding a set of :ref:`NXcs_profiling_event` instances. + + :ref:`NXcs_profiling_event`: + Profiling/benchmark data to an event of + tracking an algorithm/computational step. + + :ref:`NXcs_computer`: + Metadata of a computer. + + :ref:`NXcs_cpu`: + Metadata of a central processing unit. + + :ref:`NXcs_gpu`: + Metadata of a graphical processing unit / accelerator. + + :ref:`NXcs_mm_sys`: + Metadata of the (main) memory (sub-)system. + + :ref:`NXcs_io_sys`: + Metadata of the input/output system. + + :ref:`NXcs_io_obj`: + Metadata of a component storing data of an :ref:`NXcs_io_sys` instance. + +.. _IcmeMsModels1: + +Application definitions for ICME models +####################################### + +To bridge to our colleagues from the NFDI-MatWerk and NFDI4Ing consortia we +have created an example how the proposed components of the nexus-fairmat-proposal +can be used to create data schemes for vanilla-type ICME microstructure models. +ICME is an abbreviation for Integrated Computational Materials Engineering, which +is a design strategy and workflow whereby physics-based modelling of microstructure +evolution at the mesoscopic scale is used to understand the relations between +the microstructure and technological relevant descriptors for the properties +of materials. + +To begin with we propose the following draft application definitions. + + :ref:`NXms`: + An application definition for arbitrary spatiotemporally resolved simulations. + + :ref:`NXms_score_config`: + A specific example how :ref:`NXapm_paraprobe_config_ranger` can be specialized for documenting the configuration of a computer simulation with the static recrystallization cellular automata model SCORE. + + :ref:`NXms_score_results`: + A specific example how :ref:`NXms` can be specialized for documenting results of computer simulations with the static recrystallization cellular automata model SCORE. diff --git a/manual/source/ellipsometry-structure.rst b/manual/source/ellipsometry-structure.rst new file mode 100644 index 000000000..add5aaaec --- /dev/null +++ b/manual/source/ellipsometry-structure.rst @@ -0,0 +1,157 @@ +.. _Ellipsometry-Structure1: + +======================== +B4: Optical spectroscopy +======================== + +.. index:: + Ellipsometry1 + DispersiveMaterial1 + + +.. _Ellipsometry1: + +Ellipsometry +############## + +Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. The measurements are based on determining how the polarization state of light changes upon transmission and reflection. Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. + +In the application definition we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. + + +Application Definitions +----------------------- + +We created one application definition: + + :ref:`NXellipsometry`: + A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. + + + +Base Classes Extended in Application Definitions +------------------------------------------------ + +We use existent base classes in application definitions and add descriptors: + + :ref:`NXinstrument` + Added fields to add information that is important for an ellipsometry setup, such as the ellipsometer type, the light source, the type of the sample stage, or the angle(s) of incidence, as well as information on calibration, focussing probes, data correction etc. + + :ref:`NXdetector` + Added fields to describe spectroscopic detection with polarization (e.g. rotating analyzer). + + :ref:`NXaperture` + Added fields to define parameters that describe windows (e.g. windows of a UHV cryostat), such as the thickness and the orientation angle of the window, as well as reference data to calculate window effects. + + :ref:`NXsample` + Added fields to specify the sample and material properties, as well as the sample environment (e.g. refractive index of surrounding medium) and experimental conditions (e.g. temperature, pressure, pH value etc.). + +.. _DispersiveMaterial1: + + +Dispersive Material +################### + +A dispersive material is a description for the optical dispersion of materials. +This description may be used to store optical model data from an ellipsometric analysis +(or any other technique) or to build a database of optical constants for optical properties of materials. + +Application Definition +---------------------- + + :ref:`NXdispersive_material`: + An application definition to describe the dispersive properties of a material. + The material may be isotropic, uniaxial or biaxial. Hence, it may contain up + to three dispersive functions or tables. + + + +Base Classes +------------ + +There is a set of base classes for describing a dispersion. + + :ref:`NXdispersion` + This is an umbrella base class for a group of dispersion functions to describe the material. + For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. + If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. + This allows for, e.g. splitting real and imaginary parts and describing them seperately or + adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). + + :ref:`NXdispersion_function` + This dispersion is described by a function and its single and repeated parameter values. + It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` + (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. + + :ref:`NXdispersion_single_parameter` + This denotes a parameter which is used outside the summed part of a dispersion function, + e.g. ``eps_inf`` in the formula example above. + + :ref:`NXdispersion_repeated_parameter` + This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. + ``A`` and ``B`` are repeated parameters in the formula above. + + :ref:`NXdispersion_table` + This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. + +Formula Grammar +--------------- + +Below you find a grammar to which the formula should adhere and which can be used to parse and +evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be +filled with the respective single and repeated params from the stored data. + +.. code-block:: + + ?assignment: "eps" "=" kkr_expression -> eps + | "n" "=" kkr_expression -> n + + ?kkr_expression: expression + | "" "+" "1j" "*" term -> kkr_term + + ?expression: term + | expression "+" term -> add + | expression "-" term -> sub + + ?term: factor + | term "*" factor -> mul + | term "/" factor -> div + + ?factor: power + | power "**" power -> power + + + ?power: "(" expression ")" + | FUNC "(" expression ")" -> func + | "sum" "[" repeated_expression "]" -> sum_expr + | NAME -> single_param_name + | SIGNED_NUMBER -> number + | BUILTIN -> builtin + + ?repeated_expression: repeated_term + | repeated_expression "+" repeated_term -> add + | repeated_expression "-" repeated_term -> sub + + + ?repeated_term: repeated_factor + | repeated_term "*" repeated_factor -> mul + | repeated_term "/" repeated_factor -> div + + ?repeated_factor: repeated_power + | repeated_power "**" repeated_power -> power + + ?repeated_power: "(" repeated_expression ")" + | FUNC "(" repeated_expression ")" -> func + | SIGNED_NUMBER -> number + | NAME -> param_name + | BUILTIN -> builtin + + FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" + BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" + + %import common.CNAME -> NAME + %import common.SIGNED_NUMBER + %import common.WS_INLINE + + %ignore WS_INLINE + diff --git a/manual/source/em-structure.rst b/manual/source/em-structure.rst new file mode 100644 index 000000000..3a4b41d25 --- /dev/null +++ b/manual/source/em-structure.rst @@ -0,0 +1,151 @@ +.. _Em-Structure1: + +======================= +B1: Electron microscopy +======================= + +.. index:: + IntroductionEm1 + EmAppDef1 + EmBC1 + EmCommonBC1 + EmPartnerClasses1 + EmDeprecated1 + + + +.. _IntroductionEm1: + +Introduction +############ + +Set of data storage objects to describe components of an electron microscope and its eventually available focused-ion beam functionalities. The data storage objects were designed from the perspective of how electron microscopes are used by colleagues in the materials-science-branch of electron microscopy. We realize that the biology-/bio-materials/omics-branch of electron microscopy is eventually in an already more mature state of discussion with respect to data management practices. Realizing that we need to start somewhere, though, we focus for now on the condensed-matter physics, chemical physics of solids, and materials science applications of electron microscopy. As many of the components of electron microscopes used in the bio-materials communities are the same or at least many components very similar to those used and described in materials science, we are confident that the here presented schema definitions can also inspire discussion and exchange with the bio-materials community in the future. Partner consortia in the German National Research Data Infrastructure are here NFDI-Microbiota, NFDI4Health, and e.g. NFDI-Neuro. + +Electron microscopes are functionally very customizable tools: Examples include multi-signal/-modal analyses which are frequently realized as on-the-fly computational analyses, regularly switching between GUI-based instrument control, computational steps, and more and more using high-throughput stream-based processing. Also artificial intelligence methods get increasingly used and become closer interconnected with classical modes of controlling the instrument and perform data processing. A challenge in electron microscopy is that these steps are often executed within commercial integrated control and analysis software. This makes it additionally difficult to keep track of workflows and challenging to identify which specific quantities in the control software mean and represent in technical detail which physical quantity (and how these +quantities can be connected to the development of ontologies for electron microscopy experiments). + +.. _EmAppDef1: + +Application Definitions +####################### + +We acknowledge that it can be difficult to agree on a single application definition which is generally enough applicable yet remains easy enough and useful across a variety of instruments, technology partners, and instrument use cases. Therefore, we conceptualized first the basic components of an electron microscope and the usual workflow how an electron microscope is used. That is scientists place a specimen/sample into the microscope, calibrate the instrument, take measurements, may perform experiments or prepare their specimens with a focused ion beam, calibrate again, and take other measurements, before their session on the instrument ends. In between virtually all these steps data are collected and stream in from different detectors probing different physical mechanisms of the interaction between electrons or other types of radiation with the specimen. The session ends with the scientist removing +the specimen from the instrument or parking it so that the next user can start a session. Occasionally, service technicians perform calibrations and maintenance which also can be described as session on the microscope. Next, we wrote base classes to describe these steps and events. + + :ref:`NXem`: + A general application definition which explores the possibilities of electron microscopes. + +.. _EmBC1: + +Base Classes +############ + +We developed entirely new base classes. Some of them are also used for other techniques of this proposal but mentioned here for the sake of completeness: + + + :ref:`NXaberration_model`, :ref:`NXaberration_model_ceos`, :ref:`NXaberration_model_nion`, :ref:`NXaberration`: + Base classes to describe procedures and values for the calibration of aberrations based on either CEOS or Nion. + + :ref:`NXaperture_em`: + A base class to describe an aperture. + + :ref:`NXchamber`: + A base class to describe the chamber as a part of the microscope or storage unit for transferring specimens in-between or within an instrument. + + :ref:`NXcoordinate_system_set`: + A base class to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. + + :ref:`NXcorrector_cs`: + A base class to describe details about corrective lens or compound lens devices which reduce the aberration of an electron beam. + + :ref:`NXebeam_column`: + A base class serving the possibility to group the components relevant for generating and shaping the electron beam in an electron microscope. + + :ref:`NXevent_data_em`: + A base class representing a container to hold time-stamped and microscope-state-annotated data during a session at an electron microscope. + + :ref:`NXevent_data_em_set`: + A base class to group all :ref:`NXevent_data_em` instances. + + :ref:`NXibeam_column`: + A base class serving the possibility to group the components relevant for generating and shaping an ion beam of an instrument to offer focused ion beam (milling) capabilities. + + :ref:`NXimage_set`: + Base classes for storing acquisition details for individual images or stacks of images. Specialized versions can be defined and use controlled vocabulary terms for group name prefixes like **adf** annular dark field, **bf** bright field, **bse** backscattered electron, **chamber** camera to monitor the stage and chamber, **df** darkfield, **diffrac** diffraction, **ecci** electron channeling contrast imaging, **kikuchi** electron backscatter diffraction, **ronchigram** - convergent beam diffraction pattern, or **se** secondary electron. + + :ref:`NXinteraction_vol_em`: + A base class to describe details about e.g. the simulated or known volume of interaction of the electrons with the specimen, especially in scanning electron microscopy. + + :ref:`NXion`: + A base class to describe charged molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with which all possible isotopes can be described. + + :ref:`NXlens_em`: + A base class to detail an electro-magnetic lens. In practice, an electron microscope has many such lenses. It is possible to specify as many lenses as necessary to represent eventually each single lens of the microscope and thus describe how the lenses are affecting the electron beam. This can offer opportunities for developers of software tools which strive to model the instrument e.g. to create digital twins of the instrument. We understand there is still a way to go with this to arrive there though. Consequently, we suggest to focus first on which details should be collected for a lens as a component so that developers of application definitions can take immediate advantage of this work. + + :ref:`NXfabrication`: + A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. + + :ref:`NXoptical_system_em`: + A base class to store for now qualitative and quantitative values of frequent interest which are affected by the interplay of the components and state of an electron microscope. + Examples are the semiconvergence angle or the depth of field and depth of focus, the magnification, or the camera length. + + :ref:`NXpeak`: + A base class to describe peaks mathematically so that it can be used to detail how peaks in mass-to-charge-state ratio histograms (aka mass spectra) are defined and labelled as iontypes. + + :ref:`NXpump`: + A base class to describe details about a pump in an instrument. + + :ref:`NXscanbox_em`: + A base class to represent the component of an electron microscope which realizes a controlled deflection (and eventually shift, blanking, and/or descanning) of the electron beam to illuminate the specimen in a controlled manner. This can be used to document the scan pattern. + + :ref:`NXspectrum_set`: + Base class and specializations comparable to NXimage_set but for storing spectra. Specialized base classes should use controlled vocabulary items as prefixes such as **eels** electron energy loss spectroscopy, **xray** X-ray spectroscopy (EDS/STEM, EDX, SEM/EDX, SEM/EDS), **auger** Auger spectroscopy, or **cathodolum** for cathodoluminescence spectra. + + :ref:`NXstage_lab`: + As it was mentioned for atom probe microscopy, this is a base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities which modern stages of electron microscopes frequently offer. + + :ref:`NXcircuit_board`:, :ref:`NXadc`, and :ref:`NXdac`: + Base classes to describe electronic components of an electron microscope. These base classes need still to be harmonized with those used in the field of low-temperature scanning probe microscopy. + +.. _EmCommonBC1: + +Common Base Classes +################### + +We support the proposal of our colleagues from photoemission spectroscopy that the :ref:`NXlens_em` and :ref:`NXxraylens` have similarities. +It should be discussed with the NIAC if these classes can be consolidated/harmonized further e.g. eventually become a child class of a more general +base class lenses. We understand also that the proposed set of NXimage_set_em base classes can benefit from future discussion and consolidation efforts. + +The first result of such consolidations is the NXem_ebsd partner application definition. + +.. _EmPartnerClasses1: + +Partner application definitions +############################### + +A partner application definition is considered an application definition which stores data and metadata which are relevant for a given experiment but have usually only few connections to the detailed description of the workflow and experiment which motivates to granularize these pieces of information in an own application definition. In fact, one limitation of application definitions in NeXus is that they define a set of constraints on their graph of controlled concepts and terms. If we take for example diffraction experiments with an electron microscope it is usually the case that the pattern are collected in the session at the microscope but all scientifically relevant conclusions are drawn later, i.e. in post-processing of these data. These numerical and algorithmic steps define computational workflows were data from the application definitions such as NXem are used as input but many additional concepts and constraints may apply without any need for changing constraints on fields or groups of NXem. If we were to modify NXem for these cases, NXem would likely combinatorially diverge as every different combination of required constraints trigger the need for having an own but almost similar application definition. For this reason we use the concept of partner application definition which have fields/links where specifically relevant sources of information are connected to e.g. NXem. + +The first partner application definition is NXem_ebsd. + + :ref:`NXem_ebsd`: + Application definition for collecting and indexing Kikuchi pattern into orientation maps for the two-dimensional, three- and four-dimensional case. + +Several new base classes are used by this application definition. + + :ref:`NXem_ebsd_conventions`: + A collection of reference frames and rotation conventions necessary to interpret the alignment and orientation data. + + :ref:`NXem_ebsd_crystal_structure_model`: + A description of a crystalline phase/structure used for a forward simulation using kinetic or dynamic diffraction theory to generate simulated diffraction pattern against which measured pattern can be indexed. + + +.. _EmDeprecated1: + +Deprecated +########## + +In April/May 2023, we refactored the design of the NXimage_set and NXspectrum set base classes. Therefore, the following base classes should not longer be used: +NXimage_set_em_bf, NXimage_set_em_bse, NXimage_set_em_chamber, NXimage_set_em_df, NXimage_set_em_diffrac, NXimage_set_em_ecci, NXimage_set_em_kikuchi, NXimage_set_em_ronchigram, NXimage_set_em_se, NXimage_set_em, NXspectrum_set_em_eels, NXspectrum_set_em_xray, NXspectrum_set_em_auger, NXspectrum_set_em_cathodolum. + +With the NeXus 2022.06 Code Camp, we refactored the NXem application definition. Therefore, the following base classes and application definitions should no longer be used: +NXem_nion (replaced by :ref:`NXem`), NXfib (replaced by :ref:`NXibeam_column`). diff --git a/manual/source/index.rst b/manual/source/index.rst index 25f293f57..ca2de5522 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -7,7 +7,8 @@ Welcome to the user manual of the NeXus for FAIRmat project. https://www.nexusformat.org/ .. toctree:: - :maxdepth: 2 + :maxdepth: 5 + :numbered: 5 fairmat-cover nexus-index @@ -20,6 +21,9 @@ https://www.nexusformat.org/ cgms-structure laboratory-structure north-structure + napi + history + diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index 9755e8b2c..eb45358f7 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -1,18 +1,18 @@ -.. _Mpes-Structure: +.. _Mpes-Structure1: ============================================== B2/B3: Photoemission & core-level spectroscopy ============================================== .. index:: - IntroductionMpes - MpesAppDef - MpesBC - MpesCommonBC - MpesExtendedBC + IntroductionMpes1 + MpesAppDef1 + MpesBC1 + MpesCommonBC1 + MpesExtendedBC1 -.. _IntroductionMpes: +.. _IntroductionMpes1: Introduction ############ @@ -22,7 +22,7 @@ hard x-ray photoelectron spectroscopy (HAXPES), angle-resolved photoemission spe and photoemission electron microscopy (PEEM). We also included descriptors for advanced specializations, such as spin-resolution, time resolution, near-ambient pressure conditions, dichroism etc. -.. _MpesAppDef: +.. _MpesAppDef1: Application Definitions ####################### @@ -32,7 +32,7 @@ We created two new application definitions: :ref:`NXmpes`: A general appdef with minimalistic metadata requirements, apt to describe all photemission experiments. -.. _MpesBC: +.. _MpesBC1: Base Classes ############ @@ -66,7 +66,7 @@ We developed three base classes to describe data processing, which can be used a :ref:`NXregistration`: A base class to describe the rigid transformations that are applied to an image. May be redundant as they can be described with :ref:`NXtransformations`. -.. _MpesCommonBC: +.. _MpesCommonBC1: Common Base Classes ################### @@ -79,7 +79,7 @@ We developed two classes that are common to other techniques: :ref:`NXdeflector` A class to describe all kinds of deflectors, including electrostatic and magnetostatic deflectors for electron energy analysers. -.. _MpesExtendedBC: +.. _MpesExtendedBC1: Base Classes Extended in Application Definitions ################################################ diff --git a/manual/source/north-structure.rst b/manual/source/north-structure.rst new file mode 100644 index 000000000..2198f3f86 --- /dev/null +++ b/manual/source/north-structure.rst @@ -0,0 +1,264 @@ +.. _North-Structure1: + +====================== +Nomad Remote Tools Hub +====================== + + +.. index:: + IntroductionApmParaprobe1 + WhatHasBeenAchieved1 + ApmParaprobeAppDef1 + ApmParaprobeNewBC1 + NextStep1 + + +.. _IntroductionApmParaprobe1: + +Introduction +############## + +NORTH (the NOMAD Oasis Remote Tools Hub) is a NOMAD Oasis service which makes +preconfigured scientific software of different communities available and coupled +to Oasis and accessible via the webbrowser. This part of the proposal documents +examples for specific NeXus-related work to some of the tools and containers +available in NORTH. + + +apmtools +######## + +One tool is the paraprobe-toolbox software package in the the apmtools container. +The software is developed by `M. Kühbach et al. `_. + +Here we show how NeXus is used to consistently define application definitions +for scientific software in the field of atom probe. In this community the paraprobe-toolbox is an example of an open-source parallelized +software for analyzing point cloud data, for assessing meshes in 3D continuum +space, and analyzing the effects of parameterization on descriptors +about the microstructure of materials which were studied with atom probe microscopy. + +The need for a thorough documentation of the tools in not only the paraprobe-toolbox was motivated by several needs: + +First, users of software would like to better understand and also be able to +study themselves which individual parameter and settings for each tool exist +and how configuring these affects their analyses quantitatively. + +Second, scientific software like the tools in the paraprobe-toolbox implement a +numerical/algorithmical (computational) workflow whereby data from multiple input sources +(like previous analysis results) are processed and carried through more involved analysis +within several steps inside the tool. The tool then creates output as files. + +Individual tools are developed in C/C++ and/or Python. Here, having a possibility +for provenance tracking is useful as it is one component and requirement for +making workflows exactly numerically reproducible and thus to empower scientists +to fullfill better the "R", i.e. reproducibility of daily FAIR research practices. + +The paraprobe-toolbox is one example of a software which implements a workflow +via a sequence of operations executed within a jupyter notebook +(or Python script respectively). Specifically, individual tools are chained. +Convenience functions are available to create well-defined input/configuration +files for each tool. These config files instruct the tool upon processing. + +In this design, each workflow step (with a tool) is in fact a pair (or triple) of +at least two sub-steps: i) the creation of a configuration file, +ii) the actual analysis using the Python/or C/C++ tools, +iii) the optional post-processing/visualizing of the results inside the NeXus/HDF5 +files generated from each tool run using other software. + + +.. _WhatHasBeenAchieved1: + +What has been achieved so far? +############################## + +This proposal summarizes both of the steps which we worked on between Q3/2022-Q1/2023 to change the interface and +file interaction in all tools of the paraprobe-toolbox to accept exclusively +well-defined configuration files and yield exclusively specific output. + +Data and metadata between the tools are exchanged with NeXus/HDF5 files. +Specifically, we created for each tool an application definition (see below) +which details all possible settings and options for the configuration as to +guide users. The config(uration) files are HDF5 files, whose content matches +to the naming conventions of the respective `config` application definition for each tool. +As an example NXapm_paraprobe_config_surfacer specifies how a configuration file +for the paraprobe-surfacer tool should be formatted and which parameter it contains. + +That is each config file uses a controlled vocabulary of terms. Furthermore, +the config files store a SHA256 checksum for each input file. +This implements a full provenance tracking on the input files along the +processing chain/workflow. + +As an example, a user may first range their reconstruction and then compute +correlation functions. The config file for the ranging tool stores the files +which hold the reconstructed ion position and ranging definitions. +The ranging tool generates a results file with the ion type labels stored. +This results file is formatted according to the tool-specific `results` +application definition. This results file and the reconstruction is +imported by the spatial statistics tool which again keeps track of all files. + +This design makes it possible to rigorously trace which numerical results +were achieved with a specific chain of input and +settings using specifically-versioned tools. + +We understand that this additional handling of metadata and provenance tracking +may not be at first glance super relevant for scientists or appears to be an +unnecessarily complex feature. There is indeed an additional layer of work which +came with the development and maintenance of this functionality. + +However, we are convinced that this is the preferred way of performing software +development and data analyses as it enables users to take advantage of a completely +automated provenance tracking which happens silently in the background. + +.. _ApmParaprobeAppDef1: + +Application Definitions +####################### + +Firstly, we define application definitions for the input side (configuration) of each tool. + + :ref:`NXapm_paraprobe_config_transcoder`: + Configuration of paraprobe-transcoder + Load POS, ePOS, APSuite APT, RRNG, RNG, and NXapm HDF5 files. + + :ref:`NXapm_paraprobe_config_ranger`: + Configuration of paraprobe-ranger + Apply ranging definitions and explore possible molecular ions. + + :ref:`NXapm_paraprobe_config_selector`: + Configuration of paraprobe-selector + Defining complex spatial regions-of-interest to filter reconstructed datasets. + + :ref:`NXapm_paraprobe_config_surfacer`: + Configuration of paraprobe-surfacer + Create a model for the edge of a point cloud via convex hulls, alpha shapes. + + :ref:`NXapm_paraprobe_config_distancer`: + Configuration of paraprobe-distancer + Compute analytical distances between ions to a set of triangles. + + :ref:`NXapm_paraprobe_config_tessellator`: + Configuration of paraprobe-tessellator + Compute Voronoi cells for if desired all ions in a dataset. + + :ref:`NXapm_paraprobe_config_nanochem`: + Configuration of paraprobe-nanochem + Compute delocalization, iso-surfaces, analyze 3D objects, and composition profiles. + + :ref:`NXapm_paraprobe_config_intersector`: + Configuration of paraprobe-intersector + Assess intersections and proximity of 3D triangulated surface meshes in + continuum space to study the effect the parameterization of surface + extraction algorithms on the resulting shape, spatial arrangement, + and colocation of 3D objects via graph-based techniques. + + :ref:`NXapm_paraprobe_config_spatstat`: + Configuration of paraprobe-spatstat + Spatial statistics on the entire or selected regions of the reconstructed dataset. + + :ref:`NXapm_paraprobe_config_clusterer`: + Configuration of paraprobe-clusterer + Import cluster analysis results of IVAS/APSuite and perform clustering + analyses in a Python ecosystem. + +Secondly, we define application definitions for the output side (results) of each tool. + + :ref:`NXapm_paraprobe_results_transcoder`: + Results of paraprobe-transcoder + Store reconstructed positions, ions, and charge states. + + :ref:`NXapm_paraprobe_results_ranger`: + Results of paraprobe-ranger + Store applied ranging definitions and combinatorial analyses of all possible iontypes. + + :ref:`NXapm_paraprobe_results_selector`: + Results of paraprobe-selector + Store which points are inside or on the boundary of complex spatial regions-of-interest. + + :ref:`NXapm_paraprobe_results_surfacer`: + Results of paraprobe-surfacer + Store triangulated surface meshes of models for the edge of a dataset. + + :ref:`NXapm_paraprobe_results_distancer`: + Results of paraprobe-distancer + Store analytical distances between ions to a set of triangles. + + :ref:`NXapm_paraprobe_results_tessellator`: + Results of paraprobe-tessellator + Store volume of all Voronoi cells about each ion in the dataset. + + :ref:`NXapm_paraprobe_results_nanochem`: + Results of paraprobe-nanochem + Store all results of delocalization, isosurface, and interface detection algorithms, + store all extracted triangulated surface meshes of found microstructural features, + store composition profiles and corresponding geometric primitives (ROIs). + + :ref:`NXapm_paraprobe_results_intersector`: + Results of paraprobe-intersector + Store graph of microstructural features and relations/link identified between them. + + :ref:`NXapm_paraprobe_results_spatstat`: + Results of paraprobe-spatstat + Store spatial correlation functions. + + :ref:`NXapm_paraprobe_results_clusterer`: + Results of paraprobe-clusterer + Store results of cluster analyses. + +.. _ApmParaprobeNewBC1: + +Base Classes +############ + +We envision that the above-mentioned definitions can be useful not only to take +inspiration for other software tools in the field of atom probe but also to support +a discussion towards a stronger standardization of the vocabulary used. +Therefore, we are happy for your comments and suggestions on this and the related +pages via the hypothesis web annotation service or as your issues posted on GitHub. + +We are convinced that the majority of data analyses in atom probe use +an in fact common set of operations and conditions on the input data +even though this might not be immediately evident. In particular this is not +the case for some community built tools with a very specific scope where oftentimes +the algorithms are hardcoded for specific material systems. A typical example is a +reseacher who implements a ranging tool and uses that all the examples are on a +specific material. We are convinced it is better to follow a much more generalized approach. + +In this spirit, we propose the following base classes and the above application +definitions as examples how very flexible constraints can be implemented which +restrict which ions in the dataset should be processed or not. We see that these +suggestions complement the proposal on computational geometry base classes: + + :ref:`NXapm_input_reconstruction`: + A description from which file the reconstructed ion positions are imported. + + :ref:`NXapm_input_ranging`: + A description from which file the ranging definitions are imported. + The design of the ranging definitions is, thanks to :ref:`NXion` so + general that all possible nuclids can be considered, be they observationally stable, + be they radioactive or transuranium nuclids. + +A detailed inspection of spatial and other type of filters used in atom probe microscopy +data analysis revealed that it is better to define atom probe agnostic, i.e. more +general filters: + + :ref:`NXspatial_filter`: + A proposal how a point cloud can be spatial filtered in a very specific, + flexible, yet general manner. This base class takes advantage of + :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, and :ref:`NXcg_hexahedron_set` + to cater for all of the most commonly used geometric primitives in + atom probe. + + :ref:`NXsubsampling_filter`: + A proposal for a filter that can also be used for specifying how entries + like ions can be filtered via sub-sampling. + + :ref:`NXmatch_filter`: + A proposal for a filter that can also be used for specifying how entries + like ions can be filtered based on their type (ion species) + or hit multiplicity. + +In summary, we report with this proposal our experience made in an experimental +project that is about using NeXus for standardizing a set of non-trivial scientific software tools. +During the implementation we learned that for handling computational geometry +and microstructure-related terms many subtilities have to be considered which +makes a controlled vocabulary valuable not only to avoid a reimplementing of the wheel. diff --git a/manual/source/transport-structure.rst b/manual/source/transport-structure.rst new file mode 100644 index 000000000..304a4f0e2 --- /dev/null +++ b/manual/source/transport-structure.rst @@ -0,0 +1,26 @@ +.. _Transport-Structure1: + +=================== +Transport Phenomena +=================== + +.. index:: + IntroductionTransport1 + TransportAppDef1 + + +.. _IntroductionTransport1: + +Introduction +############## + + +.. _TransportAppDef1: + +Application Definitions +####################### + +Work on handshaking between EPICS-controlled experiments and NeXus resulted in one application definition for temperature dependent IV curve measurements. + + :ref:`NXiv_temp`: + Application definition for temperature dependent IV curve measurements. From 154fea997dd802152fe2120a2825ecd72b8a53f6 Mon Sep 17 00:00:00 2001 From: Sandor Brockhauser Date: Thu, 20 Jul 2023 12:22:37 +0200 Subject: [PATCH 004/136] make TOC not too deep --- manual/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/source/index.rst b/manual/source/index.rst index ca2de5522..412a30dd0 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -7,7 +7,7 @@ Welcome to the user manual of the NeXus for FAIRmat project. https://www.nexusformat.org/ .. toctree:: - :maxdepth: 5 + :maxdepth: 2 :numbered: 5 fairmat-cover From 01e381a982e7e3321e2a7c125fb6a6fc52fb978a Mon Sep 17 00:00:00 2001 From: domna Date: Mon, 24 Jul 2023 09:09:11 +0200 Subject: [PATCH 005/136] Removes base classes from appdef overview pages --- manual/source/apm-structure.rst | 63 ------------ manual/source/ellipsometry-structure.rst | 21 ---- manual/source/em-structure.rst | 119 ----------------------- manual/source/mpes-structure.rst | 82 ---------------- 4 files changed, 285 deletions(-) diff --git a/manual/source/apm-structure.rst b/manual/source/apm-structure.rst index 01be214ac..d7e94f6af 100644 --- a/manual/source/apm-structure.rst +++ b/manual/source/apm-structure.rst @@ -7,9 +7,6 @@ B5: Atom-probe tomography .. index:: IntroductionApm1 ApmAppDef1 - ApmBC1 - ApmRemovedBC1 - ApmFurtherDefs1 .. _IntroductionApm1: @@ -28,63 +25,3 @@ We created one new application definition whose intention is to serve both the d :ref:`NXapm`: A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes (ranging). - -.. _ApmBC1: - -Base Classes -############ - -We developed new base classes to structure the application definition into lab experiment and computational steps: - - :ref:`NXchamber`: - A base class to describe a component of the instrument which houses other components. A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. - - :ref:`NXcoordinate_system_set` - A base class to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. - - :ref:`NXion`: - A base class to describe charged molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with which all possible isotopes can be described. - - :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - - :ref:`NXpeak`: - A base class to describe peaks mathematically so that it can be used to detail how peaks in mass-to-charge-state ratio histograms (aka mass spectra) are defined and labelled as iontypes. - - :ref:`NXpump`: - A base class to describe details about a pump in an instrument. - - :ref:`NXpulser_apm`: - A base class to describe the high-voltage and/or laser pulsing capabilities of an atom probe microscope. - - :ref:`NXreflectron`: - A base class to describe a kinetic-energy-sensitive filtering device for time of flight (ToF). - - :ref:`NXstage_lab`: - A base class to describe the specimen fixture including the cryo-head. This base class is an example that the so far used :ref:`NXstage_lab` base class is insufficiently detailed to represent the functionalities which modern stages of an - atom probe microscope or especially an electron microscope offer. Nowadays, these stages represent small-scale laboratory platforms. Hence, there is a need to define their characteristics in more detail, especially in light of in-situ experiments. We see many similarities between a stage in an electron microscope and one in an atom probe instrument, given that both offer fixture functionalities and additional components for applying e.g. stimuli on the specimen. For this reason, we use this base class currently for atom probe and electron microscopy. - -Microscopy experiments, not only taking into account those performed on commercial instruments, offer the user usually -a set of frequently on-the-fly processed computational data. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. - -.. _ApmRemovedBC1: - -.. Removed base classes -.. #################### - -.. _ApmFurtherDefs1: - -Further data schemas for atom probe -################################### - -We have also developed a collection of application definition which exemplify how data post-processing workflows -with typical steps specific for atom probe and reconstruction of microstructural features can be described with NeXus. -These application definitions and base classes have an own section in the proposal which you can find on the landing -page by inspection the section on computational geometry and microstructures. - -Furthermore, we are working with the NFDI-MatWerk consortium to explore how tools from the FAIRmat and the NFDI-MatWerk -consortium can be used to describe research, data, metadata, and workflows. This work is organized in the infrastructure -use case IUC09 within the NFDI-MatWerk project. One example how NeXus could be used to describe processing of -atom probe data with a tool which was developed by Alaukik Saxena et al. at the Max-Planck-Institut für Eisenforschung GmbH -in Düsseldorf is available as the so-called :ref:`NXapm_composition_space_results` application definition. - diff --git a/manual/source/ellipsometry-structure.rst b/manual/source/ellipsometry-structure.rst index add5aaaec..c801f341f 100644 --- a/manual/source/ellipsometry-structure.rst +++ b/manual/source/ellipsometry-structure.rst @@ -28,27 +28,6 @@ We created one application definition: A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - -Base Classes Extended in Application Definitions ------------------------------------------------- - -We use existent base classes in application definitions and add descriptors: - - :ref:`NXinstrument` - Added fields to add information that is important for an ellipsometry setup, such as the ellipsometer type, the light source, the type of the sample stage, or the angle(s) of incidence, as well as information on calibration, focussing probes, data correction etc. - - :ref:`NXdetector` - Added fields to describe spectroscopic detection with polarization (e.g. rotating analyzer). - - :ref:`NXaperture` - Added fields to define parameters that describe windows (e.g. windows of a UHV cryostat), such as the thickness and the orientation angle of the window, as well as reference data to calculate window effects. - - :ref:`NXsample` - Added fields to specify the sample and material properties, as well as the sample environment (e.g. refractive index of surrounding medium) and experimental conditions (e.g. temperature, pressure, pH value etc.). - -.. _DispersiveMaterial1: - - Dispersive Material ################### diff --git a/manual/source/em-structure.rst b/manual/source/em-structure.rst index 3a4b41d25..40965d1cf 100644 --- a/manual/source/em-structure.rst +++ b/manual/source/em-structure.rst @@ -7,11 +7,6 @@ B1: Electron microscopy .. index:: IntroductionEm1 EmAppDef1 - EmBC1 - EmCommonBC1 - EmPartnerClasses1 - EmDeprecated1 - .. _IntroductionEm1: @@ -35,117 +30,3 @@ the specimen from the instrument or parking it so that the next user can start a :ref:`NXem`: A general application definition which explores the possibilities of electron microscopes. -.. _EmBC1: - -Base Classes -############ - -We developed entirely new base classes. Some of them are also used for other techniques of this proposal but mentioned here for the sake of completeness: - - - :ref:`NXaberration_model`, :ref:`NXaberration_model_ceos`, :ref:`NXaberration_model_nion`, :ref:`NXaberration`: - Base classes to describe procedures and values for the calibration of aberrations based on either CEOS or Nion. - - :ref:`NXaperture_em`: - A base class to describe an aperture. - - :ref:`NXchamber`: - A base class to describe the chamber as a part of the microscope or storage unit for transferring specimens in-between or within an instrument. - - :ref:`NXcoordinate_system_set`: - A base class to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. - - :ref:`NXcorrector_cs`: - A base class to describe details about corrective lens or compound lens devices which reduce the aberration of an electron beam. - - :ref:`NXebeam_column`: - A base class serving the possibility to group the components relevant for generating and shaping the electron beam in an electron microscope. - - :ref:`NXevent_data_em`: - A base class representing a container to hold time-stamped and microscope-state-annotated data during a session at an electron microscope. - - :ref:`NXevent_data_em_set`: - A base class to group all :ref:`NXevent_data_em` instances. - - :ref:`NXibeam_column`: - A base class serving the possibility to group the components relevant for generating and shaping an ion beam of an instrument to offer focused ion beam (milling) capabilities. - - :ref:`NXimage_set`: - Base classes for storing acquisition details for individual images or stacks of images. Specialized versions can be defined and use controlled vocabulary terms for group name prefixes like **adf** annular dark field, **bf** bright field, **bse** backscattered electron, **chamber** camera to monitor the stage and chamber, **df** darkfield, **diffrac** diffraction, **ecci** electron channeling contrast imaging, **kikuchi** electron backscatter diffraction, **ronchigram** - convergent beam diffraction pattern, or **se** secondary electron. - - :ref:`NXinteraction_vol_em`: - A base class to describe details about e.g. the simulated or known volume of interaction of the electrons with the specimen, especially in scanning electron microscopy. - - :ref:`NXion`: - A base class to describe charged molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with which all possible isotopes can be described. - - :ref:`NXlens_em`: - A base class to detail an electro-magnetic lens. In practice, an electron microscope has many such lenses. It is possible to specify as many lenses as necessary to represent eventually each single lens of the microscope and thus describe how the lenses are affecting the electron beam. This can offer opportunities for developers of software tools which strive to model the instrument e.g. to create digital twins of the instrument. We understand there is still a way to go with this to arrive there though. Consequently, we suggest to focus first on which details should be collected for a lens as a component so that developers of application definitions can take immediate advantage of this work. - - :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - - :ref:`NXoptical_system_em`: - A base class to store for now qualitative and quantitative values of frequent interest which are affected by the interplay of the components and state of an electron microscope. - Examples are the semiconvergence angle or the depth of field and depth of focus, the magnification, or the camera length. - - :ref:`NXpeak`: - A base class to describe peaks mathematically so that it can be used to detail how peaks in mass-to-charge-state ratio histograms (aka mass spectra) are defined and labelled as iontypes. - - :ref:`NXpump`: - A base class to describe details about a pump in an instrument. - - :ref:`NXscanbox_em`: - A base class to represent the component of an electron microscope which realizes a controlled deflection (and eventually shift, blanking, and/or descanning) of the electron beam to illuminate the specimen in a controlled manner. This can be used to document the scan pattern. - - :ref:`NXspectrum_set`: - Base class and specializations comparable to NXimage_set but for storing spectra. Specialized base classes should use controlled vocabulary items as prefixes such as **eels** electron energy loss spectroscopy, **xray** X-ray spectroscopy (EDS/STEM, EDX, SEM/EDX, SEM/EDS), **auger** Auger spectroscopy, or **cathodolum** for cathodoluminescence spectra. - - :ref:`NXstage_lab`: - As it was mentioned for atom probe microscopy, this is a base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities which modern stages of electron microscopes frequently offer. - - :ref:`NXcircuit_board`:, :ref:`NXadc`, and :ref:`NXdac`: - Base classes to describe electronic components of an electron microscope. These base classes need still to be harmonized with those used in the field of low-temperature scanning probe microscopy. - -.. _EmCommonBC1: - -Common Base Classes -################### - -We support the proposal of our colleagues from photoemission spectroscopy that the :ref:`NXlens_em` and :ref:`NXxraylens` have similarities. -It should be discussed with the NIAC if these classes can be consolidated/harmonized further e.g. eventually become a child class of a more general -base class lenses. We understand also that the proposed set of NXimage_set_em base classes can benefit from future discussion and consolidation efforts. - -The first result of such consolidations is the NXem_ebsd partner application definition. - -.. _EmPartnerClasses1: - -Partner application definitions -############################### - -A partner application definition is considered an application definition which stores data and metadata which are relevant for a given experiment but have usually only few connections to the detailed description of the workflow and experiment which motivates to granularize these pieces of information in an own application definition. In fact, one limitation of application definitions in NeXus is that they define a set of constraints on their graph of controlled concepts and terms. If we take for example diffraction experiments with an electron microscope it is usually the case that the pattern are collected in the session at the microscope but all scientifically relevant conclusions are drawn later, i.e. in post-processing of these data. These numerical and algorithmic steps define computational workflows were data from the application definitions such as NXem are used as input but many additional concepts and constraints may apply without any need for changing constraints on fields or groups of NXem. If we were to modify NXem for these cases, NXem would likely combinatorially diverge as every different combination of required constraints trigger the need for having an own but almost similar application definition. For this reason we use the concept of partner application definition which have fields/links where specifically relevant sources of information are connected to e.g. NXem. - -The first partner application definition is NXem_ebsd. - - :ref:`NXem_ebsd`: - Application definition for collecting and indexing Kikuchi pattern into orientation maps for the two-dimensional, three- and four-dimensional case. - -Several new base classes are used by this application definition. - - :ref:`NXem_ebsd_conventions`: - A collection of reference frames and rotation conventions necessary to interpret the alignment and orientation data. - - :ref:`NXem_ebsd_crystal_structure_model`: - A description of a crystalline phase/structure used for a forward simulation using kinetic or dynamic diffraction theory to generate simulated diffraction pattern against which measured pattern can be indexed. - - -.. _EmDeprecated1: - -Deprecated -########## - -In April/May 2023, we refactored the design of the NXimage_set and NXspectrum set base classes. Therefore, the following base classes should not longer be used: -NXimage_set_em_bf, NXimage_set_em_bse, NXimage_set_em_chamber, NXimage_set_em_df, NXimage_set_em_diffrac, NXimage_set_em_ecci, NXimage_set_em_kikuchi, NXimage_set_em_ronchigram, NXimage_set_em_se, NXimage_set_em, NXspectrum_set_em_eels, NXspectrum_set_em_xray, NXspectrum_set_em_auger, NXspectrum_set_em_cathodolum. - -With the NeXus 2022.06 Code Camp, we refactored the NXem application definition. Therefore, the following base classes and application definitions should no longer be used: -NXem_nion (replaced by :ref:`NXem`), NXfib (replaced by :ref:`NXibeam_column`). diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index eb45358f7..cae1c026b 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -7,10 +7,6 @@ B2/B3: Photoemission & core-level spectroscopy .. index:: IntroductionMpes1 MpesAppDef1 - MpesBC1 - MpesCommonBC1 - MpesExtendedBC1 - .. _IntroductionMpes1: @@ -31,81 +27,3 @@ We created two new application definitions: :ref:`NXmpes`: A general appdef with minimalistic metadata requirements, apt to describe all photemission experiments. - -.. _MpesBC1: - -Base Classes -############ - -We developed entirely new base classes: - - :ref:`NXelectronanalyser`: - A base class to describe electron kinetic energy analizers. Contains the collective characteristics of the instrument such as energy resolution, and includes the following subclasses: - - :ref:`NXcollectioncolumn`: - Base class to describe the set of electronic lenses in the electron collection column (standard, PEEM, momentum-microscope, etc.). - - :ref:`NXenergydispersion`: - Base class to describe the energy dispersion sytem (hemispherical, time-of-flight, etc.). - - :ref:`NXspindispersion`: - Base class to describe the set of electronic lenses in the electron collection column. - - :ref:`NXmanipulator`: - A base class to describe the complex manipulators used in photoemission experiments, often with > 4 degrees of freedom, - cryogenic cooling and other advanced features. - -We developed three base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: - - :ref:`NXcalibration`: - A base class to describe the 1D calibration of an axis, with a function mapping a raw data scale to a calibrated scale with the same number of points. - - :ref:`NXdistortion`: - A base class to describe the 2D distortion correction of an axis, with a matrix mapping a raw data image to a undistorted image. - - :ref:`NXregistration`: - A base class to describe the rigid transformations that are applied to an image. May be redundant as they can be described with :ref:`NXtransformations`. - -.. _MpesCommonBC1: - -Common Base Classes -################### - -We developed two classes that are common to other techniques: - - :ref:`NXlens_em`: - A class to describe all types of lenses. Includes electrostatic lenses for electron energy analysers. - - :ref:`NXdeflector` - A class to describe all kinds of deflectors, including electrostatic and magnetostatic deflectors for electron energy analysers. - -.. _MpesExtendedBC1: - -Base Classes Extended in Application Definitions -################################################ - -We use existent base classes in application definitions and add descriptors: - - :ref:`NXaperture` - Added fileds to describe analyser apertures and slits. - - :ref:`NXbeam` - Adedd fields to describe utrafast laser beams. - - :ref:`NXdetector` - Added fields to describe electron detectors (MCP+Phospor screen, delay lines etc.). - - :ref:`NXentry` - Added fields to describe an experiment. - - :ref:`NXprocess` - Added subclasses and collective processing descriptors. - - :ref:`NXsample` - Added descriptors specific to photoemission experiments. - - :ref:`NXsource` - Added descriptors for laboratory sources (X-ray, UV lamps) but mostly for ultrafast lasers with complex time structures. - - :ref:`NXinstrument` - Added descriptors for the overall resolutions of the experiment (energy, momentum, angular, spatial, temporal). From 4413d0c602dec8c8ac900eaa28bffbc23bbe4566 Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Mon, 24 Jul 2023 13:30:35 +0200 Subject: [PATCH 006/136] Remaining refactoring to remove unnecessary duplicates of old fairmat-proposal introductions and explanations which have now been replaced by the respective subgroups in contributed_classes, fixed typos, rerouted ci pipeline to point to fairmat branch # Conflicts: # manual/source/classes/contributed_definitions/cgms-structure.rst # manual/source/classes/contributed_definitions/em-structure.rst # manual/source/classes/contributed_definitions/transport-structure.rst # manual/source/conf.py --- .github/workflows/ci.yaml | 4 +- .../NXelectronanalyser.nxdl.xml | 6 +- dev_tools/docs/nxdl_index.py | 2 + manual/source/apm-structure.rst | 24 +- manual/source/cgms-structure.rst | 287 +--------------- .../contributed_definitions/apm-structure.rst | 310 +++++++++--------- .../ellipsometry-structure.rst | 6 +- .../icme-structure.rst | 37 +++ .../mpes-structure.rst | 4 +- .../sample-prep-structure.rst | 20 ++ manual/source/ellipsometry-structure.rst | 2 +- manual/source/em-structure.rst | 29 +- manual/source/icme-structure.rst | 9 + manual/source/img/FAIRmat_new.png | Bin 0 -> 24990 bytes manual/source/img/FAIRmat_new_with_text.png | Bin 0 -> 29306 bytes manual/source/index.rst | 3 +- manual/source/laboratory-structure.rst | 22 +- manual/source/mpes-structure.rst | 2 +- manual/source/north-structure.rst | 274 +--------------- manual/source/stm-structure.rst | 19 +- manual/source/transport-structure.rst | 22 +- 21 files changed, 277 insertions(+), 805 deletions(-) create mode 100644 manual/source/classes/contributed_definitions/icme-structure.rst create mode 100644 manual/source/classes/contributed_definitions/sample-prep-structure.rst create mode 100644 manual/source/icme-structure.rst create mode 100644 manual/source/img/FAIRmat_new.png create mode 100644 manual/source/img/FAIRmat_new_with_text.png diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4da534ddf..489cac82a 100755 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,10 +3,10 @@ name: Documentation build on: push: branches: - - main # push commit to the main branch + - fairmat # push commit to the fairmat branch pull_request: branches: - - main # pull request to the main branch + - fairmat # pull request to the fairmat branch workflow_dispatch: # allow manual triggering inputs: deploy: diff --git a/contributed_definitions/NXelectronanalyser.nxdl.xml b/contributed_definitions/NXelectronanalyser.nxdl.xml index db991447d..956d0c931 100644 --- a/contributed_definitions/NXelectronanalyser.nxdl.xml +++ b/contributed_definitions/NXelectronanalyser.nxdl.xml @@ -28,13 +28,13 @@ - Number of fast axes (axes acquired symultaneously, without scanning a pysical - quantity) + Number of fast axes (axes acquired simultaneously, without scanning a + physical quantity) - Number of slow axes (axes acquired scanning a pysical quantity) + Number of slow axes (axes acquired scanning a physical quantity) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index bcb8ac666..259464c6b 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -73,6 +73,8 @@ def nxdl_indices() -> Dict[str, dict]: rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") rst_lines.append(f"{indentation}cgms-structure\n") + rst_lines.append(f"{indentation}icme-structure\n") + rst_lines.append(f"{indentation}sample-prep-structure\n") for cname in sorted(classes): rst_lines.append(f"{indentation}{cname}\n") diff --git a/manual/source/apm-structure.rst b/manual/source/apm-structure.rst index d7e94f6af..84ff91a11 100644 --- a/manual/source/apm-structure.rst +++ b/manual/source/apm-structure.rst @@ -1,27 +1,9 @@ -.. _Apm-Structure1: +.. _Apm-Structure-Fairmat: ========================= B5: Atom-probe tomography ========================= -.. index:: - IntroductionApm1 - ApmAppDef1 +Atom probe tomography and related field-ion microscopy, aka atom probe microscopy (techniques) cover metrology methods with an origin in the materials science and condensed-matter physics communities. With its maturation and commercialization in the last two decades atom probe is increasingly being used for characterization of bio materials and fundamental science of field evaporation physics. - -.. _IntroductionApm1: - -Introduction -############## - -Set of data storage objects to describe the acquisition/measurement side, the reconstruction, and the ranging for atom probe microscopy experiments. The data storage objects can be useful as well for field-ion microscopy experiments. - -.. _ApmAppDef1: - -Application Definitions -####################### - -We created one new application definition whose intention is to serve both the description of atom probe tomography and field-ion microscopy measurements: - - :ref:`NXapm`: - A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes (ranging). +A status report of the ongoing work on data schemas for atom probe using NeXus is available here: :ref:`Apm-Structure`. diff --git a/manual/source/cgms-structure.rst b/manual/source/cgms-structure.rst index cb32812b3..4a4950933 100644 --- a/manual/source/cgms-structure.rst +++ b/manual/source/cgms-structure.rst @@ -1,284 +1,9 @@ -.. _CgmsFeatures-Structure1: +.. _Cg-Structure-Fairmat: -========================= -Geometry & Microstructure -========================= +====================== +Computational geometry +====================== -.. index:: - IntroductionCgms1 - PhysicsCgms1 - CgmsAppDef1 - CgmsBC1 - IcmeMsModels1 +Computational geometry is a frequently used tool for describing the shape and geometry of structural features in materials and components of instruments used for materials characterization. NeXus has a long history of base classes which serve these purposes. Upon closer inspection during the first year of the FAIRmat project, we found though that the collection of base classes could profit from an extension to make working with computational geometry data in NeXus simpler and more fine-grained. - -.. _IntroductionCgms1: - -Introduction -############ - -The computational-geometry/microstructure-modeling-based part of the proposal -has the following aims: - -First, we would like to contribute to efforts on standardizing a controlled -vocabulary, definitions for these terms, and relations between the terms, for -computational-geometry-based descriptions of the microstructure of materials -and atomic configurations used when characterizing materials in experiments -and computer simulations. - -As far as NeXus is concerned, the here proposed distinct sets of simple -geometric primitives and shapes offer a complementary alternative to the -already existent base classes in NeXus for constructive solid geometry -such as :ref:`NXcsg`, :ref:`NXoff_geometry`, or :ref:`NXquadric` to name but a few. - -Second, we would like to explore with this proposal how we can harmonize terms -frequently used by materials scientists in the field of condensed-matter physics -with definitions and terms offer by the NOMAD MetaInfo description. - -Third, the proposal should yield a substantiated set of arguments and suggestions -how descriptors for the structure and atomic architecture of materials can be -harmonized. With this we especially would like to reach out and intensify the -cooperation between the materials-science-related consortia of the German -National Research Infrastructure, specifically, FAIRmat, NFDI-MatWerk, NFDI4Ing, -NFDI4Chem, NFDI4Cat, MaRDi, and DAPHNE. - -.. The proposal reaches out to our colleagues in the materials engineering-based -.. consortia to document that there is value in discussing about controlled vocabulary. - -.. _PhysicsCgms1: - -Physics background -################## -Microstructural features or crystal defects are spatial arrangements of atoms. -Given their specific atomic arrangement and composition, such features have -specific constraints on the degrees of freedom how atoms can arrange. This causes -that these defects have specific properties. -Provided well-defined coarse-graining procedures are used and regions-of-interest -and/or regions-of-applicability are defined, microstructural features are often -characterized and modelled to have associated thermodynamic descriptors. - -Another motivation for the proposal was the observation that frequently the design -of file formats for simulation software in the computational materials science especially -those tools at the interface between condensed-matter physics and materials engineering -are frequently reimplementing the wheel (at least partly) when it comes to decide how to store -e.g. atom and feature positions or shape of regions-of-interest, grids, crystals, -grains, precipitates, and dislocations. - -Maybe this is a historical burden given the large set of technical terms and jargon -in place, which then motivated pragmatic solutions that resulted in many research groups -have developed similar formats using similar descriptions. - -We see this work on base classes and application definitions not primarily an -effort to improve and extend NeXus for now. Rather this part of the proposal -is an effort to support activities in materials science to work towards -common terminology and using controlled vocabularies more frequently. -These are the foundation for more sophisticated thoughts about practically -useful ontologies. - -Defining crystal defects is a question of how to coarse-grain a given spatio- -temporal set of atoms, each having a nuclid type and position/trajectory. -In most cases, such a coarse-graining is an ill-posed task because different -mathematical/geometrical methods exists how a point, a line, a surface, or a volumetric defect -can be described and be spatio-temporally constrained through a geometrical model -with defined geometric primitives and associated coarser-scale properties. - -The key motivation to such coarse-graining is to reduce the complexity of the -description. On the one hand to support visualization and scientific analyses - not only -of crystal defect arrangements. On the other hand it is the hope that using descriptors -at a coarser level, i.e. nanometer, micrometer, and larger, it is still possible -to find sufficiently accurate and precise descriptors which avoid that one has -to account for the dynamics of each atom to predict or understand the properties -of defects and their dynamics. - -Nevertheless, experience has shown that computational-geometry-based descriptions -when combined with hierarchical clustering/labeling methods, applied on set of -atoms and features turn out to yield useful descriptors. Examples include point, -line, surface defects, such as vacancies, solute cluster, dislocations, -disconnections, interfaces to name but a few. - -.. _CgmsBC1: - -Base Classes -############ - -We propose the following base classes, starting with a set of descriptors -for frequently used shapes and geometric primitives: - - :ref:`NXcg_sphere_set`: - A description for a set of possibly dissimilar spheres. - - :ref:`NXcg_ellipsoid_set`: - A description for a set of possibly dissimilar rotated ellipsoids. - - :ref:`NXcg_cylinder_set`: - A description for a set of possibly dissimilar rotated cylinders. - - :ref:`NXcg_point_set`: - A collection of points with labels or mark data. - - :ref:`NXcg_polyline_set`: - A collection of lines and linearized segments. - - :ref:`NXcg_triangle_set`: - A collection (or soup) of triangles. - - :ref:`NXcg_parallelogram_set`: - A collection of possibly dissimilar parallelograms. - - :ref:`NXcg_triangulated_surface_mesh`: - A mesh of triangles. - - :ref:`NXcg_polygon_set`: - A collection (or soup) of polygons. - - :ref:`NXcg_polyhedron_set`: - A collection (or soup) of polyhedra. - - :ref:`NXcg_roi_set`: - A container to host a number of different types of primitives. - - :ref:`NXcg_tetrahedron_set`: - A collection (or soup) of tetrahedra. - - :ref:`NXcg_hexahedron_set`: - A collection (or soup) of hexahedra with capabilities to represent - also simpler (bounding) boxes for e.g. binary trees. - -These base classes make use of new base classes which describe data structures: - - :ref:`NXcg_face_list_data_structure`: - In essence, the usual way how polygon/polyhedra data are reported: - Via a list of vertices and faces with identifier and properties. - - :ref:`NXcg_half_edge_data_structure`: - A half-edge data structure is a useful complementary descriptor for - polygon/polyhedra which enables topological analyses and traversal - of the graph how polygons and polyhedra can alternatively be described. - - :ref:`NXcg_unit_normal_set`: - As an additional structuring element especially for meshes, well-documented - normal information is crucial for distance computations. - - :ref:`NXcg_geodesic_mesh`: - Geodesic meshes are useful for all applications when meshing the surface - of a sphere. - - :ref:`NXcg_alpha_complex`: - Alpha shapes and alpha wrappings, specifically the special case of the - convex hull, are frequently used geometrical models for describing - a boundary or edge to a set of geometric primitives. - -Furthermore, we propose a few base classes for operations when working with -discretized representations of material (area or volume) which can be useful -not only for stencil-based methods: - - :ref:`NXcg_grid`: - A grid of cells. - - :ref:`NXisocontour`: - A description for isocontour descriptions. - - :ref:`NXcg_marching_cubes`: - An approach to store metadata of a specific implementation of - the Marching Cubes algorithm, whose sensitivity to specific topological - configurations is known to result in different triangle soups. - - :ref:`NXdelocalization`: - An approach to document procedures whereby a scalar field - is smoothened in a controlled manner. - -Assuming that these base classes can serve as building blocks, we would like -to test with the proposal also how these base classes can be applied in base -classes for specific types of microstructural features and/or utility classes -to hold metadata for these features: - - :ref:`NXsimilarity_grouping`: - An alias for NXclustering. - - :ref:`NXclustering`: - A description for clustering of objects (such as atoms or features). - - :ref:`NXorientation_set`: - A set of rotations to describe the relative orientation of members of a set of features/objects. - - :ref:`NXslip_system_set`: - Metadata to a set of slip system/slip system family for - a given crystal structure. - - :ref:`NXms_feature_set`: - Generic base class to describe any nested set of features - of a microstructure at the continuum-, micron-, nano-scale, or - to represent a topology of molecules and atoms. - - :ref:`NXms_snapshot`: - A container to describe the state of microstructural features - at a given point in time. - - :ref:`NXms_snapshot_set`: - The corresponding class to hold a set of :ref:`NXms_snapshot` objects. - - :ref:`NXchemical_composition`: - (Chemical) composition of a sample or a set of things. - -Furthermore, we found that it can be useful to have a set of base classes with -which software documents it state and gives a summary for users about the performance -and elapsed time measured while processing data. These utility classes include: - - :ref:`NXprogram`: - A named and version of a program of library/component of a larger software framework. - - :ref:`NXcs_filter_boolean_mask`: - A boolean mask. - - :ref:`NXcs_prng`: - Metadata of a pseudo-random number generator (PRNG) algorithm. - - :ref:`NXcs_profiling`: - A structuring group holding a set of :ref:`NXcs_profiling_event` instances. - - :ref:`NXcs_profiling_event`: - Profiling/benchmark data to an event of - tracking an algorithm/computational step. - - :ref:`NXcs_computer`: - Metadata of a computer. - - :ref:`NXcs_cpu`: - Metadata of a central processing unit. - - :ref:`NXcs_gpu`: - Metadata of a graphical processing unit / accelerator. - - :ref:`NXcs_mm_sys`: - Metadata of the (main) memory (sub-)system. - - :ref:`NXcs_io_sys`: - Metadata of the input/output system. - - :ref:`NXcs_io_obj`: - Metadata of a component storing data of an :ref:`NXcs_io_sys` instance. - -.. _IcmeMsModels1: - -Application definitions for ICME models -####################################### - -To bridge to our colleagues from the NFDI-MatWerk and NFDI4Ing consortia we -have created an example how the proposed components of the nexus-fairmat-proposal -can be used to create data schemes for vanilla-type ICME microstructure models. -ICME is an abbreviation for Integrated Computational Materials Engineering, which -is a design strategy and workflow whereby physics-based modelling of microstructure -evolution at the mesoscopic scale is used to understand the relations between -the microstructure and technological relevant descriptors for the properties -of materials. - -To begin with we propose the following draft application definitions. - - :ref:`NXms`: - An application definition for arbitrary spatiotemporally resolved simulations. - - :ref:`NXms_score_config`: - A specific example how :ref:`NXapm_paraprobe_config_ranger` can be specialized for documenting the configuration of a computer simulation with the static recrystallization cellular automata model SCORE. - - :ref:`NXms_score_results`: - A specific example how :ref:`NXms` can be specialized for documenting results of computer simulations with the static recrystallization cellular automata model SCORE. +A status report of this ongoing work is available here: :ref:`CgmsFeatures-Structure`. diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index 10e2c77c3..1e8b36152 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -1,36 +1,33 @@ .. _Apm-Structure: -========================= +===================== Atom-probe tomography -========================= +===================== .. index:: IntroductionApm ApmAppDef ApmBC - WhatHasBeenAchieved + StatusQuoApm ApmParaprobeAppDef ApmParaprobeNewBC - NextStep - - .. _IntroductionApm: Introduction -############## +############ -Set of data storage objects to describe the acquisition/measurement side, the reconstruction, and the ranging for atom probe microscopy experiments. The data storage objects can be useful as well for field-ion microscopy experiments. +Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, +steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, +i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. +The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. .. _ApmAppDef: Application Definition ###################### -It is proposed to use one application definition to serve atom probe tomography -and field-ion microscopy measurements, i.e. the data collection with the instrument: - :ref:`NXapm`: A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. @@ -43,178 +40,209 @@ The following base classes are proposed to support modularizing the storage of p :ref:`NXchamber`: A base class to describe a component of the instrument which houses other components. - A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. + A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities + for storing and loading specimens. :ref:`NXcoordinate_system_set` A base class to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. :ref:`NXion`: - A base class to describe charged molecular ions with an adjustable number of atoms/isotopes building each ion. Right now the maximum number of atoms supported building a molecular ion - is 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with - which all possible isotopes can be described. + A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. + For the usage in atom probe research the maximum number of atoms supported building a molecular ion + is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with + which all possible isotopes (stable, radioactive, or synthetically generated ones) can be described. :ref:`NXfabrication`: - A base class to bundle manufacturer/technology-partner-specific details about a - component or device of an instrument. + A base class to bundle manufacturer/technology-partner-specific details about + a component or device of an instrument. :ref:`NXpeak`: A base class to describe peaks mathematically to detail how peaks in - mass-to-charge-state ratio histograms (aka mass spectra) are - defined and labelled as iontypes. + mass-to-charge-state ratio histograms (aka mass spectra) are defined and + labelled as iontypes. :ref:`NXpump`: - A base class to describe details about pump(s) of an instrument. + A base class to describe details about pump(s) used as components of an instrument. :ref:`NXpulser_apm`: - A base class to describe the high-voltage and/or laser pulsing capabilities of - an atom probe microscope. + A base class to describe the high-voltage and/or laser pulsing capabilities. :ref:`NXreflectron`: A base class to describe a kinetic-energy-sensitive filtering device - for time of flight (ToF) mass spectrometry. + for time-of-flight (ToF) mass spectrometry. :ref:`NXstage_lab`: A base class to describe the specimen fixture including the cryo-head. - Nowadays, these stages represent small-scale laboratory platforms. + Nowadays, stages of microscopes represent small-scale laboratory platforms. Therefore, there is a need to define the characteristics of such stages in more detail, especially in light of in-situ experiments. Many similarities exists between a stage - in an electron microscope and one in an atom probe instrument. Both offer fixture functionalities and additional components for applying e.g. stimuli on the specimen. + in an electron microscope and one in an atom probe instrument. Both offer fixture + functionalities and additional components for applying e.g. stimuli on the specimen. -Microscopy experiments, not only taking into account those performed on commercial instruments, offer the user usually to apply a set of data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. +Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of +data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named +instances of the :ref:`NXprocess` base class. +Data processing steps are essential to transform measurements into knowledge. Therefore, these steps +should be documented to enable reproducible research, ideally numerically, and learn how pieces of information are connected. +In what follows, an example is presented how an open-source community software can be modified to use descriptions +of these computational steps. + +The respective research software here is the `paraprobe-toolbox `_ +The software is developed by `M. Kühbach et al. `_. +For atom probe research the proposal can also serve as a blue print how computational steps of other software +tool including commercial ones could be developed further to benefit from NeXus. -Like every research community data processing steps are essential to transform measurements -into knowledge. These processing steps should be documented to enable reproducible research -and learn how pieces of information were connected. In what follows, an example is presented -how an open-source community software can be modified to use descriptions of these computational -steps. The respective research software here is the `paraprobe-toolbox `_ .. _IntroductionApmParaprobe: apmtools ######## -One tool is the paraprobe-toolbox software package in the the apmtools container. -The software is developed by `M. Kühbach et al. `_. - -Here we show how NeXus is used to consistently define application definitions for scientific software -in the field of atom probe. In this community the paraprobe-toolbox is an example of an -open-source parallelized software for analyzing point cloud data, for assessing meshes in -3D continuum space, and for studying the effects of parameterization on descriptors -which describe the micro- and nanostructure of materials that are studied with -atom probe microscopy. +The paraprobe-toolbox is an example of an open-source parallelized software for analyzing +point cloud data, for assessing meshes in 3D continuum space, and for studying the effects of +parameterization on descriptors of micro- and nanoscale structural features (crystal defects) +within materials when characterized and studied with atom probe. The need for a thorough documentation of the tools in not only the paraprobe-toolbox was motivated by several needs: -First, users of software would like to better understand and also be able to -study for themselves which individual parameters and settings for each tool exist -and how configuring these affects their analyses quantitatively. +First, users of software would like to better understand and also be able to study for themselves +which individual parameters and settings for each tool exist and how configuring these +affects analyses quantitatively. This stresses the aspect how to improve documentation. -Second, scientific software like the tools in the paraprobe-toolbox implement a -numerical/algorithmical (computational) workflow whereby data from multiple input sources -(like previous analysis results) are processed and carried through more involved analysis -within several steps inside the tool. The tool then creates output as files. +Second, scientific software like paraprobe-toolbox implement numerical/algorithmical +(computational) workflows whereby data coming from multiple input sources +(like previous analysis results) are processed and carried through more involved analyses +within several steps inside the tool. The tool then creates output as files. This +provenance and workflow should be documented. Individual tools of paraprobe-toolbox are developed in C/C++ and/or Python. Provenance tracking is useful as it is one component and requirement for making -workflows exactly numerically reproducible and thereby empower scientists -to fulfill better the "R", i.e. reproducibility of their daily FAIR research practices. - -The paraprobe-toolbox is one example of a software which implements a workflow -via a sequence of operations executed within a jupyter notebook -(or Python script respectively). Specifically, individual tools are chained. -Convenience functions are available to create well-defined input/configuration -files for each tool. These config files instruct the tool upon processing. - -In this design, each workflow step (with a tool) is in fact a pair (or triple) of -at least two sub-steps: i) the creation of a configuration file, -ii) the actual analysis using the Python/or C/C++ tools, -iii) the optional post-processing/visualizing of the results inside the NeXus/HDF5 -files generated from each tool run using other software. +workflows exactly numerically reproducible and thus to enable reproducibility (the "R" +of the FAIR principles of data stewardship). +For tools of the paraprobe-toolbox each workflow step is a pair or triple of sub-steps: +1. The creation of a configuration file. +2. The actual analysis using the Python/or C/C++ tools. +3. The optional analyses/visualization of the results based on data in NeXus/HDF5 files generated by each tool. -.. _WhatHasBeenAchieved: +.. _StatusQuoApm: What has been achieved so far? ############################## -This proposal summarizes work of members of the FAIRmat project, which is part -of the German National Research Data Infrastructure aimed at a change of the paraprobe-toolbox -and its interaction with files for all tools so that only well-defined configuration files -are accepted as input and results end up as specifically formatted output. For this -NeXus application definitions are used. - -Data and metadata between the tools are exchanged with NeXus/HDF5 files. -Specifically, we created for each tool an application definition (see below) -which details all possible settings and options for the configuration as to -guide users. The config(uration) files are currently implemented as HDF5 files, -whose content matches to the naming conventions of the respective `config` application -definition for each tool. As an example NXapm_paraprobe_config_surfacer specifies +This proposal summarizes work of members of the FAIRmat project, which is part of the `German +National Research Data Infrastructure `_. The here detailed +proposal documents how all tools of the paraprobe-toolbox were modified to generate +only well-defined configuration files as accepted input and yield specifically formatted output +files according to the following NeXus application definitions. + +Data and metadata between the tools are exchanged with NeXus/HDF5 files. This means that data +inside HDF5 binary containers are named, formatted, and hierarchically structured according +to application definitions. + +For example the application definition NXapm_paraprobe_config_surfacer specifies how a configuration file for the paraprobe-surfacer tool should be formatted -and which parameter it should and/or may contain. +and which parameters it contains including optionality and cardinality constraints. -That is each config file uses a controlled vocabulary of terms. Furthermore, -the config files store a SHA256 checksum for each input file. -This implements a full provenance tracking on the input files along the -processing chain/workflow. +Thereby, each config file uses a controlled vocabulary of terms. Furthermore, +the config files store a SHA256 checksum for each input file. This implements a full +provenance tracking on the input files along the workflow. -As an example, a user may first range their reconstruction and then compute +As an example, a user may first range their reconstruction and then compute spatial correlation functions. The config file for the ranging tool stores the files which hold the reconstructed ion position and ranging definitions. -The ranging tool generates a results file with the ion type labels stored. +The ranging tool generates a results file with the labels of each molecular ion. This results file is formatted according to the tool-specific `results` -application definition. This results file and the reconstruction is -imported by the spatial statistics tool which again keeps track of all files. - -This design makes it possible to rigorously trace which numerical results -were achieved with a specific input and settings using specifically-versioned tools. +application definition. The generated results file and the reconstruction is +imported by the spatial statistics tool which again keeps track of all files +and reports its results in a spatial statistics tool results file. -We understand that this additional handling of metadata and provenance tracking -may not be at first glance super relevant for scientists or appears to be an -unnecessarily complex feature. There is indeed an additional layer of work which -came with the development and maintenance of this functionality. +This design makes it possible to rigorously trace which numerical results were achieved +with specific inputs and settings using specifically-versioned tools. Noteworthy +this includes Y-junction on a graph which is where multiple input sources are +combined to generate new results. -However, we are convinced that this is the preferred way of performing software -development and data analyses as it enables users to take advantage of a completely -automated provenance tracking which happens silently in the background. +We are convinced that defining, documenting, using, and sharing application definitions +is useful and future-proof strategy for software development and data analyses as it enables +automated provenance tracking which happens silently in the background .. _ApmParaprobeAppDef: Application Definitions ####################### -Application definitions for the input side (configuration) of each tool were defined. +NXapm_paraprobe application definitions are in fact pairs of application definitions. +One for the configuration (input) side and one for the results (output) side. For each +tool one such pair is proposed: :ref:`NXapm_paraprobe_config_transcoder`: Configuration of paraprobe-transcoder Load POS, ePOS, APSuite APT, RRNG, RNG, and NXapm HDF5 files. + :ref:`NXapm_paraprobe_results_transcoder`: + Results of paraprobe-transcoder + Store reconstructed positions, ions, and charge states. + + :ref:`NXapm_paraprobe_config_ranger`: Configuration of paraprobe-ranger Apply ranging definitions and explore possible molecular ions. + :ref:`NXapm_paraprobe_results_ranger`: + Results of paraprobe-ranger + Store applied ranging definitions and combinatorial analyses of all possible iontypes. + + :ref:`NXapm_paraprobe_config_selector`: Configuration of paraprobe-selector Defining complex spatial regions-of-interest to filter reconstructed datasets. + :ref:`NXapm_paraprobe_results_selector`: + Results of paraprobe-selector + Store which points are inside or on the boundary of complex spatial regions-of-interest. + + :ref:`NXapm_paraprobe_config_surfacer`: Configuration of paraprobe-surfacer Create a model for the edge of a point cloud via convex hulls, alpha shapes. + :ref:`NXapm_paraprobe_results_surfacer`: + Results of paraprobe-surfacer + Store triangulated surface meshes of models for the edge of a dataset. + + :ref:`NXapm_paraprobe_config_distancer`: Configuration of paraprobe-distancer Compute analytical distances between ions to a set of triangles. + :ref:`NXapm_paraprobe_results_distancer`: + Results of paraprobe-distancer + Store analytical distances between ions to a set of triangles. + + :ref:`NXapm_paraprobe_config_tessellator`: Configuration of paraprobe-tessellator Compute Voronoi cells for if desired all ions in a dataset. + :ref:`NXapm_paraprobe_results_tessellator`: + Results of paraprobe-tessellator + Store volume of all Voronoi cells about each ion in the dataset. + + :ref:`NXapm_paraprobe_config_nanochem`: Configuration of paraprobe-nanochem Compute delocalization, iso-surfaces, analyze 3D objects, and composition profiles. + :ref:`NXapm_paraprobe_results_nanochem`: + Results of paraprobe-nanochem + Store all results of delocalization, isosurface, and interface detection algorithms, + store all extracted triangulated surface meshes of found microstructural features, + store composition profiles and corresponding geometric primitives (ROIs). + + :ref:`NXapm_paraprobe_config_intersector`: Configuration of paraprobe-intersector Assess intersections and proximity of 3D triangulated surface meshes in @@ -222,55 +250,25 @@ Application definitions for the input side (configuration) of each tool were def extraction algorithms on the resulting shape, spatial arrangement, and colocation of 3D objects via graph-based techniques. + :ref:`NXapm_paraprobe_results_intersector`: + Results of paraprobe-intersector + Store graph of microstructural features and relations/link identified between them. + + :ref:`NXapm_paraprobe_config_spatstat`: Configuration of paraprobe-spatstat Spatial statistics on the entire or selected regions of the reconstructed dataset. + :ref:`NXapm_paraprobe_results_spatstat`: + Results of paraprobe-spatstat + Store spatial correlation functions. + + :ref:`NXapm_paraprobe_config_clusterer`: Configuration of paraprobe-clusterer Import cluster analysis results of IVAS/APSuite and perform clustering analyses in a Python ecosystem. -Application definitions for the output side (results) of each tool were defined. - - :ref:`NXapm_paraprobe_results_transcoder`: - Results of paraprobe-transcoder - Store reconstructed positions, ions, and charge states. - - :ref:`NXapm_paraprobe_results_ranger`: - Results of paraprobe-ranger - Store applied ranging definitions and combinatorial analyses of all possible iontypes. - - :ref:`NXapm_paraprobe_results_selector`: - Results of paraprobe-selector - Store which points are inside or on the boundary of complex spatial regions-of-interest. - - :ref:`NXapm_paraprobe_results_surfacer`: - Results of paraprobe-surfacer - Store triangulated surface meshes of models for the edge of a dataset. - - :ref:`NXapm_paraprobe_results_distancer`: - Results of paraprobe-distancer - Store analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_results_tessellator`: - Results of paraprobe-tessellator - Store volume of all Voronoi cells about each ion in the dataset. - - :ref:`NXapm_paraprobe_results_nanochem`: - Results of paraprobe-nanochem - Store all results of delocalization, isosurface, and interface detection algorithms, - store all extracted triangulated surface meshes of found microstructural features, - store composition profiles and corresponding geometric primitives (ROIs). - - :ref:`NXapm_paraprobe_results_intersector`: - Results of paraprobe-intersector - Store graph of microstructural features and relations/link identified between them. - - :ref:`NXapm_paraprobe_results_spatstat`: - Results of paraprobe-spatstat - Store spatial correlation functions. - :ref:`NXapm_paraprobe_results_clusterer`: Results of paraprobe-clusterer Store results of cluster analyses. @@ -282,45 +280,33 @@ Base Classes We envision that the above-mentioned definitions can be useful not only to take inspiration for other software tools in the field of atom probe but also to support -a discussion towards a stronger standardization of the vocabulary used. -Therefore, we are happy for comments and suggestions. - -The majority of data analyses in atom probe use a common set of operations and -conditions on the input data even though this might not be immediately evident -or might not have been so explicitly communicated in the literature. -Some tools have a specific scope because of which algorithms are hardcoded -to work for specific material systems. A typical example is a ranging tool -which exploits that all the examples it is used for apply to a specific material -and thus specific iontypes can be hardcoded. - -Instead, we are convinced it is better to follow a more generalized approach. -The following base classes and the above application definitions present examples -how one can use NeXus for this. +a discussion towards a stronger standardization of the vocabulary used. This is an +ongoing discussion in the field emission community `IFES `_. +We are happy for taking comments and suggestions. The use of base classes for atom probe +is motivated by the observation that the majority of data analyses in atom probe +use a common set of operations and conditions on the input data: :ref:`NXapm_input_reconstruction`: - A description from which file the reconstructed ion positions are imported. + A base class documenting from where reconstructed ion positions are imported. :ref:`NXapm_input_ranging`: - A description from which file the ranging definitions are imported. + A base class documenting from where ranging definitions are imported. The design of the ranging definitions is, thanks to :ref:`NXion`, so - general that all possible nuclids can be considered, be they observationally - stable, be they radioactive or transuranium nuclids. + general that all possible nuclids can be considered. -A detailed inspection of spatial and other type of filters frequently used in -analysis of atom probe data revealed that it is better to define atom-probe-agnostic, -i.e. more general filters: +A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe +data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: :ref:`NXspatial_filter`: - A proposal how a point cloud can be spatially filtered in a specific yet general manner. + A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, - and :ref:`NXcg_hexahedron_set` to cater for all of the most commonly used - geometric primitives in atom probe. + and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. + The primitives are used for defining the shape and extent of a region of interest (ROI). :ref:`NXsubsampling_filter`: - A proposal for a filter that can also be used for specifying how entries + A base class for a filter that can also be used for specifying how entries like ions can be filtered via sub-sampling. :ref:`NXmatch_filter`: - A proposal for a filter that can also be used for specifying how entries - like ions can be filtered based on their type (ion species) - or hit multiplicity. + A base class for a filter that can also be used for specifying how entries + like ions can be filtered based on their type or other descriptors like hit multiplicity. diff --git a/manual/source/classes/contributed_definitions/ellipsometry-structure.rst b/manual/source/classes/contributed_definitions/ellipsometry-structure.rst index 1f3ddbfaf..32259ecd5 100644 --- a/manual/source/classes/contributed_definitions/ellipsometry-structure.rst +++ b/manual/source/classes/contributed_definitions/ellipsometry-structure.rst @@ -1,8 +1,8 @@ .. _Ellipsometry-Structure: -======================== +==================== Optical Spectroscopy -======================== +==================== .. index:: Ellipsometry @@ -12,7 +12,7 @@ Optical Spectroscopy .. _Ellipsometry: Ellipsometry -############## +############ Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. The measurements are based on determining how the polarization state of light changes upon transmission and reflection. diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst new file mode 100644 index 000000000..b21ad199e --- /dev/null +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -0,0 +1,37 @@ +.. _Icme-Structure: + +============================================== +Integrated Computational Materials Engineering +============================================== + +.. index:: + IcmeMsModels + +.. _IcmeMsModels: + +Application definitions for ICME models +####################################### + +It is important to embrace the large research community of materials engineers +as they are frequent users of electron microscopy and atom probe microscopy. +ICME is an abbreviation for Integrated Computational Materials Engineering, which is +a design strategy and workflow whereby physics-based modelling of microstructure +evolution is used to understand the relations between the microstructure and +its technologically relevant descriptors to understand and tailor properties of materials. + +The following application definitions are proposed to support the discussion +how materials engineering-specific data schemas can connect to or be mapped on +concepts which are equally modellable with NeXus: + + :ref:`NXms`: + An application definition for arbitrary spatiotemporally resolved simulations. + + :ref:`NXms_score_config`: + A specific example how :ref:`NXapm_paraprobe_config_ranger` can be + specialized for documenting the configuration of a computer simulation + with the static recrystallization cellular automata model SCORE. + + :ref:`NXms_score_results`: + A specific example how :ref:`NXms` can be specialized for documenting + results of computer simulations with the static recrystallization + cellular automata model SCORE. diff --git a/manual/source/classes/contributed_definitions/mpes-structure.rst b/manual/source/classes/contributed_definitions/mpes-structure.rst index 1d37fdba6..df89809bf 100644 --- a/manual/source/classes/contributed_definitions/mpes-structure.rst +++ b/manual/source/classes/contributed_definitions/mpes-structure.rst @@ -1,8 +1,8 @@ .. _Mpes-Structure: -============================================== +======================================= Photoemission & core-level spectroscopy -============================================== +======================================= .. index:: IntroductionMpes diff --git a/manual/source/classes/contributed_definitions/sample-prep-structure.rst b/manual/source/classes/contributed_definitions/sample-prep-structure.rst new file mode 100644 index 000000000..39f8249e9 --- /dev/null +++ b/manual/source/classes/contributed_definitions/sample-prep-structure.rst @@ -0,0 +1,20 @@ +.. _Synthesis-Structure: + +================== +Sample preparation +================== + +.. index:: + SamplePreparation + +.. _SamplePreparation: + +Document steps of wet-lab sample preparation +############################################ + +Virtually all experiments require a preparation of the sample. As most techniques are surface-sensitive or probe exclusively the surface, the use of careful preparation +techniques is the key to successful experiments. Unfortunately, the quality of such processes is often difficult to reproduce. Nevertheless, documenting how samples +are prepared is relevant. This part of the proposal provides prototypes how descriptions of steps performed by human or robots in a lab could be described using NeXus. + + :ref:`NXlab_electro_chemo_mechanical_preparation`, :ref:`NXlab_sample_mounting`: + Prototype application definitions for documenting steps during sample preparation. diff --git a/manual/source/ellipsometry-structure.rst b/manual/source/ellipsometry-structure.rst index c801f341f..223643d68 100644 --- a/manual/source/ellipsometry-structure.rst +++ b/manual/source/ellipsometry-structure.rst @@ -1,4 +1,4 @@ -.. _Ellipsometry-Structure1: +.. _Ellipsometry-Structure-Fairmat: ======================== B4: Optical spectroscopy diff --git a/manual/source/em-structure.rst b/manual/source/em-structure.rst index 40965d1cf..ae9fed2f7 100644 --- a/manual/source/em-structure.rst +++ b/manual/source/em-structure.rst @@ -1,32 +1,9 @@ -.. _Em-Structure1: +.. _Em-Structure-Fairmat: ======================= B1: Electron microscopy ======================= -.. index:: - IntroductionEm1 - EmAppDef1 - - -.. _IntroductionEm1: - -Introduction -############ - -Set of data storage objects to describe components of an electron microscope and its eventually available focused-ion beam functionalities. The data storage objects were designed from the perspective of how electron microscopes are used by colleagues in the materials-science-branch of electron microscopy. We realize that the biology-/bio-materials/omics-branch of electron microscopy is eventually in an already more mature state of discussion with respect to data management practices. Realizing that we need to start somewhere, though, we focus for now on the condensed-matter physics, chemical physics of solids, and materials science applications of electron microscopy. As many of the components of electron microscopes used in the bio-materials communities are the same or at least many components very similar to those used and described in materials science, we are confident that the here presented schema definitions can also inspire discussion and exchange with the bio-materials community in the future. Partner consortia in the German National Research Data Infrastructure are here NFDI-Microbiota, NFDI4Health, and e.g. NFDI-Neuro. - -Electron microscopes are functionally very customizable tools: Examples include multi-signal/-modal analyses which are frequently realized as on-the-fly computational analyses, regularly switching between GUI-based instrument control, computational steps, and more and more using high-throughput stream-based processing. Also artificial intelligence methods get increasingly used and become closer interconnected with classical modes of controlling the instrument and perform data processing. A challenge in electron microscopy is that these steps are often executed within commercial integrated control and analysis software. This makes it additionally difficult to keep track of workflows and challenging to identify which specific quantities in the control software mean and represent in technical detail which physical quantity (and how these -quantities can be connected to the development of ontologies for electron microscopy experiments). - -.. _EmAppDef1: - -Application Definitions -####################### - -We acknowledge that it can be difficult to agree on a single application definition which is generally enough applicable yet remains easy enough and useful across a variety of instruments, technology partners, and instrument use cases. Therefore, we conceptualized first the basic components of an electron microscope and the usual workflow how an electron microscope is used. That is scientists place a specimen/sample into the microscope, calibrate the instrument, take measurements, may perform experiments or prepare their specimens with a focused ion beam, calibrate again, and take other measurements, before their session on the instrument ends. In between virtually all these steps data are collected and stream in from different detectors probing different physical mechanisms of the interaction between electrons or other types of radiation with the specimen. The session ends with the scientist removing -the specimen from the instrument or parking it so that the next user can start a session. Occasionally, service technicians perform calibrations and maintenance which also can be described as session on the microscope. Next, we wrote base classes to describe these steps and events. - - :ref:`NXem`: - A general application definition which explores the possibilities of electron microscopes. +Electron microscopy is a cross-cutting characterization technique of key demand and relevance within materials science, materials engineering, and bio-science/omics research communities. +A status report of the ongoing work on data schemas for electron microscopy using NeXus is available here: :ref:`Em-Structure`. diff --git a/manual/source/icme-structure.rst b/manual/source/icme-structure.rst new file mode 100644 index 000000000..8ff31eaf7 --- /dev/null +++ b/manual/source/icme-structure.rst @@ -0,0 +1,9 @@ +.. _Icme-Structure-Fairmat: + +============================================== +Integrated Computational Materials Engineering +============================================== + +With a large set of data schemas for computational geometry, and methods from condensed-matter physics as well as materials engineering we are convinced that the NeXus standardization framework can be one component of efforts to harmonize and consolidate the zoo of descriptions and data schemas used within the field of Integrated Computational Materials Engineering (ICME). + +A status report along these lines of thoughts and ongoing efforts is available here: :ref:`Icme-Structure`. diff --git a/manual/source/img/FAIRmat_new.png b/manual/source/img/FAIRmat_new.png new file mode 100644 index 0000000000000000000000000000000000000000..eeddabe3400c469ed1619f50d834533d2afc0303 GIT binary patch literal 24990 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 literal 0 HcmV?d00001 diff --git a/manual/source/index.rst b/manual/source/index.rst index 412a30dd0..306329d7b 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -19,8 +19,9 @@ https://www.nexusformat.org/ transport-structure stm-structure cgms-structure - laboratory-structure north-structure + laboratory-structure + icme-structure napi history diff --git a/manual/source/laboratory-structure.rst b/manual/source/laboratory-structure.rst index 05523bcbf..568e6d482 100644 --- a/manual/source/laboratory-structure.rst +++ b/manual/source/laboratory-structure.rst @@ -1,25 +1,9 @@ -.. _Lab-Structure: +.. _Lab-Structure-Fairmat: ================== Sample preparation ================== -.. index:: - Draft classes +Prototype application definitions for documenting steps during sample preparation are a part of ongoing work. -.. _LaboratorySteps: - -Virtually all experiments require a preparation of the sample. As most techniques -are surface-sensitive or probe exclusively the surface, the use of careful preparation -techniques is the key to successful experiments. Unfortunately, the quality of -such processes is often difficult to reproduce. Nevertheless, documenting how samples -are prepared is relevant. The classes here provide minimal examples how descriptions -of the sample preparation steps can be interfaced to NeXus. -Currently, we consider these drafts to work towards harmonization with the -specific examples developed by the team of area A of FAIRmat. - - :ref:`NXlab_sample_mounting`: - An application definition to document how a sample was mounted. - - :ref:`NXlab_electro_chemo_mechanical_preparation`: - An application definition to document how a sample was prepared. +A status quo of this work is reported here: :ref:`Synthesis-Structure` via the :ref:`NXlab_electro_chemo_mechanical_preparation` and the :ref:`NXlab_sample_mounting` application definitions. These are drafts. diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index cae1c026b..3b0fd8394 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -1,4 +1,4 @@ -.. _Mpes-Structure1: +.. _Mpes-Structure-Fairmat: ============================================== B2/B3: Photoemission & core-level spectroscopy diff --git a/manual/source/north-structure.rst b/manual/source/north-structure.rst index 2198f3f86..26526638d 100644 --- a/manual/source/north-structure.rst +++ b/manual/source/north-structure.rst @@ -1,264 +1,26 @@ -.. _North-Structure1: - -====================== -Nomad Remote Tools Hub -====================== +.. _North-Structure-Fairmat: +============================ +NOMAD OASIS Remote Tools Hub +============================ .. index:: - IntroductionApmParaprobe1 - WhatHasBeenAchieved1 - ApmParaprobeAppDef1 - ApmParaprobeNewBC1 - NextStep1 - - -.. _IntroductionApmParaprobe1: - -Introduction -############## - -NORTH (the NOMAD Oasis Remote Tools Hub) is a NOMAD Oasis service which makes -preconfigured scientific software of different communities available and coupled -to Oasis and accessible via the webbrowser. This part of the proposal documents -examples for specific NeXus-related work to some of the tools and containers -available in NORTH. - - -apmtools -######## - -One tool is the paraprobe-toolbox software package in the the apmtools container. -The software is developed by `M. Kühbach et al. `_. - -Here we show how NeXus is used to consistently define application definitions -for scientific software in the field of atom probe. In this community the paraprobe-toolbox is an example of an open-source parallelized -software for analyzing point cloud data, for assessing meshes in 3D continuum -space, and analyzing the effects of parameterization on descriptors -about the microstructure of materials which were studied with atom probe microscopy. - -The need for a thorough documentation of the tools in not only the paraprobe-toolbox was motivated by several needs: - -First, users of software would like to better understand and also be able to -study themselves which individual parameter and settings for each tool exist -and how configuring these affects their analyses quantitatively. - -Second, scientific software like the tools in the paraprobe-toolbox implement a -numerical/algorithmical (computational) workflow whereby data from multiple input sources -(like previous analysis results) are processed and carried through more involved analysis -within several steps inside the tool. The tool then creates output as files. - -Individual tools are developed in C/C++ and/or Python. Here, having a possibility -for provenance tracking is useful as it is one component and requirement for -making workflows exactly numerically reproducible and thus to empower scientists -to fullfill better the "R", i.e. reproducibility of daily FAIR research practices. - -The paraprobe-toolbox is one example of a software which implements a workflow -via a sequence of operations executed within a jupyter notebook -(or Python script respectively). Specifically, individual tools are chained. -Convenience functions are available to create well-defined input/configuration -files for each tool. These config files instruct the tool upon processing. - -In this design, each workflow step (with a tool) is in fact a pair (or triple) of -at least two sub-steps: i) the creation of a configuration file, -ii) the actual analysis using the Python/or C/C++ tools, -iii) the optional post-processing/visualizing of the results inside the NeXus/HDF5 -files generated from each tool run using other software. - - -.. _WhatHasBeenAchieved1: - -What has been achieved so far? -############################## - -This proposal summarizes both of the steps which we worked on between Q3/2022-Q1/2023 to change the interface and -file interaction in all tools of the paraprobe-toolbox to accept exclusively -well-defined configuration files and yield exclusively specific output. - -Data and metadata between the tools are exchanged with NeXus/HDF5 files. -Specifically, we created for each tool an application definition (see below) -which details all possible settings and options for the configuration as to -guide users. The config(uration) files are HDF5 files, whose content matches -to the naming conventions of the respective `config` application definition for each tool. -As an example NXapm_paraprobe_config_surfacer specifies how a configuration file -for the paraprobe-surfacer tool should be formatted and which parameter it contains. - -That is each config file uses a controlled vocabulary of terms. Furthermore, -the config files store a SHA256 checksum for each input file. -This implements a full provenance tracking on the input files along the -processing chain/workflow. - -As an example, a user may first range their reconstruction and then compute -correlation functions. The config file for the ranging tool stores the files -which hold the reconstructed ion position and ranging definitions. -The ranging tool generates a results file with the ion type labels stored. -This results file is formatted according to the tool-specific `results` -application definition. This results file and the reconstruction is -imported by the spatial statistics tool which again keeps track of all files. - -This design makes it possible to rigorously trace which numerical results -were achieved with a specific chain of input and -settings using specifically-versioned tools. - -We understand that this additional handling of metadata and provenance tracking -may not be at first glance super relevant for scientists or appears to be an -unnecessarily complex feature. There is indeed an additional layer of work which -came with the development and maintenance of this functionality. - -However, we are convinced that this is the preferred way of performing software -development and data analyses as it enables users to take advantage of a completely -automated provenance tracking which happens silently in the background. - -.. _ApmParaprobeAppDef1: - -Application Definitions -####################### - -Firstly, we define application definitions for the input side (configuration) of each tool. - - :ref:`NXapm_paraprobe_config_transcoder`: - Configuration of paraprobe-transcoder - Load POS, ePOS, APSuite APT, RRNG, RNG, and NXapm HDF5 files. - - :ref:`NXapm_paraprobe_config_ranger`: - Configuration of paraprobe-ranger - Apply ranging definitions and explore possible molecular ions. - - :ref:`NXapm_paraprobe_config_selector`: - Configuration of paraprobe-selector - Defining complex spatial regions-of-interest to filter reconstructed datasets. - - :ref:`NXapm_paraprobe_config_surfacer`: - Configuration of paraprobe-surfacer - Create a model for the edge of a point cloud via convex hulls, alpha shapes. - - :ref:`NXapm_paraprobe_config_distancer`: - Configuration of paraprobe-distancer - Compute analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_config_tessellator`: - Configuration of paraprobe-tessellator - Compute Voronoi cells for if desired all ions in a dataset. - - :ref:`NXapm_paraprobe_config_nanochem`: - Configuration of paraprobe-nanochem - Compute delocalization, iso-surfaces, analyze 3D objects, and composition profiles. - - :ref:`NXapm_paraprobe_config_intersector`: - Configuration of paraprobe-intersector - Assess intersections and proximity of 3D triangulated surface meshes in - continuum space to study the effect the parameterization of surface - extraction algorithms on the resulting shape, spatial arrangement, - and colocation of 3D objects via graph-based techniques. - - :ref:`NXapm_paraprobe_config_spatstat`: - Configuration of paraprobe-spatstat - Spatial statistics on the entire or selected regions of the reconstructed dataset. - - :ref:`NXapm_paraprobe_config_clusterer`: - Configuration of paraprobe-clusterer - Import cluster analysis results of IVAS/APSuite and perform clustering - analyses in a Python ecosystem. - -Secondly, we define application definitions for the output side (results) of each tool. - - :ref:`NXapm_paraprobe_results_transcoder`: - Results of paraprobe-transcoder - Store reconstructed positions, ions, and charge states. - - :ref:`NXapm_paraprobe_results_ranger`: - Results of paraprobe-ranger - Store applied ranging definitions and combinatorial analyses of all possible iontypes. - - :ref:`NXapm_paraprobe_results_selector`: - Results of paraprobe-selector - Store which points are inside or on the boundary of complex spatial regions-of-interest. - - :ref:`NXapm_paraprobe_results_surfacer`: - Results of paraprobe-surfacer - Store triangulated surface meshes of models for the edge of a dataset. - - :ref:`NXapm_paraprobe_results_distancer`: - Results of paraprobe-distancer - Store analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_results_tessellator`: - Results of paraprobe-tessellator - Store volume of all Voronoi cells about each ion in the dataset. - - :ref:`NXapm_paraprobe_results_nanochem`: - Results of paraprobe-nanochem - Store all results of delocalization, isosurface, and interface detection algorithms, - store all extracted triangulated surface meshes of found microstructural features, - store composition profiles and corresponding geometric primitives (ROIs). - - :ref:`NXapm_paraprobe_results_intersector`: - Results of paraprobe-intersector - Store graph of microstructural features and relations/link identified between them. - - :ref:`NXapm_paraprobe_results_spatstat`: - Results of paraprobe-spatstat - Store spatial correlation functions. - - :ref:`NXapm_paraprobe_results_clusterer`: - Results of paraprobe-clusterer - Store results of cluster analyses. - -.. _ApmParaprobeNewBC1: - -Base Classes -############ - -We envision that the above-mentioned definitions can be useful not only to take -inspiration for other software tools in the field of atom probe but also to support -a discussion towards a stronger standardization of the vocabulary used. -Therefore, we are happy for your comments and suggestions on this and the related -pages via the hypothesis web annotation service or as your issues posted on GitHub. - -We are convinced that the majority of data analyses in atom probe use -an in fact common set of operations and conditions on the input data -even though this might not be immediately evident. In particular this is not -the case for some community built tools with a very specific scope where oftentimes -the algorithms are hardcoded for specific material systems. A typical example is a -reseacher who implements a ranging tool and uses that all the examples are on a -specific material. We are convinced it is better to follow a much more generalized approach. - -In this spirit, we propose the following base classes and the above application -definitions as examples how very flexible constraints can be implemented which -restrict which ions in the dataset should be processed or not. We see that these -suggestions complement the proposal on computational geometry base classes: - - :ref:`NXapm_input_reconstruction`: - A description from which file the reconstructed ion positions are imported. - - :ref:`NXapm_input_ranging`: - A description from which file the ranging definitions are imported. - The design of the ranging definitions is, thanks to :ref:`NXion` so - general that all possible nuclids can be considered, be they observationally stable, - be they radioactive or transuranium nuclids. + IntroductionNorth + IntroductionApmTools -A detailed inspection of spatial and other type of filters used in atom probe microscopy -data analysis revealed that it is better to define atom probe agnostic, i.e. more -general filters: +.. _IntroductionNorth: - :ref:`NXspatial_filter`: - A proposal how a point cloud can be spatial filtered in a very specific, - flexible, yet general manner. This base class takes advantage of - :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, and :ref:`NXcg_hexahedron_set` - to cater for all of the most commonly used geometric primitives in - atom probe. +Introduction to NORTH +##################### +The NOMAD OASIS Remote Tools Hub (NORTH), is a `NOMAD OASIS `_ service which provides access to containerized applications. +These containers contain pre-configured scientific software of different academic communities and offer access to the data inside the NOMAD OASIS research data management system. +This page delivers status reports of ongoing work specific to NeXus and how NeXus is being used by tools within specific containers offered by NORTH. - :ref:`NXsubsampling_filter`: - A proposal for a filter that can also be used for specifying how entries - like ions can be filtered via sub-sampling. +.. _IntroductionApmTools: - :ref:`NXmatch_filter`: - A proposal for a filter that can also be used for specifying how entries - like ions can be filtered based on their type (ion species) - or hit multiplicity. +apmtools container +################## -In summary, we report with this proposal our experience made in an experimental -project that is about using NeXus for standardizing a set of non-trivial scientific software tools. -During the implementation we learned that for handling computational geometry -and microstructure-related terms many subtilities have to be considered which -makes a controlled vocabulary valuable not only to avoid a reimplementing of the wheel. +One containerized application in NORTH and its apmtools container, is the paraprobe-toolbox. This software is developed by `M. Kühbach et al. `_. +The software provides an implementation which exemplifies how NeXus/HDF5 and community tools for atom probe can be used to document provenance and steps of post-processing +for many steps relevant within the field of atom probe tomography and related field-ion microscopy: Inspect :ref:`Apm-Structure` for a status report and details. diff --git a/manual/source/stm-structure.rst b/manual/source/stm-structure.rst index 944c26203..253b6f3e8 100644 --- a/manual/source/stm-structure.rst +++ b/manual/source/stm-structure.rst @@ -1,4 +1,4 @@ -.. _Stm-Structure: +.. _Stm-Structure-Fairmat: ============================= Scanning Tunneling Microscopy @@ -14,19 +14,18 @@ Scanning Tunneling Microscopy .. _IntroductionStm: Introduction -############## -TBD +############ +Scientists of the scanning tunneling microscopy community and FAIRmat have worked together to create an application definition and related base classes for +documenting scanning tunneling spectroscopy. This is one community under the large umbrella of scanning (probe) microscopy methods. A status report of these efforts will be reported here. .. _StmAppDef: -Application Definitions -####################### -TBD - +.. Application Definitions +.. ####################### .. _StmNewBC: -Base Classes -############ -TBD +.. Base Classes +.. ############ + diff --git a/manual/source/transport-structure.rst b/manual/source/transport-structure.rst index 304a4f0e2..d75649a1f 100644 --- a/manual/source/transport-structure.rst +++ b/manual/source/transport-structure.rst @@ -1,26 +1,14 @@ -.. _Transport-Structure1: +.. _Transport-Structure-Fairmat: =================== Transport Phenomena =================== -.. index:: - IntroductionTransport1 - TransportAppDef1 +Work of scientists within FAIRmat how to handshake between instrument control software like EPICS and CAMELS using NeXus resulted in an application definition for exemplar temperature dependent IV curve measurements. +IV curve measurements are one example of a large group of so-called transport measurements. The key idea behind these is to monitor one or more observables under controlled environmental conditions and eventual stimuli applied on a sample. - -.. _IntroductionTransport1: - -Introduction -############## - - -.. _TransportAppDef1: - -Application Definitions -####################### - -Work on handshaking between EPICS-controlled experiments and NeXus resulted in one application definition for temperature dependent IV curve measurements. +Many techniques especially used within materials engineering fall into this category and thus could make use of specializations or extensions of NXiv_temp. +Examples include hardness measurements, nanoindentation, resistance, electro-chemical probing, or diffusion. :ref:`NXiv_temp`: Application definition for temperature dependent IV curve measurements. From 925e635e33112e285fa5c5e6329d4111b4884c94 Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Mon, 24 Jul 2023 14:37:30 +0200 Subject: [PATCH 007/136] Fixed bugs related to naming conventions of makefile recipes because of which the pdf did not compile properly # Conflicts: # manual/source/conf.py --- .github/workflows/ci.yaml | 2 ++ Makefile | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 489cac82a..7450c7833 100755 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,9 +3,11 @@ name: Documentation build on: push: branches: + - main - fairmat # push commit to the fairmat branch pull_request: branches: + - main - fairmat # pull request to the fairmat branch workflow_dispatch: # allow manual triggering inputs: diff --git a/Makefile b/Makefile index 3a882c256..500e50dae 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ prepare :: pdf :: $(SPHINX) -M latexpdf $(BUILD_DIR)/manual/source/ $(BUILD_DIR)/manual/build - cp $(BUILD_DIR)/manual/build/latex/nexus.pdf $(BUILD_DIR)/manual/source/_static/NeXusManual.pdf + cp $(BUILD_DIR)/manual/build/latex/nexus-fairmat.pdf $(BUILD_DIR)/manual/source/_static/NeXusManual.pdf html :: $(SPHINX) -b html -W $(BUILD_DIR)/manual/source/ $(BUILD_DIR)/manual/build/html @@ -95,7 +95,7 @@ all :: @echo "HTML built: `ls -lAFgh $(BUILD_DIR)/impatient-guide/build/html/index.html`" @echo "PDF built: `ls -lAFgh $(BUILD_DIR)/impatient-guide/build/latex/NXImpatient.pdf`" @echo "HTML built: `ls -lAFgh $(BUILD_DIR)/manual/build/html/index.html`" - @echo "PDF built: `ls -lAFgh $(BUILD_DIR)/manual/build/latex/nexus.pdf`" + @echo "PDF built: `ls -lAFgh $(BUILD_DIR)/manual/build/latex/nexus-fairmat.pdf`" $(BASE_CLASS_DIR)/%.nxdl.xml : $(BASE_CLASS_DIR)/$(NYAML_SUBDIR)/%.yaml nyaml2nxdl $< --output-file $@ From 56532b1eb31c2b0a4b441f54b2124d753bd6ce7e Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Wed, 26 Jul 2023 11:06:03 +0200 Subject: [PATCH 008/136] Renamed stm to sts --- .../sts-structure.rst} | 0 manual/source/sts-structure.rst | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+) rename manual/source/{stm-structure.rst => classes/contributed_definitions/sts-structure.rst} (100%) create mode 100644 manual/source/sts-structure.rst diff --git a/manual/source/stm-structure.rst b/manual/source/classes/contributed_definitions/sts-structure.rst similarity index 100% rename from manual/source/stm-structure.rst rename to manual/source/classes/contributed_definitions/sts-structure.rst diff --git a/manual/source/sts-structure.rst b/manual/source/sts-structure.rst new file mode 100644 index 000000000..253b6f3e8 --- /dev/null +++ b/manual/source/sts-structure.rst @@ -0,0 +1,31 @@ +.. _Stm-Structure-Fairmat: + +============================= +Scanning Tunneling Microscopy +============================= + + +.. index:: + IntroductionStm + StmAppDef + StmNewBC + + +.. _IntroductionStm: + +Introduction +############ + +Scientists of the scanning tunneling microscopy community and FAIRmat have worked together to create an application definition and related base classes for +documenting scanning tunneling spectroscopy. This is one community under the large umbrella of scanning (probe) microscopy methods. A status report of these efforts will be reported here. + +.. _StmAppDef: + +.. Application Definitions +.. ####################### + +.. _StmNewBC: + +.. Base Classes +.. ############ + From c4ae553e5a64618849f29d36c5f2f85dbdde6078 Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Wed, 26 Jul 2023 11:18:26 +0200 Subject: [PATCH 009/136] Added mvp doc for sts --- dev_tools/docs/nxdl_index.py | 1 + .../contributed_definitions/sts-structure.rst | 52 ++++++++++++------- manual/source/index.rst | 2 +- manual/source/sts-structure.rst | 33 ++---------- 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index 259464c6b..e5840aaeb 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -72,6 +72,7 @@ def nxdl_indices() -> Dict[str, dict]: rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") + rst_lines.append(f"{indentation}sts-structure\n") rst_lines.append(f"{indentation}cgms-structure\n") rst_lines.append(f"{indentation}icme-structure\n") rst_lines.append(f"{indentation}sample-prep-structure\n") diff --git a/manual/source/classes/contributed_definitions/sts-structure.rst b/manual/source/classes/contributed_definitions/sts-structure.rst index 253b6f3e8..42aef5e6e 100644 --- a/manual/source/classes/contributed_definitions/sts-structure.rst +++ b/manual/source/classes/contributed_definitions/sts-structure.rst @@ -1,31 +1,47 @@ -.. _Stm-Structure-Fairmat: - -============================= -Scanning Tunneling Microscopy -============================= +.. _Stm-Structure: +=============================== +Scanning Tunneling Spectroscopy +=============================== .. index:: - IntroductionStm - StmAppDef - StmNewBC + StsAppDef + StsBC + +.. _StsAppDef: + +Application Definition +###################### + :ref:`NXsts`: + An application definition for scanning tunneling spectroscopy experiments. -.. _IntroductionStm: +.. _StsNewBC: -Introduction +Base Classes ############ -Scientists of the scanning tunneling microscopy community and FAIRmat have worked together to create an application definition and related base classes for -documenting scanning tunneling spectroscopy. This is one community under the large umbrella of scanning (probe) microscopy methods. A status report of these efforts will be reported here. + :ref:`NXamplifier`: + A base class + + :ref:`NXbias_spectroscopy`: + A base class + + :ref:`NXcircuit`: + A base class + + :ref:`NXiv_bias`: + A base class -.. _StmAppDef: + :ref:`NXlockin`: + A base class -.. Application Definitions -.. ####################### + :ref:`NXpid`: + A base class -.. _StmNewBC: + :ref:`NXpositioner_sts`: + A base class -.. Base Classes -.. ############ + :ref:`NXsensor_scan`: + A base class diff --git a/manual/source/index.rst b/manual/source/index.rst index 306329d7b..dfa4d1bcf 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -17,7 +17,7 @@ https://www.nexusformat.org/ ellipsometry-structure apm-structure transport-structure - stm-structure + sts-structure cgms-structure north-structure laboratory-structure diff --git a/manual/source/sts-structure.rst b/manual/source/sts-structure.rst index 253b6f3e8..26d406c30 100644 --- a/manual/source/sts-structure.rst +++ b/manual/source/sts-structure.rst @@ -1,31 +1,8 @@ .. _Stm-Structure-Fairmat: -============================= -Scanning Tunneling Microscopy -============================= - - -.. index:: - IntroductionStm - StmAppDef - StmNewBC - - -.. _IntroductionStm: - -Introduction -############ - -Scientists of the scanning tunneling microscopy community and FAIRmat have worked together to create an application definition and related base classes for -documenting scanning tunneling spectroscopy. This is one community under the large umbrella of scanning (probe) microscopy methods. A status report of these efforts will be reported here. - -.. _StmAppDef: - -.. Application Definitions -.. ####################### - -.. _StmNewBC: - -.. Base Classes -.. ############ +=============================== +Scanning Tunneling Spectroscopy +=============================== +Scientists of the scanning tunneling spectroscopy community and FAIRmat have worked together to create an application definition and related base classes for documenting scanning tunneling spectroscopy experiments. +This is one community under the large umbrella of scanning (probe) microscopy methods. A status report of these efforts will be reported here: :ref:`Stm-Structure`. From f80a78c41841a1f30bf0070eef57a8dc59a0edb4 Mon Sep 17 00:00:00 2001 From: "markus.kuehbach" Date: Thu, 31 Aug 2023 14:48:50 +0200 Subject: [PATCH 010/136] Activated collapsible docstrings, change page width, added fairmat corporate design colours, added chopping of too long first lines of docstrings, added acknowledgements of the dfg and the nfdi on the front page # Conflicts: # dev_tools/docs/nxdl.py # manual/source/conf.py --- manual/source/_static/to_alabaster.css | 3 ++- manual/source/index.rst | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/manual/source/_static/to_alabaster.css b/manual/source/_static/to_alabaster.css index 32ccc19a6..3518cf2f7 100644 --- a/manual/source/_static/to_alabaster.css +++ b/manual/source/_static/to_alabaster.css @@ -2,8 +2,9 @@ /* Override sidebar background color default (#FFFFFF) */ .sphinxsidebar { - background: #005F73 !important; + background: #283593 !important; } +/* #005F73 is the original NIAC sidebar colour */ /* Control logo positioning */ .sphinxsidebarwrapper p.logo { diff --git a/manual/source/index.rst b/manual/source/index.rst index dfa4d1bcf..d2d0ee59b 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -36,6 +36,12 @@ https://www.nexusformat.org/ | This commit identifier <>. | This manual built |today|. +.. rubric:: Acknowledgements + +| The FAIRmat project is funded by the Deutsche Forschungsgemeinschaft +| (`DFG `_, German Research Foundation) - project 460197019. +| FAIRmat is a consortium within the `German NFDI `_. + .. seealso:: From b2c8156379a585fe325f5c41ff973232e933e78a Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:50:58 +0200 Subject: [PATCH 011/136] Changes two link in FAIRmat-NeXus Proposal cover page --- manual/source/fairmat-cover.rst | 292 ++++++++++++++++---------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/manual/source/fairmat-cover.rst b/manual/source/fairmat-cover.rst index d86dd303e..9545073b6 100644 --- a/manual/source/fairmat-cover.rst +++ b/manual/source/fairmat-cover.rst @@ -1,146 +1,146 @@ -.. _FairmatCover: - -======================= -FAIRmat-NeXus Proposal -======================= - -.. index:: - IntroductionCover - OurScope - Outreach - WhichData - WhatIsNew - -Aim -######################### - -Experiments nowadays create a set of very often voluminous and diverse numerical data and metadata. -These pieces of information represent entities of what is effectively a graph of materials data. -This graph can have a very large number of nodes and edges representing the large variety of -relations which scientists ideally want to identify and master -when transforming experimental research into knowledge. - -Experimentalists face the challenge that these pieces of information come at different levels -of granularity and format, of which many need to be better documented. You have very likely experienced -yourself how file and data formats are routinely encountered tasks to master in your daily -research practice and you might have questioned how these formats are currently handled -when you want to produce FAIR research data and publications. - -The NeXus-FAIRmat proposal is an interdisciplinary data science activity initiated by scientists of the -condensed-matter physics community which strives to develop community-maintained open file and data formats -for describing specific experimental techniques, their numerical data and metadata, -and strategies how to exchange these pieces of information. - -.. _IntroductionCover: - -The FAIRmat proposal to NeXus is an effort by the community of scientists of the `FAIRmat consortium `_ -to refine and expand the structure of NeXus. As a project which aims at creating an infrastructure -for experimental data to be findable, accessible, interoperable, and reusable (FAIR) in the fields of -condensed-matter physics and the chemical physics of solids, FAIRmat has adopted NeXus as the common format. - -`NeXus `_ is a common data exchange format which has its origin in the community of -scientists performing neutron, x-ray, and muon experiments. The development of NeXus is coordinated by the -NeXus International Advisory Committee (NIAC). -NeXus defines a schema of data entries with a controlled vocabulary and defined relations between the entries. -NeXus offers not only tools to document these schema definitions in a version-controlled manner but -also tools to check and verify how and if specific instances of NeXus schemata comply with the intended -schema definition when the data are written to files. Although, the Hierarchical Data Format (HDF5) is the -most commonly used file format to write NeXus file to, NeXus can also be used with other file formats. - -NeXus defines domain-specific rules for organizing data in e.g. HDF5 files (:ref:`application.definitions`) -and defines a dictionary of well-defined domain-specific (a vocabulary) of terms (:ref:`base.class.definitions`). -The meta- and numerical data in a NeXus file represent a hierarchical graph which encodes a specifically -granularized representation of relevant pieces of information and results that should be stored with -an experiment. - -Base classes and application definitions are two key components of the NeXus data model. -A base class represents a set of numerical data and metadata which specify details about -scientists, projects, instruments, and other physical devices, including the numerical data -and metadata which are deemed relevant for their description and the associated -computational analyses. Application definitions are constructed from combining such experiment- -and research-question-specifically customized base classes. - -In this combination, an application definition is a data contract between -a producer and a consumer of these scientific data. - -This design has sufficient flexibility to cover any experimental technique and instrumentation, while -ensuring rigorous, application-specific structures that can be processed in an automated manner. - -In cases where base classes or application definitions have not yet been proposed advantage of NeXus can be taken -if the respective scientific community explicitly designs, implements, uses, and continuously evolves -these classes and definitions. Here the role of the NIAC is to support the community with -data modeling and data science technical expertise, thus taking an important role of -cross-disciplinary review. - -The NeXus-FAIRmat proposal represents the results of this development for experiments and use cases which have not yet used NeXus. -Specifically, the proposal includes cases in the materials-science-branch of electron microscopy (EM), photo-emission spectroscopy, -ellipsometry, and the field of atom probe tomography and related field-ion microscopy, here jointly referred to as atom probe microscopy. - - -The documentation available here includes parts of the contents of the NeXus User Manual (also available `here `_), -reported here for the convenience of the user, but is restricted to the parts most pertinent to the our proposal. - -For more extensive information, please visit the original manual. - -.. _OurScope: - -Our scope and perspective -######################### - -Thanks to a cooperative approach across a wide variety of experimental techniques, -the NeXus-FAIRmat proposal of the FAIRmat project has an opportunity -to expand the set of data/metadata accurately described via NeXus. - -With a closely-connected team of domain experts, we will develop such expansion while at the same time maintaining -a consistent structure across different techniques and methods, striving for the maximum simplicity of use. - -Achieving a standardized and FAIR data structure has a wide spectrum of advantages, ranging from radical -progress in scientific transparency to the development of new, far-reaching tools that can be shared across -the whole scientific community. The convenience of such tools can range from guaranteeing data reusability within -a single lab, to enabling open-source availability of ready-to-use advanced analysis software. - -Perhaps the greatest resource, however, is the inclusion of experimental datasets in the `NOMAD Laboratory `_: -a data infrastructure that already hosts the largest computational material science repository in the world, representing a -homogeneous and machine-readable archive, a human-accessible encyclopedia of materials data -with tools for automated artificial intelligence analyses and data access. - -.. _Outreach: - -Outreach to the community -########################## - -A data infrastructure is not effective if it does not integrate seamlessly in the day-to-day workflow of a laboratory. -For this reason, we approach our newly developed NeXus proposal as a community-driven development. -We have drafted an accurate and consistent expansion of NeXus capabilities for a number of lab-based techniques, -but need extensive testing and tweaking of its characteristics by the community. - -If your data is generated with these techniques and you are interested in producing FAIR data and accessing the FAIRmat tools, we -invite you to try out our proposed structure. If you find any conflicts or inconsistencies, please raise them to us using the -comment section. These comments are implemented with `Hypothesis `_, a modern web annotation -tool from the journalism community. The commenting function for each page of the proposal enable you to contribute to the -creation of a more consistent and practical NeXus structure which, in our firm belief, can serve your community and beyond. - -If you do not find your specific experimental technique but would be interested in participating in the development -of a standard using NeXus, feel also very much invited to contact us directly at the `FAIRmat-Team `_. - -.. _WhichData: - -Which data should I convert? -############################ - -You are free to choose at which point in the workflow you wish to convert the data to NeXus, as its flexibility allows to -describe raw data, pre-processed data and fully processed data. As an entry step, we suggest to use a test dataset -that is fully processed and already published (or, alternatively, of negligible scientific content). These datasets, indeed, require often the most -extensive metadata description, but are most easily converted to NeXus, with minimal to no impact on the data processing pipeline. - -In fact, a low barrier (but high yield!) way to participate to FAIRmat consists in converting only fully processed datasets that -are used for a publication, and publishing them via FAIRmat only when your manuscript is in press. This makes the task of -converting to NeXus much more sporadic than fairifying raw data, to the point that it may be even acceptable not to automate it. At the same time, -it guarantees full control on the data until publication. We are confident that if you take this approach, more appetite will come with eating, -and you will be naturally inclined to gradually integrate FAIRmat structures and tools further in your workflow. - - -.. _WhatIsNew: - -.. What is New? -.. ############## +.. _FairmatCover: + +======================= +FAIRmat-NeXus Proposal +======================= + +.. index:: + IntroductionCover + OurScope + Outreach + WhichData + WhatIsNew + +Aim +######################### + +Experiments nowadays create a set of very often voluminous and diverse numerical data and metadata. +These pieces of information represent entities of what is effectively a graph of materials data. +This graph can have a very large number of nodes and edges representing the large variety of +relations which scientists ideally want to identify and master +when transforming experimental research into knowledge. + +Experimentalists face the challenge that these pieces of information come at different levels +of granularity and format, of which many need to be better documented. You have very likely experienced +yourself how file and data formats are routinely encountered tasks to master in your daily +research practice and you might have questioned how these formats are currently handled +when you want to produce FAIR research data and publications. + +The NeXus-FAIRmat proposal is an interdisciplinary data science activity initiated by scientists of the +condensed-matter physics community which strives to develop community-maintained open file and data formats +for describing specific experimental techniques, their numerical data and metadata, +and strategies how to exchange these pieces of information. + +.. _IntroductionCover: + +The FAIRmat proposal to NeXus is an effort by the community of scientists of the `FAIRmat consortium `_ +to refine and expand the structure of NeXus. As a project which aims at creating an infrastructure +for experimental data to be findable, accessible, interoperable, and reusable (FAIR) in the fields of +condensed-matter physics and the chemical physics of solids, FAIRmat has adopted NeXus as the common format. + +`NeXus `_ is a common data exchange format which has its origin in the community of +scientists performing neutron, x-ray, and muon experiments. The development of NeXus is coordinated by the +NeXus International Advisory Committee (NIAC). +NeXus defines a schema of data entries with a controlled vocabulary and defined relations between the entries. +NeXus offers not only tools to document these schema definitions in a version-controlled manner but +also tools to check and verify how and if specific instances of NeXus schemata comply with the intended +schema definition when the data are written to files. Although, the Hierarchical Data Format (HDF5) is the +most commonly used file format to write NeXus file to, NeXus can also be used with other file formats. + +NeXus defines domain-specific rules for organizing data in e.g. HDF5 files (:ref:`application.definitions`) +and defines a dictionary of well-defined domain-specific (a vocabulary) of terms (:ref:`base.class.definitions`). +The meta- and numerical data in a NeXus file represent a hierarchical graph which encodes a specifically +granularized representation of relevant pieces of information and results that should be stored with +an experiment. + +Base classes and application definitions are two key components of the NeXus data model. +A base class represents a set of numerical data and metadata which specify details about +scientists, projects, instruments, and other physical devices, including the numerical data +and metadata which are deemed relevant for their description and the associated +computational analyses. Application definitions are constructed from combining such experiment- +and research-question-specifically customized base classes. + +In this combination, an application definition is a data contract between +a producer and a consumer of these scientific data. + +This design has sufficient flexibility to cover any experimental technique and instrumentation, while +ensuring rigorous, application-specific structures that can be processed in an automated manner. + +In cases where base classes or application definitions have not yet been proposed advantage of NeXus can be taken +if the respective scientific community explicitly designs, implements, uses, and continuously evolves +these classes and definitions. Here the role of the NIAC is to support the community with +data modeling and data science technical expertise, thus taking an important role of +cross-disciplinary review. + +The NeXus-FAIRmat proposal represents the results of this development for experiments and use cases which have not yet used NeXus. +Specifically, the proposal includes cases in the materials-science-branch of electron microscopy (EM), photo-emission spectroscopy, +ellipsometry, and the field of atom probe tomography and related field-ion microscopy, here jointly referred to as atom probe microscopy. + + +The documentation available here includes parts of the contents of the NeXus User Manual (also available `here `_), +reported here for the convenience of the user, but is restricted to the parts most pertinent to the our proposal. + +For more extensive information, please visit the original manual. + +.. _OurScope: + +Our scope and perspective +######################### + +Thanks to a cooperative approach across a wide variety of experimental techniques, +the NeXus-FAIRmat proposal of the FAIRmat project has an opportunity +to expand the set of data/metadata accurately described via NeXus. + +With a closely-connected team of domain experts, we will develop such expansion while at the same time maintaining +a consistent structure across different techniques and methods, striving for the maximum simplicity of use. + +Achieving a standardized and FAIR data structure has a wide spectrum of advantages, ranging from radical +progress in scientific transparency to the development of new, far-reaching tools that can be shared across +the whole scientific community. The convenience of such tools can range from guaranteeing data reusability within +a single lab, to enabling open-source availability of ready-to-use advanced analysis software. + +Perhaps the greatest resource, however, is the inclusion of experimental datasets in the `NOMAD Laboratory `_: +a data infrastructure that already hosts the largest computational material science repository in the world, representing a +homogeneous and machine-readable archive, a human-accessible encyclopedia of materials data +with tools for automated artificial intelligence analyses and data access. + +.. _Outreach: + +Outreach to the community +########################## + +A data infrastructure is not effective if it does not integrate seamlessly in the day-to-day workflow of a laboratory. +For this reason, we approach our newly developed NeXus proposal as a community-driven development. +We have drafted an accurate and consistent expansion of NeXus capabilities for a number of lab-based techniques, +but need extensive testing and tweaking of its characteristics by the community. + +If your data is generated with these techniques and you are interested in producing FAIR data and accessing the FAIRmat tools, we +invite you to try out our proposed structure. If you find any conflicts or inconsistencies, please raise them to us using the +comment section. These comments are implemented with `Hypothesis `_, a modern web annotation +tool from the journalism community. The commenting function for each page of the proposal enable you to contribute to the +creation of a more consistent and practical NeXus structure which, in our firm belief, can serve your community and beyond. + +If you do not find your specific experimental technique but would be interested in participating in the development +of a standard using NeXus, feel also very much invited to contact us directly at the `FAIRmat-Team `_. + +.. _WhichData: + +Which data should I convert? +############################ + +You are free to choose at which point in the workflow you wish to convert the data to NeXus, as its flexibility allows to +describe raw data, pre-processed data and fully processed data. As an entry step, we suggest to use a test dataset +that is fully processed and already published (or, alternatively, of negligible scientific content). These datasets, indeed, require often the most +extensive metadata description, but are most easily converted to NeXus, with minimal to no impact on the data processing pipeline. + +In fact, a low barrier (but high yield!) way to participate to FAIRmat consists in converting only fully processed datasets that +are used for a publication, and publishing them via FAIRmat only when your manuscript is in press. This makes the task of +converting to NeXus much more sporadic than fairifying raw data, to the point that it may be even acceptable not to automate it. At the same time, +it guarantees full control on the data until publication. We are confident that if you take this approach, more appetite will come with eating, +and you will be naturally inclined to gradually integrate FAIRmat structures and tools further in your workflow. + + +.. _WhatIsNew: + +.. What is New? +.. ############## From 3f776255207a00e3e6fba25ae56f444fe0817a09 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Mon, 25 Sep 2023 11:37:28 +0200 Subject: [PATCH 012/136] =?UTF-8?q?Convenience=20functions=20for=20nyaml?= =?UTF-8?q?=20=E2=87=84=20nxdl=20and=20gh=20pages=20build=20(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add appdef/bc yaml files to gitignore * Improve Makefile for nxdl build * Tricking make to avoid circular dependency * Generalization and cleanup * Change chmod 755 to 644 for NXentry * Reintroduce for-loop for make nyaml * Adds push to github pages * Set correct docs dir * Prepare building * Change id to name * Build and deploy * Push pages to fairmat-docs * Adds clean flag * Use docs folder * Target fairmat branch to rebuild live-docs * Removes old workflows * Updates color and logo * Optimise styling * Add logo padding * Run ci on pr * Adds cleanup ci * Removes yaml files from .gitignore # Conflicts: # .gitignore # Makefile --- .github/nexus-fairmat-gen-docs.yml | 94 ------------------ .github/workflows/fairmat-build-pages.yaml | 45 +++++++++ .github/workflows/fairmat-clean-pages.yaml | 24 +++++ .github/workflows/nexus-fairmat-gen-docs.yml | 98 ------------------- Makefile | 4 +- base_classes/NXentry.nxdl.xml | 0 manual/source/_static/to_alabaster.css | 13 ++- manual/source/img/FAIRmat_new.png | Bin 24990 -> 10334 bytes 8 files changed, 81 insertions(+), 197 deletions(-) delete mode 100644 .github/nexus-fairmat-gen-docs.yml create mode 100644 .github/workflows/fairmat-build-pages.yaml create mode 100644 .github/workflows/fairmat-clean-pages.yaml delete mode 100644 .github/workflows/nexus-fairmat-gen-docs.yml mode change 100755 => 100644 base_classes/NXentry.nxdl.xml diff --git a/.github/nexus-fairmat-gen-docs.yml b/.github/nexus-fairmat-gen-docs.yml deleted file mode 100644 index 4d7e3813a..000000000 --- a/.github/nexus-fairmat-gen-docs.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: Publish Sphinx Docs to GitHub Pages -on: [push] - -# see: https://sphinx-notes.github.io/pages/ -# see: https://github.com/marketplace/actions/sphinx-to-github-pages - -jobs: - - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@master - with: - fetch-depth: 0 # otherwise, you will fail to push refs to dest repo - - - name: Install build requirements - run: | - pip install -r requirements.txt - - name: Diagnostic - run: | - pip list - - name: Run the test suite - run: | - # stops publishing when known problems are found - python utils/test_suite.py - - name: Prepare for out-of-source Sphinx build - run: | - rm -rf ./build - mkdir ./build - python ./utils/build_preparation.py . ./build - - name: Diagnostic - run: | - ls -lAFGh - ls -lAFGh ./build - - name: Install LaTeX - run: | - sudo apt-get update -y && \ - sudo apt-get install -y \ - latexmk \ - texlive-latex-recommended \ - texlive-latex-extra \ - texlive-fonts-recommended - - name: Build impatient guide - run: | - make -C ./build/impatient-guide html latexpdf - ls -lAFGh ./build/impatient-guide/_build/latex/*.pdf - # Copy to documentation source directory - cp \ - ./build/impatient-guide/_build/latex/NXImpatient.pdf \ - ./build/manual/source/_static/ - - name: Build PDF of manual - run: | - # expect next make (PDF) to fail (thus exit 0) - # since nexus.ind not found first time - # extra option for "levels nested too deeply" error - ( \ - make latexpdf \ - LATEXOPTS="--interaction=nonstopmode" \ - -C build/manual \ - || exit 0 \ - ) - # make that missing file - makeindex build/manual/build/latex/nexus.idx - # build the PDF, still a failure will be noted - # but we can ignore it without problem - ( \ - make latexpdf \ - LATEXOPTS="--interaction=nonstopmode" \ - -C build/manual \ - || exit 0\ - ) - # Copy to documentation source directory - cp \ - ./build/manual/build/latex/nexus.pdf \ - ./build/manual/source/_static/NeXusManual.pdf - - name: Include other PDFs - run: | - wget https://github.com/nexusformat/code/raw/master/doc/api/NeXusIntern.pdf -O ./build/manual/source/_static/NeXusIntern.pdf - wget https://github.com/nexusformat/code/raw/master/applications/NXtranslate/docs/NXtranslate.pdf -O ./build/manual/source/_static/NXtranslate.pdf - - name: Build (html) and Commit - uses: sphinx-notes/pages@master - with: - # path to conf.py directory - documentation_path: build/manual/source - - - name: Publish if refs/tags - # remove/comment next line to push right away - if: startsWith(github.ref, 'refs/tags') - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: gh-pages diff --git a/.github/workflows/fairmat-build-pages.yaml b/.github/workflows/fairmat-build-pages.yaml new file mode 100644 index 000000000..d228e735f --- /dev/null +++ b/.github/workflows/fairmat-build-pages.yaml @@ -0,0 +1,45 @@ +name: GH pages fairmat proposal + +on: + push: + branches: [fairmat] + pull_request: + branches: [fairmat] + +jobs: + pages: + runs-on: ubuntu-20.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: install dependencies + run: pip install -r requirements.txt + - name: Get branch name + id: branch-name + uses: tj-actions/branch-names@v7 + - name: test + run: make test + - name: prepare + run: make prepare + - name: html + run: make html + - name: Deploy + if: steps.branch-name.outputs.is_default == 'true' + uses: JamesIves/github-pages-deploy-action@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + folder: build/manual/build/html + branch: fairmat-docs + target-folder: docs + clean: false + - name: Deploy PR + if: steps.branch-name.outputs.is_default == 'false' + uses: JamesIves/github-pages-deploy-action@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + folder: build/manual/build/html + branch: fairmat-docs + target-folder: docs/${{ steps.branch-name.outputs.current_branch }} + clean: false \ No newline at end of file diff --git a/.github/workflows/fairmat-clean-pages.yaml b/.github/workflows/fairmat-clean-pages.yaml new file mode 100644 index 000000000..b70bd52e1 --- /dev/null +++ b/.github/workflows/fairmat-clean-pages.yaml @@ -0,0 +1,24 @@ +name: GH pages cleanup + +on: + delete: + +jobs: + cleanup: + if: github.event.ref_type == 'branch' + runs-on: ubuntu-latest + steps: + - name: Checkout pages + uses: actions/checkout@v2 + with: + ref: fairmat-docs + persist-credentials: false + fetch-depth: 0 + - name: Remove branch directory + run: rm -rf docs/${{ github.event.ref }} + - name: Commit & Push changes + uses: actions-js/push@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: fairmat-docs + message: Fairmat docs cleanup ${date} \ No newline at end of file diff --git a/.github/workflows/nexus-fairmat-gen-docs.yml b/.github/workflows/nexus-fairmat-gen-docs.yml deleted file mode 100644 index 53c001e24..000000000 --- a/.github/workflows/nexus-fairmat-gen-docs.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: NeXus/FAIRmat-Experimental Sphinx Docs to GitHub Pages -on: - #push: - # branches: - # - fairmat - workflow_dispatch: - -# see: https://sphinx-notes.github.io/pages/ -# see: https://github.com/marketplace/actions/sphinx-to-github-pages - -jobs: - - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@fairmat - with: - fetch-depth: 0 # otherwise, you will fail to push refs to dest repo - - #- name: Install build requirements - # run: | - # pip install -r requirements.txt - #- name: Diagnostic - # run: | - # pip list - #- name: Run the test suite - # run: | - # # stops publishing when known problems are found - # python utils/test_suite.py - #- name: Prepare for out-of-source Sphinx build - # run: | - # rm -rf ./build - # mkdir ./build - # python ./utils/build_preparation.py . ./build - #- name: Diagnostic - # run: | - # ls -lAFGh - # ls -lAFGh ./build - #- name: Install LaTeX - # run: | - # sudo apt-get update -y && \ - # sudo apt-get install -y \ - # latexmk \ - # texlive-latex-recommended \ - # texlive-latex-extra \ - # texlive-fonts-recommended - #- name: Build impatient guide - # run: | - # make -C ./build/impatient-guide html latexpdf - # ls -lAFGh ./build/impatient-guide/_build/latex/*.pdf - # # Copy to documentation source directory - # cp \ - # ./build/impatient-guide/_build/latex/NXImpatient.pdf \ - # ./build/manual/source/_static/ - #- name: Build PDF of manual - # run: | - # # expect next make (PDF) to fail (thus exit 0) - # # since nexus.ind not found first time - # # extra option for "levels nested too deeply" error - # ( \ - # make latexpdf \ - # LATEXOPTS="--interaction=nonstopmode" \ - # -C build/manual \ - # || exit 0 \ - # ) - # # make that missing file - # makeindex build/manual/build/latex/nexus.idx - # # build the PDF, still a failure will be noted - # # but we can ignore it without problem - # ( \ - # make latexpdf \ - # LATEXOPTS="--interaction=nonstopmode" \ - # -C build/manual \ - # || exit 0\ - # ) - # # Copy to documentation source directory - # cp \ - # ./build/manual/build/latex/nexus.pdf \ - # ./build/manual/source/_static/NeXusManual.pdf - #- name: Include other PDFs - # run: | - # wget https://github.com/nexusformat/code/raw/master/doc/api/NeXusIntern.pdf -O ./build/manual/source/_static/NeXusIntern.pdf - # wget https://github.com/nexusformat/code/raw/master/applications/NXtranslate/docs/NXtranslate.pdf -O ./build/manual/source/_static/NXtranslate.pdf - #- name: Build (html) and Commit - # uses: sphinx-notes/pages@master - # with: - # # path to conf.py directory - # documentation_path: build/manual/source - - - name: Publish if refs/tags - # remove/comment next line to push right away - if: startsWith(github.ref, 'refs/tags') - uses: ad-m/github-push-action@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: gh-pages diff --git a/Makefile b/Makefile index 500e50dae..3a882c256 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ prepare :: pdf :: $(SPHINX) -M latexpdf $(BUILD_DIR)/manual/source/ $(BUILD_DIR)/manual/build - cp $(BUILD_DIR)/manual/build/latex/nexus-fairmat.pdf $(BUILD_DIR)/manual/source/_static/NeXusManual.pdf + cp $(BUILD_DIR)/manual/build/latex/nexus.pdf $(BUILD_DIR)/manual/source/_static/NeXusManual.pdf html :: $(SPHINX) -b html -W $(BUILD_DIR)/manual/source/ $(BUILD_DIR)/manual/build/html @@ -95,7 +95,7 @@ all :: @echo "HTML built: `ls -lAFgh $(BUILD_DIR)/impatient-guide/build/html/index.html`" @echo "PDF built: `ls -lAFgh $(BUILD_DIR)/impatient-guide/build/latex/NXImpatient.pdf`" @echo "HTML built: `ls -lAFgh $(BUILD_DIR)/manual/build/html/index.html`" - @echo "PDF built: `ls -lAFgh $(BUILD_DIR)/manual/build/latex/nexus-fairmat.pdf`" + @echo "PDF built: `ls -lAFgh $(BUILD_DIR)/manual/build/latex/nexus.pdf`" $(BASE_CLASS_DIR)/%.nxdl.xml : $(BASE_CLASS_DIR)/$(NYAML_SUBDIR)/%.yaml nyaml2nxdl $< --output-file $@ diff --git a/base_classes/NXentry.nxdl.xml b/base_classes/NXentry.nxdl.xml old mode 100755 new mode 100644 diff --git a/manual/source/_static/to_alabaster.css b/manual/source/_static/to_alabaster.css index 3518cf2f7..cf2c82d78 100644 --- a/manual/source/_static/to_alabaster.css +++ b/manual/source/_static/to_alabaster.css @@ -2,14 +2,21 @@ /* Override sidebar background color default (#FFFFFF) */ .sphinxsidebar { - background: #283593 !important; + background: #55af31 !important; } /* #005F73 is the original NIAC sidebar colour */ +div.document { + margin-top: 0 !important; +} + +div.body { + margin-top: 30px !important; +} + /* Control logo positioning */ .sphinxsidebarwrapper p.logo { - margin-top: -8px !important; - margin-bottom: -8px !important; + padding: 15% !important; text-align: center !important; } diff --git a/manual/source/img/FAIRmat_new.png b/manual/source/img/FAIRmat_new.png index eeddabe3400c469ed1619f50d834533d2afc0303..e5b7158a781f014b5c2a7feeacfc72e32fd507f4 100644 GIT binary patch literal 10334 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 JDcT|Oe*jcWnZN)5 literal 24990 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 Date: Wed, 27 Sep 2023 08:09:17 +0200 Subject: [PATCH 013/136] Cleaner docs for NXmpes --- manual/source/mpes-structure.rst | 42 +++++++++++++------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index 3b0fd8394..dc0e4a75d 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -1,29 +1,21 @@ .. _Mpes-Structure-Fairmat: -============================================== -B2/B3: Photoemission & core-level spectroscopy -============================================== - -.. index:: - IntroductionMpes1 - MpesAppDef1 - -.. _IntroductionMpes1: - -Introduction -############ - -Set of data storage objects to describe photoemission experiments including x-ray photoelectron spectroscopy (XPS), ultraviolet photoelectron spectroscopy (UPS), -hard x-ray photoelectron spectroscopy (HAXPES), angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) -and photoemission electron microscopy (PEEM). We also included descriptors for advanced specializations, such as spin-resolution, time resolution, -near-ambient pressure conditions, dichroism etc. - -.. _MpesAppDef1: - -Application Definitions -####################### - -We created two new application definitions: +======================================= +Photoemission & core-level spectroscopy +======================================= + +The NXmpes application definition aims at describing any possible multidimensional PES setup. +Hence, it is very general and currently the only limitation to the data is that an energy +axis has to be present. +The general experimental techniques described by this application definitions are +photons in and photoelectrons out. +If you want NXmpes for such a techniques, changes are good you find something useful here. + +An example set of techniques covered by this application defintions are x-ray/UV photoelectron spectroscopy (XPS/UPS), +angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) or +photoemission electron microscopy (PEEM). +We also include descriptors for advanced specializations, such as spin- and time-resolution, near-ambient pressure conditions, +dichroism and many more. :ref:`NXmpes`: - A general appdef with minimalistic metadata requirements, apt to describe all photemission experiments. + A general appdef with minimalistic metadata requirements to describe all photemission experiments. From b85a7b6fcdeb661d84e84ae428efbdf947e0bfc9 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 10 Nov 2023 10:20:13 +0100 Subject: [PATCH 014/136] update mpes-structure.rst --- manual/source/mpes-structure.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index dc0e4a75d..a251bdc09 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -4,14 +4,14 @@ Photoemission & core-level spectroscopy ======================================= -The NXmpes application definition aims at describing any possible multidimensional PES setup. +The NXmpes application definition aims at describing data and metadata obtained with any possible multidimensional PES setup. Hence, it is very general and currently the only limitation to the data is that an energy axis has to be present. The general experimental techniques described by this application definitions are photons in and photoelectrons out. If you want NXmpes for such a techniques, changes are good you find something useful here. -An example set of techniques covered by this application defintions are x-ray/UV photoelectron spectroscopy (XPS/UPS), +Example techniques covered by this application definition include x-ray/UV photoelectron spectroscopy (XPS/UPS), angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) or photoemission electron microscopy (PEEM). We also include descriptors for advanced specializations, such as spin- and time-resolution, near-ambient pressure conditions, From 65b4da63464d0e8f7accf65c383d8bce96d136f6 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 10 Nov 2023 10:55:39 +0100 Subject: [PATCH 015/136] Update manual/source/mpes-structure.rst Co-authored-by: Florian Dobener --- manual/source/mpes-structure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index a251bdc09..809dd3401 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -8,7 +8,7 @@ The NXmpes application definition aims at describing data and metadata obtained Hence, it is very general and currently the only limitation to the data is that an energy axis has to be present. The general experimental techniques described by this application definitions are -photons in and photoelectrons out. +photon-in and photoelectron-out. If you want NXmpes for such a techniques, changes are good you find something useful here. Example techniques covered by this application definition include x-ray/UV photoelectron spectroscopy (XPS/UPS), From a44108684e23518206692bae458782a5430ff96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20K=C3=BChbach?= Date: Thu, 30 Nov 2023 20:19:51 +0100 Subject: [PATCH 016/136] Base class templates (#51) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactored cg_primitive base classes for two key aspects: i) make all primitives inherit from new base class NXcg_primitive_set which makes a substantial number of repeated properties of specialized primitive base classes unnecessary, ii) introducing a rigorous mathematical set theoretical approach to describe the number type N, N0, Z, R, R+, R, iii) introduce short hand notation to reduce writing costs for shape/dimensions of arrays: now numpy syntax is used, for scalars (), (1, can be omitted, experience in FAIRmat has shown that in almost all cases the optional doc string to a dimension was almost never used and thus yaml based descriptions can be written more succinct, iv) proof-read docstrings and shortened them, introduced the suggestion to use info: as a keyword which should for now be just appended to the docstring as usual but in the future should be treated as a comment, i.e. only meant for human contextualization but ignored for semantic interpretation of concepts, a key difference that I hope this will bring is to reduce also the length of base classes and appdef as they show up in html pages, specifically for appdefs like NXem many of the conceptual ideas which these docstrings currently contain would be much better placed in a proper documentation instead of the actual class definition in the hope that the overall appearance of classes becomes easier and faster for people to power read; maybe this also works against some criticism that NeXus is considered complex, I have to say with the outsourcing of NXcg_primitive_set I feel it is damn simple now * Refactoring of NXcs base classes * First lot of refactoring EM base classes, the rest tomorrow, NXapm will not be refactored before the APT&M2023 conference in Sept2023, also because feedback from Leoben was positive enough that no immediate changes wrt to appdefs and base classes were required * Summarize the current state of the discussion about coordinate systems with the proposed NXcoordinate_system and NXcoordinate_system_set base classes and best practice recommendations how they should be used including feedback from discussions with Florian Dobner and Tamás Haraszti * Summary of the discussion how to handle conventions and method-specific conventions for EM and methods used in EM * Base classes for implemented examples for pole figures, orientation distribution function, event_data, stage_lab, and ebsd_crystal_structure_model * NXms_ipf base class and dos2unix to correct newlines * Introducing NXem_method base class as a template how to write method-specific deep base classes to describe the terms and taxononmy of method-specific branches to be hooked into appdefs like NXem * Base class inheritance proposal for a now even stronger modularized schema set for electron microscopy research, two tasks remain: i) refactor what is now a method-specific instance rather than an appdef (NXem_ebsd) (mainly to be able to fuse all examples of em-specific data converters including new ebsd examples into one em parser for pynxtools), ii) refactor NXem which is now clearly a specific appdef specializing the NXem_base deep base class, specialization work needs to define which fields and groups from all the possible ones now composable via base classes (inheritance) are required in an appdef NXem for NOMAD OASIS * NXem_ebsd refactored into a base class to use it as a method-specific group inside the NXem application definition, next step: i) refactor NXem_sim, ii) finalize refactoring of NXem appdef (for Nomad oasis) * finished draft of NXem_ebsd, NXem_correlation, and NXem appdef, cleaning the branch * Add proposal for storing mtx cfg, fixed nxtime datatypes * 2d microstructure projection * Inspection how proposed, info, N0, N, R, Z value type abbreviations, and dimensions could be added to nyamlforward * A likely too simplistic but at least working nyaml2nxdl forward mapping to explore further usage of refactored EM base classes. Info keyword has to be a child of doc or the respective text be removed from the standard and put into proposal-specific documentation, how to store what and where so that the schema docstring remain succinct and slim but all these conceptual ideas get not forgotten, typically the would be part of a tech report, i.e. in my opinion all what is under info: sections of a docstring should move to some documentation to tell the story to humans, next test these NXDLs with the NeXus documentation system * Minor fix to handle info keyword spotted while compiling the documentation * Fixes to compile with NeXus documentation test suite and sphinx * Deactivated the annoying clean yaml via make clean for dev purposes * Minor fix in em_base, this completes the appdef/base class work for now on the refactored EM, there are still some spurious info fields now, which should be removed when a decision has been made wrt to how to deal with info: keyword fields in general, next steps: i) make decision on info, ii) test refactored EM proposal with pynxtools em-parser v2, iii) implement backwards * Styling via black * Added yaml2nxdl-forward-converted NXDL files to all refactored base classes and the refactored NXem * Added NXroot header for the em appdef and its base template appdef * Continuing the refactoring of EM and APM plus related base classes for CG and MS based on suggestions from user meetings, discussions with Sandor, represents work with the MPES sprint #83 * Continuing on #83 * Continuing #83, NXcs_* * Continuing #83, ipf, pf, odf * Continuing on #83, support classes for EM * Continued on #83, coordinate system, further base classes supporting EM * Continuing #83, event_data_set and event_data description substantially condensed amongst other points * Added cross-references to base classes for rst, continuing #83 * Aligned old NXem_ebsd_conventions with NXcoordinate_system for #83 * Reviewed method-specific base classes, ebsd, eds, eels, #83 * #83, NXms_recon * #83, composed constraints on the NXem appdef * Consolidated with changes that happened in between on the fairmat branch based on 1016aa0, NXms_recon has still an issue and is therefore deactivated currently, method-specific landing pages need to be updated * Consolidated further with fairmat 15624c0be77be13a * Fixing some missing references * Fixed syntax error to compile NXms_recon, docs building also now, reviewing intro pages remains * Consistencies of dimensionality to use NX_POSINT and an enumeration * Recompiled NXDL files using new nyaml module 3d500ced7e4ca57683957c1d61a8d0cb62eccf53, removed, modified by taking the one from fairmat, and synced all files which were binarily different between this feature branch and the fairmat branch specifically commit a15798bab795d92b587527f2cff0819e26f550ee of the fairmat branch * Deactivated em-based tests which because of a refactoring of em are not expected to work anymore * Fix improper Latex notation in math environment for polyline, face_list, nanochem * Added recompiled NXidentifier, NXserialized NXDLs which triggered pipeline errors in CatChen gh action * Some round of proof-reading * Fixed test_nxdl_utils to reflect and use refactored locations of refactored NXem * Added feedback from @phyy-nx, @PeterC-DLS, and @prjemian from discussed here https://github.com/nexusformat/definitions PR #1271 * Black formatting * Reactivated data type check for e.g. NXem NX_NUMBER * Implementing NX_DATE_TIME suggestion of @sanbrock --------- Co-authored-by: markus.kuehbach # Conflicts: # contributed_definitions/NXaberration.nxdl.xml # contributed_definitions/NXaberration_model.nxdl.xml # contributed_definitions/NXaberration_model_ceos.nxdl.xml # contributed_definitions/NXaberration_model_nion.nxdl.xml # contributed_definitions/NXaperture_em.nxdl.xml # contributed_definitions/NXapm.nxdl.xml # contributed_definitions/NXapm_paraprobe_results_nanochem.nxdl.xml # contributed_definitions/NXcg_alpha_complex.nxdl.xml # contributed_definitions/NXcg_cylinder_set.nxdl.xml # contributed_definitions/NXcg_ellipsoid_set.nxdl.xml # contributed_definitions/NXcg_face_list_data_structure.nxdl.xml # contributed_definitions/NXcg_geodesic_mesh.nxdl.xml # contributed_definitions/NXcg_grid.nxdl.xml # contributed_definitions/NXcg_half_edge_data_structure.nxdl.xml # contributed_definitions/NXcg_hexahedron_set.nxdl.xml # contributed_definitions/NXcg_marching_cubes.nxdl.xml # contributed_definitions/NXcg_parallelogram_set.nxdl.xml # contributed_definitions/NXcg_point_set.nxdl.xml # contributed_definitions/NXcg_polygon_set.nxdl.xml # contributed_definitions/NXcg_polyhedron_set.nxdl.xml # contributed_definitions/NXcg_polyline_set.nxdl.xml # contributed_definitions/NXcg_roi_set.nxdl.xml # contributed_definitions/NXcg_sphere_set.nxdl.xml # contributed_definitions/NXcg_tetrahedron_set.nxdl.xml # contributed_definitions/NXcg_triangle_set.nxdl.xml # contributed_definitions/NXcg_triangulated_surface_mesh.nxdl.xml # contributed_definitions/NXcg_unit_normal_set.nxdl.xml # contributed_definitions/NXchamber.nxdl.xml # contributed_definitions/NXcoordinate_system_set.nxdl.xml # contributed_definitions/NXcorrector_cs.nxdl.xml # contributed_definitions/NXcs_computer.nxdl.xml # contributed_definitions/NXcs_filter_boolean_mask.nxdl.xml # contributed_definitions/NXcs_io_obj.nxdl.xml # contributed_definitions/NXcs_io_sys.nxdl.xml # contributed_definitions/NXcs_mm_sys.nxdl.xml # contributed_definitions/NXcs_prng.nxdl.xml # contributed_definitions/NXcs_profiling.nxdl.xml # contributed_definitions/NXcs_profiling_event.nxdl.xml # contributed_definitions/NXdeflector.nxdl.xml # contributed_definitions/NXebeam_column.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_conventions.nxdl.xml # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXem_ebsd_crystal_structure_model.nxdl.xml # contributed_definitions/NXevent_data_em.nxdl.xml # contributed_definitions/NXevent_data_em_set.nxdl.xml # contributed_definitions/NXfabrication.nxdl.xml # contributed_definitions/NXgraph_edge_set.nxdl.xml # contributed_definitions/NXgraph_node_set.nxdl.xml # contributed_definitions/NXgraph_root.nxdl.xml # contributed_definitions/NXibeam_column.nxdl.xml # contributed_definitions/NXimage_set.nxdl.xml # contributed_definitions/NXimage_set_em_adf.nxdl.xml # contributed_definitions/NXimage_set_em_kikuchi.nxdl.xml # contributed_definitions/NXion.nxdl.xml # contributed_definitions/NXisocontour.nxdl.xml # contributed_definitions/NXlens_em.nxdl.xml # contributed_definitions/NXms.nxdl.xml # contributed_definitions/NXms_feature_set.nxdl.xml # contributed_definitions/NXms_score_results.nxdl.xml # contributed_definitions/NXoptical_system_em.nxdl.xml # contributed_definitions/NXorientation_set.nxdl.xml # contributed_definitions/NXpump.nxdl.xml # contributed_definitions/NXrotation_set.nxdl.xml # contributed_definitions/NXscanbox_em.nxdl.xml # contributed_definitions/NXspectrum_set.nxdl.xml # contributed_definitions/NXspectrum_set_em_eels.nxdl.xml # contributed_definitions/NXspectrum_set_em_xray.nxdl.xml # contributed_definitions/NXstage_lab.nxdl.xml # contributed_definitions/nyaml/NXaberration.yaml # contributed_definitions/nyaml/NXaberration_model.yaml # contributed_definitions/nyaml/NXaberration_model_ceos.yaml # contributed_definitions/nyaml/NXaberration_model_nion.yaml # contributed_definitions/nyaml/NXaperture_em.yaml # contributed_definitions/nyaml/NXapm.yaml # contributed_definitions/nyaml/NXapm_paraprobe_results_nanochem.yaml # contributed_definitions/nyaml/NXcg_alpha_complex.yaml # contributed_definitions/nyaml/NXcg_cylinder_set.yaml # contributed_definitions/nyaml/NXcg_ellipsoid_set.yaml # contributed_definitions/nyaml/NXcg_face_list_data_structure.yaml # contributed_definitions/nyaml/NXcg_geodesic_mesh.yaml # contributed_definitions/nyaml/NXcg_grid.yaml # contributed_definitions/nyaml/NXcg_half_edge_data_structure.yaml # contributed_definitions/nyaml/NXcg_hexahedron_set.yaml # contributed_definitions/nyaml/NXcg_marching_cubes.yaml # contributed_definitions/nyaml/NXcg_parallelogram_set.yaml # contributed_definitions/nyaml/NXcg_point_set.yaml # contributed_definitions/nyaml/NXcg_polygon_set.yaml # contributed_definitions/nyaml/NXcg_polyhedron_set.yaml # contributed_definitions/nyaml/NXcg_polyline_set.yaml # contributed_definitions/nyaml/NXcg_roi_set.yaml # contributed_definitions/nyaml/NXcg_sphere_set.yaml # contributed_definitions/nyaml/NXcg_tetrahedron_set.yaml # contributed_definitions/nyaml/NXcg_triangle_set.yaml # contributed_definitions/nyaml/NXcg_triangulated_surface_mesh.yaml # contributed_definitions/nyaml/NXcg_unit_normal_set.yaml # contributed_definitions/nyaml/NXchamber.yaml # contributed_definitions/nyaml/NXcoordinate_system_set.yaml # contributed_definitions/nyaml/NXcorrector_cs.yaml # contributed_definitions/nyaml/NXcs_computer.yaml # contributed_definitions/nyaml/NXcs_filter_boolean_mask.yaml # contributed_definitions/nyaml/NXcs_io_obj.yaml # contributed_definitions/nyaml/NXcs_io_sys.yaml # contributed_definitions/nyaml/NXcs_mm_sys.yaml # contributed_definitions/nyaml/NXcs_prng.yaml # contributed_definitions/nyaml/NXcs_profiling.yaml # contributed_definitions/nyaml/NXcs_profiling_event.yaml # contributed_definitions/nyaml/NXdeflector.yaml # contributed_definitions/nyaml/NXebeam_column.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXevent_data_em.yaml # contributed_definitions/nyaml/NXevent_data_em_set.yaml # contributed_definitions/nyaml/NXfabrication.yaml # contributed_definitions/nyaml/NXgraph_edge_set.yaml # contributed_definitions/nyaml/NXgraph_node_set.yaml # contributed_definitions/nyaml/NXgraph_root.yaml # contributed_definitions/nyaml/NXibeam_column.yaml # contributed_definitions/nyaml/NXimage_set.yaml # contributed_definitions/nyaml/NXinteraction_vol_em.yaml # contributed_definitions/nyaml/NXion.yaml # contributed_definitions/nyaml/NXisocontour.yaml # contributed_definitions/nyaml/NXlens_em.yaml # contributed_definitions/nyaml/NXms.yaml # contributed_definitions/nyaml/NXms_feature_set.yaml # contributed_definitions/nyaml/NXms_score_results.yaml # contributed_definitions/nyaml/NXoptical_system_em.yaml # contributed_definitions/nyaml/NXpump.yaml # contributed_definitions/nyaml/NXrotation_set.yaml # contributed_definitions/nyaml/NXscanbox_em.yaml # contributed_definitions/nyaml/NXspectrum_set.yaml # contributed_definitions/nyaml/NXstage_lab.yaml # dev_tools/tests/test_nxdl_utils.py # manual/source/classes/contributed_definitions/cgms-structure.rst # manual/source/classes/contributed_definitions/em-structure.rst --- .../NXcg_primitive_set.nxdl.xml | 212 ++++++ .../NXcomponent_em.nxdl.xml | 69 ++ .../NXcoordinate_system.nxdl.xml | 143 ++++ .../NXcrystal_structure.nxdl.xml | 280 ++++++++ contributed_definitions/NXcs_cpu_obj.nxdl.xml | 39 ++ contributed_definitions/NXcs_cpu_sys.nxdl.xml | 48 ++ contributed_definitions/NXcs_gpu_obj.nxdl.xml | 39 ++ contributed_definitions/NXcs_gpu_sys.nxdl.xml | 47 ++ contributed_definitions/NXcs_mm_obj.nxdl.xml | 51 ++ contributed_definitions/NXem_adf.nxdl.xml | 65 ++ contributed_definitions/NXem_base.nxdl.xml | 389 +++++++++++ .../NXem_conventions_ebsd.nxdl.xml | 230 +++++++ .../NXem_correlation.nxdl.xml | 245 +++++++ .../NXem_ebsd_conventions.nxdl.xml | 610 ------------------ contributed_definitions/NXem_eds.nxdl.xml | 144 +++++ contributed_definitions/NXem_eels.nxdl.xml | 79 +++ contributed_definitions/NXem_img.nxdl.xml | 63 ++ contributed_definitions/NXem_method.nxdl.xml | 47 ++ contributed_definitions/NXem_msr.nxdl.xml | 96 +++ contributed_definitions/NXem_sim.nxdl.xml | 60 ++ .../NXimage_c_set.nxdl.xml | 247 +++++++ .../NXimage_r_set.nxdl.xml | 100 +++ .../NXimage_r_set_diff.nxdl.xml | 179 +++++ .../NXinteraction_vol_em.nxdl.xml | 66 +- contributed_definitions/NXms_ipf.nxdl.xml | 383 +++++++++++ contributed_definitions/NXms_ipf_set.nxdl.xml | 33 + .../NXms_mtex_config.nxdl.xml | 310 +++++++++ contributed_definitions/NXms_odf.nxdl.xml | 171 +++++ contributed_definitions/NXms_odf_set.nxdl.xml | 33 + contributed_definitions/NXms_pf.nxdl.xml | 111 ++++ contributed_definitions/NXms_pf_set.nxdl.xml | 33 + contributed_definitions/NXms_recon.nxdl.xml | 454 +++++++++++++ contributed_definitions/NXroi.nxdl.xml | 34 + .../nyaml/NXcg_primitive_set.yaml | 136 ++++ .../nyaml/NXcomponent_em.yaml | 39 ++ .../nyaml/NXcoordinate_system.yaml | 86 +++ .../nyaml/NXcrystal_structure.yaml | 178 +++++ .../nyaml/NXcs_cpu_obj.yaml | 12 + .../nyaml/NXcs_cpu_sys.yaml | 21 + .../nyaml/NXcs_gpu_obj.yaml | 12 + .../nyaml/NXcs_gpu_sys.yaml | 20 + .../nyaml/NXcs_mm_obj.yaml | 21 + contributed_definitions/nyaml/NXem_adf.yaml | 28 + contributed_definitions/nyaml/NXem_base.yaml | 297 +++++++++ .../nyaml/NXem_conventions.yaml | 296 +++++++++ .../nyaml/NXem_conventions_ebsd.yaml | 125 ++++ .../nyaml/NXem_correlation.yaml | 191 ++++++ contributed_definitions/nyaml/NXem_eds.yaml | 80 +++ contributed_definitions/nyaml/NXem_eels.yaml | 39 ++ contributed_definitions/nyaml/NXem_img.yaml | 25 + .../nyaml/NXem_method.yaml | 21 + contributed_definitions/nyaml/NXem_msr.yaml | 63 ++ contributed_definitions/nyaml/NXem_sim.yaml | 34 + .../nyaml/NXimage_c_set.yaml | 140 ++++ .../nyaml/NXimage_r_set.yaml | 45 ++ .../nyaml/NXimage_r_set_diff.yaml | 123 ++++ contributed_definitions/nyaml/NXms_ipf.yaml | 299 +++++++++ .../nyaml/NXms_ipf_set.yaml | 9 + .../nyaml/NXms_mtex_config.yaml | 187 ++++++ contributed_definitions/nyaml/NXms_odf.yaml | 99 +++ .../nyaml/NXms_odf_set.yaml | 9 + contributed_definitions/nyaml/NXms_pf.yaml | 59 ++ .../nyaml/NXms_pf_set.yaml | 9 + contributed_definitions/nyaml/NXms_recon.yaml | 315 +++++++++ contributed_definitions/nyaml/NXroi.yaml | 9 + .../icme-structure.rst | 11 +- 66 files changed, 7511 insertions(+), 637 deletions(-) create mode 100644 contributed_definitions/NXcg_primitive_set.nxdl.xml create mode 100644 contributed_definitions/NXcomponent_em.nxdl.xml create mode 100644 contributed_definitions/NXcoordinate_system.nxdl.xml create mode 100644 contributed_definitions/NXcrystal_structure.nxdl.xml create mode 100644 contributed_definitions/NXcs_cpu_obj.nxdl.xml create mode 100644 contributed_definitions/NXcs_cpu_sys.nxdl.xml create mode 100644 contributed_definitions/NXcs_gpu_obj.nxdl.xml create mode 100644 contributed_definitions/NXcs_gpu_sys.nxdl.xml create mode 100644 contributed_definitions/NXcs_mm_obj.nxdl.xml create mode 100644 contributed_definitions/NXem_adf.nxdl.xml create mode 100644 contributed_definitions/NXem_base.nxdl.xml create mode 100644 contributed_definitions/NXem_conventions_ebsd.nxdl.xml create mode 100644 contributed_definitions/NXem_correlation.nxdl.xml delete mode 100644 contributed_definitions/NXem_ebsd_conventions.nxdl.xml create mode 100644 contributed_definitions/NXem_eds.nxdl.xml create mode 100644 contributed_definitions/NXem_eels.nxdl.xml create mode 100644 contributed_definitions/NXem_img.nxdl.xml create mode 100644 contributed_definitions/NXem_method.nxdl.xml create mode 100644 contributed_definitions/NXem_msr.nxdl.xml create mode 100644 contributed_definitions/NXem_sim.nxdl.xml create mode 100644 contributed_definitions/NXimage_c_set.nxdl.xml create mode 100644 contributed_definitions/NXimage_r_set.nxdl.xml create mode 100644 contributed_definitions/NXimage_r_set_diff.nxdl.xml create mode 100644 contributed_definitions/NXms_ipf.nxdl.xml create mode 100644 contributed_definitions/NXms_ipf_set.nxdl.xml create mode 100644 contributed_definitions/NXms_mtex_config.nxdl.xml create mode 100644 contributed_definitions/NXms_odf.nxdl.xml create mode 100644 contributed_definitions/NXms_odf_set.nxdl.xml create mode 100644 contributed_definitions/NXms_pf.nxdl.xml create mode 100644 contributed_definitions/NXms_pf_set.nxdl.xml create mode 100644 contributed_definitions/NXms_recon.nxdl.xml create mode 100644 contributed_definitions/NXroi.nxdl.xml create mode 100644 contributed_definitions/nyaml/NXcg_primitive_set.yaml create mode 100644 contributed_definitions/nyaml/NXcomponent_em.yaml create mode 100644 contributed_definitions/nyaml/NXcoordinate_system.yaml create mode 100644 contributed_definitions/nyaml/NXcrystal_structure.yaml create mode 100644 contributed_definitions/nyaml/NXcs_cpu_obj.yaml create mode 100644 contributed_definitions/nyaml/NXcs_cpu_sys.yaml create mode 100644 contributed_definitions/nyaml/NXcs_gpu_obj.yaml create mode 100644 contributed_definitions/nyaml/NXcs_gpu_sys.yaml create mode 100644 contributed_definitions/nyaml/NXcs_mm_obj.yaml create mode 100644 contributed_definitions/nyaml/NXem_adf.yaml create mode 100644 contributed_definitions/nyaml/NXem_base.yaml create mode 100644 contributed_definitions/nyaml/NXem_conventions.yaml create mode 100644 contributed_definitions/nyaml/NXem_conventions_ebsd.yaml create mode 100644 contributed_definitions/nyaml/NXem_correlation.yaml create mode 100644 contributed_definitions/nyaml/NXem_eds.yaml create mode 100644 contributed_definitions/nyaml/NXem_eels.yaml create mode 100644 contributed_definitions/nyaml/NXem_img.yaml create mode 100644 contributed_definitions/nyaml/NXem_method.yaml create mode 100644 contributed_definitions/nyaml/NXem_msr.yaml create mode 100644 contributed_definitions/nyaml/NXem_sim.yaml create mode 100644 contributed_definitions/nyaml/NXimage_c_set.yaml create mode 100644 contributed_definitions/nyaml/NXimage_r_set.yaml create mode 100644 contributed_definitions/nyaml/NXimage_r_set_diff.yaml create mode 100644 contributed_definitions/nyaml/NXms_ipf.yaml create mode 100644 contributed_definitions/nyaml/NXms_ipf_set.yaml create mode 100644 contributed_definitions/nyaml/NXms_mtex_config.yaml create mode 100644 contributed_definitions/nyaml/NXms_odf.yaml create mode 100644 contributed_definitions/nyaml/NXms_odf_set.yaml create mode 100644 contributed_definitions/nyaml/NXms_pf.yaml create mode 100644 contributed_definitions/nyaml/NXms_pf_set.yaml create mode 100644 contributed_definitions/nyaml/NXms_recon.yaml create mode 100644 contributed_definitions/nyaml/NXroi.yaml diff --git a/contributed_definitions/NXcg_primitive_set.nxdl.xml b/contributed_definitions/NXcg_primitive_set.nxdl.xml new file mode 100644 index 000000000..ac451bdc6 --- /dev/null +++ b/contributed_definitions/NXcg_primitive_set.nxdl.xml @@ -0,0 +1,212 @@ + + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + The dimensionality of the space. + + + + + The cardinality of the set, i.e. the number of members. + + + + + Computational geometry description of a set of primitives in Euclidean space. + + Primitives must neither be degenerated nor self-intersect. + Individual primitives can differ in their properties (e.g. size, shape, rotation). + + + + + Hint to help resolve in which Euclidean coordinate system field values + like center or orientation are defined. + + + + + The dimensionality of the primitive set. + + + + + + + + + + The cardinality of the primitive set. + + + + + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + + Therefore, implicit identifier are completely defined by the value of + identifier_offset and cardinality. For example if identifier run from + -2 to 3 the value for identifier_offset is -2. + + For explicit indexing the field identifier has to be used. + Fortran-/Matlab- and C-/Python-style indexing have specific implicit + identifier conventions where identifier_offset is 1 and 0 respectively. + + + + + Identifier of each member for explicit indexing. + + + + + + + + The center of mass position of each primitive. + + + + + + + + + + True if the center is a center of mass. + + + + + + + + A qualitative description of the shape of each primitive. + + + + + + + + + Qualifier for the length of characteristic features of the primitive. + + Often the term length is associated with the assumption that one + edge is parallel to an axis of the coordinate system. + + + + + + + + Qualifier often used to describe the length of one characteristic edge + within the coordinate system. + + + + + + + + True if primitive is closed such that it has properties like area or volume. + + + + + + + + Volume of each primitive. + + Set to NaN if does not apply for primitives for which is_closed is False. + + + + + + + + Alias for surface_area of each primitive. + + Set to NaN if does not apply for primitives for which is_closed is False. + + + + + + + + Direction unit vector which points along the + longest principal axis of each primitive. + + Use the depends_on attribute to specify in which coordinate system + these direction unit vectors are defined. + + + + + + + + + + + diff --git a/contributed_definitions/NXcomponent_em.nxdl.xml b/contributed_definitions/NXcomponent_em.nxdl.xml new file mode 100644 index 000000000..bedba8b6f --- /dev/null +++ b/contributed_definitions/NXcomponent_em.nxdl.xml @@ -0,0 +1,69 @@ + + + + + + + Base class for components used in an electron microscope. + + The electron microscope can be a real one or a simulated microscope. + The key motivation behind this generalization is the observation that in all + cases a controlled electron beam is generated in reality or that beam is simulated + and this beam is then used or modified in a controlled manner for the purpose + of studying physical interaction mechanisms of the beam with matter. + Here it does not matter whether one considers a real specimen or a simulated one. + + Using a common description for the real experiment in the lab and - what is + typically a simplification of it - via a computer simulation, has the benefit + that many pieces of information can be stored in the same way. In effect, + users are guided with finding information and unnecessary descriptive + variety for what are exactly the same concept is avoided to work towards + more interoperability. + + Another motivation to make no fundamental distinction between a scanning and + a transmission electron microscope is that both are electron microscopes whose + components are often very similar. + + + + Given name to the component e.g stage, lens C1, etc. + + + + + Ideally, a (globally) unique persistent identifier, link, or text to a + resource which gives further details to this component. + If such resource does not exist, a free-text field to report + further details about the component is possible. + + + + + + + Collection of axis-based translations and rotations to describe the + location and geometry of the component in the instrument. + + + diff --git a/contributed_definitions/NXcoordinate_system.nxdl.xml b/contributed_definitions/NXcoordinate_system.nxdl.xml new file mode 100644 index 000000000..a8dcb8369 --- /dev/null +++ b/contributed_definitions/NXcoordinate_system.nxdl.xml @@ -0,0 +1,143 @@ + + + + + + Base class to detail a coordinate system (CS). + + Whenever possible, an instance of :ref:`NXcoordinate_system` should be used as + a member in an :ref:`NXcoordinate_system_set` and the name of the instance + should be this alias. This may support a process whereby jargon when talking + about coordinate systems and conventions may become cleaner for users + because it is not evident for people outside a lab that terms like e.g. + tip space or specimen space refer to the same coordinate system. + This is an example of jargon used in e.g. the field of atom + probe tomography. + + + + Human-readable field telling where the origin of this CS is. + Exemplar values could be *left corner of the lab bench*, *door-handle* + *pinhole through which the electron beam exists the pole piece*. + *barycenter of the triangle*, *center of mass of the stone*. + + + + + + An alternative name given to that coordinate system. + + + + + Coordinate system type. + + + + + + + + Handedness of the coordinate system if it is a Cartesian. + + + + + + + + + Possibility to define an alias for the name of the x-axis. + + + + + Human-readable field telling in which direction the x-axis points if that + instance of :ref:`NXcoordinate_system` has no reference to any parent and as such + is the mighty world reference frame. + + Exemplar values could be direction of gravity. + + + + + Base unit vector along the first axis which spans the coordinate system. + This axis is frequently referred to as the x-axis in real space and + the i-axis in reciprocal space. + + + + + + + + Possibility to define an alias for the name of the y-axis. + + + + + Human-readable field telling in which direction the y-axis points if that + instance of :ref:`NXcoordinate_system` has no reference to any parent and as such + is the mighty world reference frame. + + See docstring of x_alias for further details. + + + + + Base unit vector along the second axis which spans the coordinate system. + This axis is frequently referred to as the y-axis in real space and + the j-axis in reciprocal space. + + + + + + + + Possibility to define an alias for the name of the z-axis. + + + + + Human-readable field telling in which direction the z-axis points if that + instance of :ref:`NXcoordinate_system` has no reference to any parent and as such + is the mighty world reference frame. + + See docstring of x_alias for further details. + + + + + Base unit vector along the second axis which spans the coordinate system. + This axis is frequently referred to as the z-axis in real space and + the k-axis in reciprocal space. + + + + + + diff --git a/contributed_definitions/NXcrystal_structure.nxdl.xml b/contributed_definitions/NXcrystal_structure.nxdl.xml new file mode 100644 index 000000000..4baccda13 --- /dev/null +++ b/contributed_definitions/NXcrystal_structure.nxdl.xml @@ -0,0 +1,280 @@ + + + + + + + + + Number of reflectors (Miller crystallographic plane triplets). + + + + + Number of atom positions. + + + + + Dimensionality of the lattice. + + + + + Base class to describe the atomic crystal structure of a phase. + + This base class contains key metadata that are relevant parameter to every + physics-based model to simulate radiation matter interaction. + + Examples where such base class is useful are kinematic or dynamic + diffraction simulations of e.g. (Kikuchi or other type of) patterns. + + + + Detail in which reference frame the unit cell is defined. + + + + + Dimensionality of the lattice. + + + + + + + + + + Reference to another resource that was used for + instantiating this structure model. + + + + + Crystallography unit cell parameters a, b, and c. + + + + + + + + + Crystallography unit cell parameters alpha, beta, and gamma. + + + + + + + + Area of the unit cell considering that d = 2. + + + + + Volume of the unit cell considering that d = 3. + + + + + Crystal system + + + + + + + + + + + + + + + Laue group using International Table of Crystallography Notation. + + + + + + Point group using International Table of Crystallography Notation. + + + + + + Space group from the International Table of Crystallography Notation. + + + + + + True if space group is considered a centrosymmetric one. + False if space group is considered a non-centrosymmetric one. + Centrosymmetric has all types and combinations of symmetry elements + (translation, rotational axis, mirror planes, center of inversion) + Non-centrosymmetric compared to centrosymmetric is constrained (no inversion). + Chiral compared to non-centrosymmetric is constrained (no mirror planes). + + + + + True if space group is considered a chiral one. + False if space group is consider a non-chiral one. + + + + + Identifier for each phase. + + The value 0 is reserved for the unknown phase that represents the + null-model no sufficiently significant confirmation. In other words, + the phase_name is n/a, notIndexed. + + The phase identifier value has to match with the integer postfix of the + group name which represents that instance in a NeXus/HDF5 file, i.e. + if two phases were used e.g. 0 and 1, two instances of an + :ref:`NXcrystal_structure` named phase0 and phase1 + should be stored in the HDF5 file. + + + + + + Name of the phase/alias. + + If the phase_identifier is 0 and one would like to use the field + phase_name the value should be n/a. + + + + + Label for each atom position. + + + + + + + + The hash value :math:`H` is :math:`H = Z + N*256` with :math:`Z` + the number of protons and :math:`N` the number of neutrons + of each isotope respectively. Z and N have to be 8-bit unsigned integers. + For the rationale behind this `M. Kühbach et al. (2021) <https://doi.org/10.1017/S1431927621012241>`_ + + + + + + + + + Atom positions. + + + + + + + + Reference to an instance of :ref:`NXcoordinate_system` + whereby the positions can be resolved. + + + + + + + Relative occupancy of the atom position. + + + + + + + + How many reflectors are distinguished. + + Value has to match value for symbol n_hkl. + + + + + + Miller indices :math:`(hkl)[uvw]` of the planes. + + The first triplet specify :math:`(hkl)` the second triplet :math:`[uvw]`. + Miller indices refer to the Cartesian right-handed coordinate system + of the unit cell. + + + + + + + + + Spacing between crystallographic planes as defined by field miller. + + + + + + + + Relative intensity of the signal for the plane. + + + + + + + + In case the :ref:`NXcrystal_structure` base class is used + with analyzed orientation maps this field stores how many scan points + of the map were identified as that phase. + + + + + + + diff --git a/contributed_definitions/NXcs_cpu_obj.nxdl.xml b/contributed_definitions/NXcs_cpu_obj.nxdl.xml new file mode 100644 index 000000000..6ce5370a3 --- /dev/null +++ b/contributed_definitions/NXcs_cpu_obj.nxdl.xml @@ -0,0 +1,39 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a (central) processing unit (C)PU of a computer. + + + + Given name of the CPU. Users should be as specific as possible. + + + + diff --git a/contributed_definitions/NXcs_cpu_sys.nxdl.xml b/contributed_definitions/NXcs_cpu_sys.nxdl.xml new file mode 100644 index 000000000..0de162c66 --- /dev/null +++ b/contributed_definitions/NXcs_cpu_sys.nxdl.xml @@ -0,0 +1,48 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a system of classical central processing units. + + For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. + + + + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single CPU one + could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of + :ref:`NXcs_cpu_sys`. + A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` + inside one instance of :ref:`NXcs_cpu_sys`. + A server with two dual-socket server nodes one could describe + with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. + + + diff --git a/contributed_definitions/NXcs_gpu_obj.nxdl.xml b/contributed_definitions/NXcs_gpu_obj.nxdl.xml new file mode 100644 index 000000000..3c5b6c26a --- /dev/null +++ b/contributed_definitions/NXcs_gpu_obj.nxdl.xml @@ -0,0 +1,39 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a graphic processing unit (GPU) of a computer. + + + + Given name of the GPU. Users should be as specific as possible. + + + + diff --git a/contributed_definitions/NXcs_gpu_sys.nxdl.xml b/contributed_definitions/NXcs_gpu_sys.nxdl.xml new file mode 100644 index 000000000..217f1adb2 --- /dev/null +++ b/contributed_definitions/NXcs_gpu_sys.nxdl.xml @@ -0,0 +1,47 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a system of coprocessor or graphics processors. + + + + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single GPU one + could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of + :ref:`NXcs_gpu_sys`. + A desktop computer with two GPUs one could describe using two instances + of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. + A GPU server like nowadays used for artificial intelligence + one could describe as a system with n instances of :ref:`NXcs_gpu_obj` + in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. + + + diff --git a/contributed_definitions/NXcs_mm_obj.nxdl.xml b/contributed_definitions/NXcs_mm_obj.nxdl.xml new file mode 100644 index 000000000..e2b247079 --- /dev/null +++ b/contributed_definitions/NXcs_mm_obj.nxdl.xml @@ -0,0 +1,51 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Computer science description of a memory in a memory system. + + + + Qualifier for the type of random access memory. + + + + + + Total amount of data which the medium can hold. + + + + + + Given name to the I/O unit. + + + + diff --git a/contributed_definitions/NXem_adf.nxdl.xml b/contributed_definitions/NXem_adf.nxdl.xml new file mode 100644 index 000000000..64534699c --- /dev/null +++ b/contributed_definitions/NXem_adf.nxdl.xml @@ -0,0 +1,65 @@ + + + + + + + + Number of images in the stack. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + + + Base class method-specific for annular dark field imaging. + + In the majority of cases simple d-dimensional regular scan patterns are used + to probe a region-of-interest (ROI). Examples can be single point aka spot + measurements, line profiles, or (rectangular) surface mappings. + The latter pattern is the most frequently used. + + For now the base class provides for scans for which the settings, + binning, and energy resolution is the same for each scan point. + + + + + Annulus inner (first value) and outer (second value) half angle. + + + + + + + + diff --git a/contributed_definitions/NXem_base.nxdl.xml b/contributed_definitions/NXem_base.nxdl.xml new file mode 100644 index 000000000..479819893 --- /dev/null +++ b/contributed_definitions/NXem_base.nxdl.xml @@ -0,0 +1,389 @@ + + + + + + + + Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. + + This base class combines a method-specific and technical-design-level base class + instance to provide a template for storing parameterized descriptions of + pieces of information collected when performing electron microscopy research. + + The base class here shows all possible branches without making any statements + as to which of these have to be used in an instance. Thereby, the base class + provides a template how to name and structure concepts in a hierarchy + to support finding information and reducing the need for renaming and + restructuring information for a research field where many scientists perform + very specific research but who all also share commonalities like usage of + controlled electron beams, a focus on studies of electron beam matter interaction + to explore physical mechanisms and phenomena, or the desire to characterize materials + using electron microscopy. + + + + A collection of all programs and libraries which are considered relevant + to understand with which software tools this NeXus file instance was + generated. Ideally, to enable a binary recreation from the input data. + + Examples include the name and version of the libraries used to write the + instance. Ideally, the software that writes these :ref:`NXprogram` instances + also includes the version of the set of NeXus classes i.e. the specific + set of base classes, application definitions, and contributed definitions + with which the here described concepts can be resolved. + + For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ + which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ + research data management system, it makes sense to store e.g. the GitHub + repository commit and respective submodule references used. + + + + + + The configuration of the I/O writer software (e.g. `pynxtools <https://github.com/FAIRmat-NFDI/pynxtools>`_) + which was used to generate this NeXus file instance. + + + + + + An at least as strong as SHA256 hashvalue of the file + which specifies the application definition. + + + + + NeXus NXDL schema to which this file conforms. + + + + + + + + Ideally, a (globally) unique persistent identifier + for referring to this experiment. + + An experiment should be understood in that this can be an experiment + in reality or a computer simulation because also the latter is an + experiment (see the Cambridge Dictionary experiment: + *a test done in order to find out something, eg if an idea is correct*). + + The identifier is usually issued by the facility, laboratory, + or the principle investigator. The identifier enables to link + experiments/simulations to e.g. proposals. + + + + + Free-text description about the experiment. + + Users are strongly advised to parameterize their description of the + experiment by using the respective base classes instead of writing prose + into this field. + + The reason is that such free-text field is difficult to machine-interpret. + The motivation behind keeping this field for now is to learn through + the information entered in this field in how far the current base + classes are incomplete. + + + + + ISO 8601 time code with local time zone offset to UTC information included + when the microscope session started. If the application demands that time + codes in this section of the application definition should only be used + for specifying when the experiment was performed - and the exact + duration is not relevant - this start_time field should be used. + + Often though it is useful to specify a time interval via setting both + a start_time and an end_time because this enables software tools and + users to collect a more detailed bookkeeping of the experiment. + + The user should be aware that even with having both time instances specified, + it may not be possible to infer how long the experiment took or for how + long data were acquired. + + More detailed timing data over the course of the experiment have + to be collected to compute this. These computations can take + advantage of individual time stamps start_time and end_time + in :ref:`NXevent_data_em` instances. + + + + + ISO 8601 time code with local time zone offset to UTC included when + the microscope session ended. See docstring of the start_time field + to see how the start_time and end_time should be used together. + + + + + + The program and eventual software libraries used with which the + NeXus instance was created. For the NOMAD OASIS research data + management system e.g. pynxtools and eventually all modules + if desired. + + + + + + Possibility to store a collection of data artifacts + associated with the experiment. + + + + + + Contact information and eventually details of at least one person + who performed or was involved in the session. This can be the + principle investigator who performed this experiment or the student + who performed the simulation. + Adding multiple users if relevant is recommended. + + + + Given (first) name and surname of the user. + + + + + Name of the affiliation of the user at the point in time + when the experiment was performed. + + + + + Postal address of the affiliation. + + + + + Email address of the user at the point in time when the experiment + was performed. Writing the most permanently used email is recommended. + + + + + Service as another mean of identification of a user than by the name. + Examples could be details about an ORCID or social media account of + the user. + + + + + (Business) (tele)phone number of the user at the point + in time when the experiment was performed. + + + + + Which role does the user have in the place and at the point + in time when the experiment was performed? Technician operating + the microscope, student, postdoc, principle investigator, or guest + are common examples. + + + + + + + A description of the material characterized in the experiment. + Sample and specimen are threaded as de facto synonyms. + Samples can be real specimens or virtual (see method). + + + + A qualifier whether the sample is a real one or a + virtual one (in a computer simulation) + + + + + + + + + + Ideally, (globally) unique persistent identifier which distinguishes + the specimen from all others and especially the predecessor/origin + from where the specimen was cut. + + This field must not be used for an alias! Instead, use name. + + In cases where multiple specimens were loaded into the microscope, + the identifier has to resolve the specific sample, whose results are + stored by this :ref:`NXentry` instance, because a single NXentry should be + used only for the characterization of a single specimen. + + Details about the specimen preparation should be + stored in resources referring to parent_identifier. + + + + + Identifier of the sample from which the sample was cut or the string + *None*. The purpose of this field is to support functionalities + for tracking sample provenance via a research data management system. + + + + + ISO 8601 time code with local time zone offset to UTC information + when the specimen was prepared. + + Ideally, report the end of the preparation, i.e. the last known time + the measured specimen surface was actively prepared. Ideally, this + matches the last timestamp that is mentioned in the digital resource + pointed to by parent_identifier. + + Knowing when the specimen was exposed to e.g. specific atmosphere is + especially required for environmentally sensitive material such as + hydrogen charged specimens or experiments including tracers with a + short half time. Additional time stamps prior to preparation_date + should better be placed in resources which describe but which do not pollute + the description here with prose. Resolving these connected pieces of information + is considered within the responsibility of the research data management + system. + + + + + An alias used to refer to the specimen to please readability for humans. + + + + + List of comma-separated elements from the periodic table that are + contained in the sample. If the sample substance has multiple + components, all elements from each component must be included in + `atom_types`. + + The purpose of the field is to offer research data management systems an + opportunity to parse the relevant elements without having to interpret + these from the resources pointed to by parent_identifier or walk through + eventually deeply nested groups in data instances. + + + + + + (Measured) sample thickness. + + The information is recorded to qualify if the beam used was likely + able to shine through the specimen. For scanning electron microscopy, + in many cases the specimen is typically thicker than what is + illuminatable by the electron beam. + + In this case the value should be set to the actual thickness of + the specimen viewed for an illumination situation where the nominal + surface normal of the specimen is parallel to the optical axis. + + + + + + + (Measured) density of the specimen. + + For multi-layered specimens this field should only be used to describe + the density of the excited volume. For scanning electron microscopy + the usage of this field is discouraged and instead an instance of an + :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` + instances can provide a cleaner description of the relevant details + why one may wish to store the density of the specimen. + + + + + Discouraged free-text field to provide further detail although adding + parent_identifier and having a working research data management system + should provide this contextualization. + + + + + + + + + + + + A region-of-interest analyzed either during or after the session + for which specific processed data generated from the measured or the + simulated data are available. + + + + + + + + + + + + diff --git a/contributed_definitions/NXem_conventions_ebsd.nxdl.xml b/contributed_definitions/NXem_conventions_ebsd.nxdl.xml new file mode 100644 index 000000000..8a19f1e29 --- /dev/null +++ b/contributed_definitions/NXem_conventions_ebsd.nxdl.xml @@ -0,0 +1,230 @@ + + + + + + + Base class for method-specific conventions EBSD. + + This base class is expected to be used with :ref:`NXem_conventions`. + + This is the main issue which currently is not in all cases documented + and thus limits the interoperability and value of collected EBSD data. + Not communicating EBSD data with such contextual pieces of information + and the use of file formats which do not store this information is the + key unsolved problem. + + + + Details about the gnomonic projection reference frame. + + + + Type of coordinate system/reference frame used for identifying + positions in the gnomonic projection space Xg, Yg, Zg + according to DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + Handedness of coordinate system. + + + + + + + + + Is the origin of the gnomonic coordinate system located + where we assume the location of the pattern centre. + This is the location Xg = 0, Yg = 0, Zg = 0 according to + reference DOI: 10.1016/j.matchar.2016.04.008. + + + + + + + + + Direction of the positively pointing "gnomomic" x-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + + + + + + + + + + + + + + Direction of the positively pointing "gnomomic" y-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + Direction of the positively pointing "gnomomic" z-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + + + + + + + + + + + + + + + Details about the definition of the pattern centre + as a special point in the gnomonic projection reference frame. + + + + From which border of the EBSP (in the detector reference frame) + is the pattern centre's x-position (PCx) measured? + Keywords assume the region-of-interest is defined by + a rectangle. We observe this rectangle and inspect the + direction of the outer-unit normals to the edges of + this rectangle. + + + + + + + + + + + + In which direction are positive values for PCx measured from + the specified boundary. Keep in mind that the gnomonic space + is in virtually all cases embedded in the detector space. + Specifically, the XgYg plane is defined such that it is + embedded/laying inside the XdYd plane (of the detector + reference frame). + When the normalization direction is the same as e.g. the + detector x-axis direction, we state that we effectively + normalize in fractions of the width of the detector. + + The issue with terms like width and height is that these + degenerate if the detector region-of-interest is square-shaped. + This is why we should better avoid talking about width and height but + state how we would measure distances practically with a ruler and + how we then measure positive distances. + + + + + + + + + + + + From which border of the EBSP (in the detector reference + frame) is the pattern centre's y-position (PCy) measured? + For further details inspect the help button of + xaxis_boundary_convention. + + + + + + + + + + + + In which direction are positive values for PCy measured from + the specified boundary. + For further details inspect the help button of + xaxis_normalization_direction. + + + + + + + + + + + + diff --git a/contributed_definitions/NXem_correlation.nxdl.xml b/contributed_definitions/NXem_correlation.nxdl.xml new file mode 100644 index 000000000..58c0f6825 --- /dev/null +++ b/contributed_definitions/NXem_correlation.nxdl.xml @@ -0,0 +1,245 @@ + + + + + + Base class to combine different method-specific data in electron microscopy. + + This base class represent a template for documenting correlations + (spatial, temporal) between different method-specific results. + + + + Details about processing steps. + + + + + + Details about correlated or logically connected EBSD datasets. + + One important class of such correlated experiments are the so-called + (quasi) in-situ experiments. In this case the same or nearly the same ROI + gets analyzed via a repetitive sequence of thermomechanical treatment, + sample preparation, measurement, on-the-fly-indexing. Phenomena + investigated are recrystallization, strain accumulation, material damage. + Post-processing is required to correlate and reidentify eventual + microstructural features or local ROIs across several orientation maps. + + Another important class of correlated experiments are the so-called + serial-sectioning experiments. Here the same sample is measured + repetitively after polishing each time, to create a stack of + orientation data which can be reconstructed to a + three-dimensional volume ROI. + + Data can be correlated in time, position (spatial), or both (spatiotemporal). + + Spatial correlations between repetitively characterized regions-of-interests + are typically correlated using image registration and alignment algorithms. + For this typically so-called landmarks are used. These can be grains with + a very large size or specific shape, i.e. grains which are qualitatively + different enough to be used as a guide how images are shifted relative to + one another. Other commonly used landmarks are fiducial marks which are + milled into the specimen surface using focus-ion beam milling and/or various + types of indentation methods. + + As far as the same physical region-of-interest is just measured several times, + the additional issue of the depth increment is not a concern. However, correct + assumptions for the depth increment, amount of material removed along the milling + direction is relevant for accurate and precise three-dimensional (serial-sectioning) + correlations. For these studies it can be tricky though to assume or estimate + useful depth increments. Different strategies have been proposed like + calibrations, wedged-shaped landmarks and computer simulation assisted + assumption making. + + Despite the use of landmarks, there are many practical issues which make the + processing of correlations imprecise and inaccurate. Among these are drift + and shift of the specimen, instabilities of the holder, the beam, irrespective + of the source of the drift, charging effects, here specifically causing local + image distortions and rotations which may require special processing algorithms + to reduce such imprecisions. + + Time correlations face all of the above-mentioned issues surplus the challenge + that specific experimental protocols have to be used to ensure the material state + is observed at specific physical time. The example of quasi in-situ characterization + of crystal growth phenomena, a common topic in engineering or modern catalysis research + makes it necessary to consider that e.g. the target value for the desired annealing + temperature is not just gauged based on macroscopic arguments but considers + that transient effects take place. Heating or quenching a sample might thus might + not have been executed under conditions in the interaction volume as they are + documented and/or assumed. + + These issue cause that correlations have an error margin as to how accurately + respective datasets were not only just synced based on the geometry of the + region-of-interests and the time markers but also to asssure which physical + conditions the specimen experienced over the course of the measurements. + + The fourth example of the em_om reference implementation explores the use of the + correlation group with a serial-sectioning datasets that was collected by the + classical Inconel 100 dataset collected by M. D. Uchic and colleagues + (M. Groeber M, Haley BK, Uchic MD, Dimiduk DM, Ghosh S 3d reconstruction and + characterization of polycrystalline microstructures using a fib-sem system data set. + Mater Charac 2006, 57 259–273. 10.1016/j.matchar.2006.01.019M). + + This dataset was specifically relevant in driving forward the implementation + of the DREAM.3D software. DREAM.3D is an open-source software project for + post-processing and reconstructing, i.e. correlating sets of orientation + microscopy data foremost spatially. One focus of the software is the + (post-)processing of EBSD datasets. Another cutting edge tool with similar + scope but a commercial solution by Bruker is QUBE which was developed by + P. Konijnenberg and coworkers. + + Conceptually, software like DREAM.3D supports users with creating linear + workflows of post-processing tasks. Workflows can be instructed via the + graphical user interface or via so-called pipeline processing via command line + calls. DREAM.3D is especially useful because its internal system documents all + input, output, and parameter of the processing steps. This makes DREAM.3D a + good candidate to interface with tools like em_om parser. Specifically, DREAM.3D + documents numerical results via a customized HDF5 file format called DREAM3D. + Workflow steps and settings are stored as nested dictionaries in JSON syntax + inside a supplementary JSON file or alongside the data in the DREAM3D file. + DREAM.3D has a few hundred algorithms implemented. These are called filters + in DREAM.3D terminology. + + Users configure a workflow which instructs DREAM.3D to send the data through + a chain of predefined and configured filters. Given that for each analysis + the filter is documented via its version tags surplus its parameter and setting + via a controlled vocabulary, interpreting the content of a DREAM3D HDF5 file + is possible in an automated manner using a parser. This makes DREAM.3D analyses + repeatable and self-descriptive. A key limitation though is that most frequently + the initial set of input data come from commercial files like ANG. + This missing link between the provenance of these input files, their associated + creation as electron microscope session, is also what NXem_ebsd solves. + + Nevertheless, as this can be solved with e.g. NXem_ebsd we are convinced that + the DREAM.3D and the em_om parser can work productively together to realize + RDMS-agnostic parsing of serial-section analyses. + + The internal documentation of the DREAM.3D workflow also simplifies the + provenance tracking represented by an instance of NXem_ebsd as not every + intermediate results has to be stored. Therefore, the fourth example + focuses on the key result obtained from DREAM.3D - the reconstructed + and aligned three-dimensional orientation map. + + Usually, this result is the starting point for further post-processing + and characterization of structural features. As here orientation microscopy + is insofar scale invariant using DREAM.3D, NXem_ebsd, and em_om should + be useful for different characterization methods, such as EBSD, Transmission + Kikuchi Diffraction (TKD), Automated Crystal Orientation Mapping (ACOM), + Nanobeam Electron Diffraction (using commercial systems like NanoMegas ASTAR) + or open-source implementations of these techniques (such as via pyxem/orix). + + The result of orientation microscopy methods are maps of local orientation + and thermodynamic phase (crystal structure) pieces of information. Virtually + all post-processing of such results for structural features includes again + a workflow of steps which are covered though by the NXms partner application + definition. The respective source of the data in an instance of NXms can + again be a link or reference to an instance of NXem_ebsd to complete the + chain of provenance. + + + + + + Descriptor representing the image contrast. + + + + + + Title of the default plot. + + + + + Descriptor values displaying the ROI. + + + + + + + + + + Descriptor values. + + + + + + Calibrated coordinate along the z-axis. + + + + + + + Label for the z axis + + + + + + Calibrated coordinate along the y-axis. + + + + + + + Label for the y axis + + + + + + Calibrated coordinate along the x-axis. + + + + + + + Label for the x axis + + + + + + + diff --git a/contributed_definitions/NXem_ebsd_conventions.nxdl.xml b/contributed_definitions/NXem_ebsd_conventions.nxdl.xml deleted file mode 100644 index 7ef85f871..000000000 --- a/contributed_definitions/NXem_ebsd_conventions.nxdl.xml +++ /dev/null @@ -1,610 +0,0 @@ - - - - - - - Conventions for rotations and coordinate systems to interpret EBSD data. - - This is the main issue which currently is not in all cases documented - and thus limits the interoperability and value of collected EBSD data. - Not communicating EBSD data with such contextual pieces of information - and the use of file formats which do not store this information is the - key unsolved problem. - - - - - Mathematical conventions and materials-science-specific conventions - required for interpreting every collection of orientation data. - - - - Convention how a positive rotation angle is defined when viewing - from the end of the rotation unit vector towards its origin, - i.e. in accordance with convention 2 of - DOI: 10.1088/0965-0393/23/8/083501. - Counter_clockwise is equivalent to a right-handed choice. - Clockwise is equivalent to a left-handed choice. - - - - - - - - - - How are rotations interpreted into an orientation - according to convention 3 of - DOI: 10.1088/0965-0393/23/8/083501. - - - - - - - - - - How are Euler angles interpreted given that there are several - choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of - DOI: 10.1088/0965-0393/23/8/083501. - The most frequently used convention is ZXZ which is based on - the work of H.-J. Bunge but other conventions are possible. - - - - - - - - - To which angular range is the rotation angle argument of an - axis-angle pair parameterization constrained according to - convention 5 of DOI: 10.1088/0965-0393/23/8/083501. - - - - - - - - - Which sign convention is followed when converting orientations - between different parameterizations/representations according - to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. - - - - - - - - - - - Details about eventually relevant named directions that may - give reasons for anisotropies. The classical example is cold-rolling - where one has to specify which directions (rolling, transverse, and normal) - align how with the direction of the base vectors of the sample_reference_frame. - - - - Type of coordinate system and reference frame according to - convention 1 of DOI: 10.1088/0965-0393/23/8/083501. - - - - - - - - - - Direction of the positively pointing x-axis base vector of - the processing_reference_frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. - - - - - - - - - - - - - - Name or alias assigned to the x-axis base vector, e.g. rolling direction. - - - - - Direction of the positively pointing y-axis base vector of - the processing_reference_frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - - - - - - - - - - - - - - Name or alias assigned to the y-axis base vector, e.g. transverse direction. - - - - - Direction of the positively pointing z-axis base vector of - the processing_reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - - - - - - - - - - - - - - Name or alias assigned to the z-axis base vector, e.g. normal direction. - - - - - Location of the origin of the processing_reference_frame. - This specifies the location Xp = 0, Yp = 0, Zp = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - - - - - - - - - - - - - - - - - Details about the sample/specimen reference frame. - - - - Type of coordinate system and reference frame according to - convention 1 of DOI: 10.1088/0965-0393/23/8/083501. - The reference frame for the sample surface reference is used for - identifying positions on a (virtual) image which is formed by - information collected from an electron beam scanning the - sample surface. We assume the configuration is inspected by - looking towards the sample surface from a position that is - located behind the detector. - Reference DOI: 10.1016/j.matchar.2016.04.008 - The sample surface reference frame has coordinates Xs, Ys, Zs. - In three dimensions these coordinates are not necessarily - located on the surface of the sample as there are multiple - faces/sides of the sample. Most frequently though the coordinate - system here is used to define the surface which the electron - beam scans. - - - - - - - - - - Direction of the positively pointing x-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - - - - - - - - - - - - - - Direction of the positively pointing y-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - - - - - - - - - - - - - - Direction of the positively pointing z-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - - - - - - - - - - - - - - Location of the origin of the sample surface reference frame. - This specifies the location Xs = 0, Ys = 0, Zs = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - - - - - - - - - - - - - - - - - Details about the detector reference frame. - - - - Type of coordinate system/reference frame used for - identifying positions in detector space Xd, Yd, Zd, - according to DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - - Direction of the positively pointing x-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - - - - - - - - - - - - - - Direction of the positively pointing y-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - Direction of the positively pointing z-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - Where is the origin of the detector space reference - frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - - - - - - - - - - - - - - - - - Details about the gnomonic projection reference frame. - - - - Type of coordinate system/reference frame used for identifying - positions in the gnomonic projection space Xg, Yg, Zg - according to DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - - Direction of the positively pointing "gnomomic" x-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - - - - - - - - - - - - - - Direction of the positively pointing "gnomomic" y-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - Direction of the positively pointing "gnomomic" z-axis base - vector when viewing how the diffraction pattern looks on the - detector screen. We assume the configuration is inspected by - looking towards the sample surface from a position - that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - - - - - - - - - - - - - - Is the origin of the gnomonic coordinate system located - where we assume the location of the pattern centre. - This is the location Xg = 0, Yg = 0, Zg = 0 according to - reference DOI: 10.1016/j.matchar.2016.04.008. - - - - - - - - - - Details about the definition of the pattern centre - as a special point in the gnomonic projection reference frame. - - - - From which border of the EBSP (in the detector reference frame) - is the pattern centre's x-position (PCx) measured? - Keywords assume the region-of-interest is defined by - a rectangle. We observe this rectangle and inspect the - direction of the outer-unit normals to the edges of - this rectangle. - - - - - - - - - - - - In which direction are positive values for PCx measured from - the specified boundary. Keep in mind that the gnomonic space - is in virtually all cases embedded in the detector space. - Specifically, the XgYg plane is defined such that it is - embedded/laying inside the XdYd plane (of the detector - reference frame). - When the normalization direction is the same as e.g. the - detector x-axis direction, we state that we effectively - normalize in fractions of the width of the detector. - - The issue with terms like width and height is that these - degenerate if the detector region-of-interest is square-shaped. - This is why we should better avoid talking about width and height but - state how we would measure distances practically with a ruler and - how we then measure positive distances. - - - - - - - - - - - - From which border of the EBSP (in the detector reference - frame) is the pattern centre's y-position (PCy) measured? - For further details inspect the help button of - xaxis_boundary_convention. - - - - - - - - - - - - In which direction are positive values for PCy measured from - the specified boundary. - For further details inspect the help button of - xaxis_normalization_direction. - - - - - - - - - - - - diff --git a/contributed_definitions/NXem_eds.nxdl.xml b/contributed_definitions/NXem_eds.nxdl.xml new file mode 100644 index 000000000..735bfe897 --- /dev/null +++ b/contributed_definitions/NXem_eds.nxdl.xml @@ -0,0 +1,144 @@ + + + + + + + + + + Number of pixel along the y direction, the slow direction + + + + + Number of pixel along the x direction, the fast direction + + + + + Number of X-ray photon energy (bins), the fastest direction. + + + + + Number of identified elements + + + + + Number of peaks detected + + + + + Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). + + `IUPAC instead of Siegbahn notation <https://doi.org/10.1002/xrs.1300200308>`_ should be used. + + + + + Details about computational steps how peaks were indexed as elements. + + + + The program with which the indexing was performed. + + + + + Name and location of each X-ray line which was indexed as a known ion. + For each ion, an NXion instance should be created which specifies + the origin of the signal. For each ion also the relevant IUPAC notation + X-ray lines should be specified. + + + + + Associated lower :math:`[e_{min}, e_{max}]` bounds of the + energy which is assumed associated with this peak. + + + + + + + + Theoretical energy of the line according to IUPAC. + + + + + IUPAC notation identifier of the line which the peak represents. + + This can be a list of IUPAC notations for (the seldom) case that + multiple lines are grouped with the same peak. + + + + + + + + + + List of the names of identified elements. + + + + + + + + Individual element-specific EDS/EDX/EDXS/SXES mapping + + A composition map is an image whose intensities for each pixel are the + accumulated X-ray quanta *under the curve(s)* of a set of peaks. + + These element-specific EDS maps are NXimage_r_set instances + and need to be named with the name of the element from the + element_names field. + + + + + A list of NXpeak instance names whose X-ray quanta + where accumulated for each pixel which yields an element-specific + EDS map. + + + + + + + + + + diff --git a/contributed_definitions/NXem_eels.nxdl.xml b/contributed_definitions/NXem_eels.nxdl.xml new file mode 100644 index 000000000..c355f6fd6 --- /dev/null +++ b/contributed_definitions/NXem_eels.nxdl.xml @@ -0,0 +1,79 @@ + + + + + + + + Number of electron energy loss bins. + + + + + Base class method-specific for Electron Energy Loss Spectroscopy (EELS). + + + + + NXspectrum_set_em specialized for EELS. + + + + + + + + + + Energy loss. + + + + + + + + + Energy loss. + + + + + + + Energy loss. + + + + + + + diff --git a/contributed_definitions/NXem_img.nxdl.xml b/contributed_definitions/NXem_img.nxdl.xml new file mode 100644 index 000000000..ebf17380a --- /dev/null +++ b/contributed_definitions/NXem_img.nxdl.xml @@ -0,0 +1,63 @@ + + + + + + + + Number of images in the stack. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + + + Base class for method-specific generic imaging. + + In the majority of cases simple d-dimensional regular scan patterns are used + to probe a region-of-interest (ROI). Examples can be single point aka spot + measurements, line profiles, or (rectangular) surface mappings. + The latter pattern is the most frequently used. + + For now the base class provides for scans for which the settings, + binning, and energy resolution is the same for each scan point. + + + + Which imaging mode was used? + + + + + + + + diff --git a/contributed_definitions/NXem_method.nxdl.xml b/contributed_definitions/NXem_method.nxdl.xml new file mode 100644 index 000000000..086d4833d --- /dev/null +++ b/contributed_definitions/NXem_method.nxdl.xml @@ -0,0 +1,47 @@ + + + + + + + Base class to describe specific analysis methods in electron microscopy. + + This base class represent a template how specialized, deep, and method-specific + base classes can be defined with which an (NXem) application + definition gets equipped with specific groups to document method-specific + processing steps and report analyzed quantities. + + The template base class name :ref:`NXem_method` needs to be changed for each + method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. + + + + Details about processing steps. + + + + + + + diff --git a/contributed_definitions/NXem_msr.nxdl.xml b/contributed_definitions/NXem_msr.nxdl.xml new file mode 100644 index 000000000..a6442b1e2 --- /dev/null +++ b/contributed_definitions/NXem_msr.nxdl.xml @@ -0,0 +1,96 @@ + + + + + + Base class for collecting a session with a real electron microscope. + + For collecting data and experiments which are simulations of an + electron microscope use the :ref:`NXem_sim` base class. + + + + (Meta)data of the microscope and the lab in which it stands. + + This em_lab group differs from potential em_lab groups inside + :ref:`NXevent_data_em` instances in that here the more static descriptions + are kept while changing, i.e. time-dependent pieces of information are + logged, via the em_lab group inside the desired number of instances + of NXevent_data_em. + + While using an :ref:`NXevent_data_em` instance, users should store only those + settings about a component which are relevant to understand the current + state of the component. Here, current means for the time interval which + the event covers (as it is detailed via start_time and end_time) timestamps. + + For example it is not relevant to store in each :ref:`NXevent_data_em` + electron_source group again the details of the gun type and the manufacturer + but only the high-voltage value and that only if it is different from the value + that is specified in the em_lab section for the static settings. + + In effect, this defines an information inference hierarchy which starts + in an individual :ref:`NXevent_data_em` instance followed by a probing of the + static section. + + + + Given name of the microscope at the hosting institution. + This is an alias. Examples could be NionHermes, Titan, JEOL, + Gemini, etc. + + + + + Location of the lab or place where the instrument is installed. + Using GEOREF is preferred. + + + + + + + + + + Description of the type of the detector. + + Electron microscopes have typically multiple detectors. + Different technologies are in use like CCD, scintillator, + direct electron, CMOS, or image plate to name but a few. + + + + Instrument-specific alias/name + + + + + + + + + + diff --git a/contributed_definitions/NXem_sim.nxdl.xml b/contributed_definitions/NXem_sim.nxdl.xml new file mode 100644 index 000000000..f5f10b1b9 --- /dev/null +++ b/contributed_definitions/NXem_sim.nxdl.xml @@ -0,0 +1,60 @@ + + + + + + + Base class for simulating electron microscopy relevant beam-matter interaction. + + The concept behind this base class is to keep it as generic as possible + that simulations of electron/ion beam interaction with matter can be + represented. This base class is envisioned as the twin of the :ref:`NXem_msr` + base class. + + It is an attempt to test the idea if at some point one might even use the + same base class template to describe measurements and computer simulations + of electron microscopy. This idea is attractive because the only practical + difference between a description of a measurement with a microscope and a + computer simulation is that the latter is typically a substantially simplified + representation of the real microscope surplus the focus of the research + in such cases on specific questions. + + Such simplification can be with respect to the optical setup, typically the + ignoring of the fact that the electron beam is produced by a complex setup + of lenses while in simulations often single Einzel lenses are considered. + Dynamics of the environment like temperature fluctuation in a lab, vibrations, + users, and multiple detectors are typically either ignored or reduced in + complexity and number and coming with idealizations to keep the simulations + focused on the specific reason questions and efficiently numerically executable. + + + + Details about the simulation. + + + + + + + diff --git a/contributed_definitions/NXimage_c_set.nxdl.xml b/contributed_definitions/NXimage_c_set.nxdl.xml new file mode 100644 index 000000000..64c945c99 --- /dev/null +++ b/contributed_definitions/NXimage_c_set.nxdl.xml @@ -0,0 +1,247 @@ + + + + + + + + Number of images in the (hyper)stack. + + + + + Number of pixel per image in the slowest direction. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + + + Specialized base class container for reporting a set of images in reciprocal space. + + In practice, complex numbers are encoded via some formatted pair of real values. + Typically, fast Algorithms for computing Fourier Transformations (FFT) are + used to encode images in reciprocal (frequency) space. FFT libraries are used + for implementing the key functionalities of these mathematical operations. + + Different libraries use different representations and encoding of the + image computed. Details can be found in the respective sections of the + typical FFT libraries: + + * `FFTW by M. Frigo and S. G. Johnson <https://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial>`_ + * `Intel MKL by the Intel Co. <https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2023-0/fourier-transform-functions.html>`_ + * `cuFFT by the NVidia Co. <https://docs.nvidia.com/cuda/cufft/index.html>`_ + + Users are strongly advised to inspect carefully which specific conventions + their library uses to be able to store and modify the implementation of their + code so that the serialized representations as it is detailed + here for NeXus matches with their intention. + + One- and two-dimensional FFTs should use the stack(NXdata) instances. + Three-dimensional FFTs should use the hyperstack(NXdata) instances. + + + + + Image stack. + + + + Image intensity of the real part. + + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + + Pixel coordinate center along j direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + + + Image hyperstack. + + + + Image intensity of the real part. + + + + + + + + + + + Image intensity of the imaginary part. + + + + + + + + + + + Magnitude of the image intensity. + + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along k direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along j direction. + + + + + + + Coordinate along j direction. + + + + + + Pixel coordinate center along i direction. + + + + + + + Coordinate along i direction. + + + + + diff --git a/contributed_definitions/NXimage_r_set.nxdl.xml b/contributed_definitions/NXimage_r_set.nxdl.xml new file mode 100644 index 000000000..3ef371809 --- /dev/null +++ b/contributed_definitions/NXimage_r_set.nxdl.xml @@ -0,0 +1,100 @@ + + + + + + + + Number of images in the stack. + + + + + Number of pixel per image in the slow direction. + + + + + Number of pixel per image in the fast direction. + + + + + Specialized base class container for reporting a set of images in real space. + + + + + Image (stack). + + + + Image intensity values. + + + + + + + + + + Image identifier + + + + + + + Image identifier. + + + + + + Pixel coordinate center along y direction. + + + + + + + Coordinate along y direction. + + + + + + Pixel coordinate center along x direction. + + + + + + + Coordinate along x direction. + + + + + diff --git a/contributed_definitions/NXimage_r_set_diff.nxdl.xml b/contributed_definitions/NXimage_r_set_diff.nxdl.xml new file mode 100644 index 000000000..c9ff02c0d --- /dev/null +++ b/contributed_definitions/NXimage_r_set_diff.nxdl.xml @@ -0,0 +1,179 @@ + + + + + + + + Number of scanned points. Scan point may have none, one, or more pattern. + + + + + Number of diffraction pattern. + + + + + Number of pixel per pattern in the slow direction. + + + + + Number of pixel per pattern in the fast direction. + + + + + Base class specialized for reporting a cuboidal stack of diffraction pattern. + + Diffraction pattern, whether they were simulated or measured are the raw data + for computational workflows to characterize the phase and orientation + of crystalline regions in matter. + + Steps of post-processing the diffraction patterns should be documented using + method-specific specialized base classes. All eventual post-processing of + resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. + + To implement an example how this base class can be used we focused in FAIRmat + on Kikuchi diffraction pattern here specifically the research community + of Electron Backscatter Diffraction (EBSD). + + For this reason, this base class and related :ref:`NXem_base` classes extend the + work of `M. A. Jackson et al. <https://doi.org/10.1186/2193-9772-3-4>`_ + (one of the developers of DREAM.3D) and the H5OINA public file format developed by + `P. Pinard et al. <https://doi.org/10.1017/S1431927621006103>`_ with Oxford Instruments. + + Kikuchi pattern are typically collected with FIB/SEM microscopes, + for two- and three-dimensional orientation microscopy. + + For a detailed overview of these techniques see e.g. + + * `M. A. Groeber et al. <https://doi.org/10.1186/2193-9772-3-5>`_ + * `A. J. Schwartz et al. <https://doi.org/10.1007/978-1-4757-3205-4>`_ + * `P. A. Rottman et al. <https://doi.org/10.1016/j.mattod.2021.05.003>`_ + + Serial-sectioning demands a recurrent sequence of ion milling and measuring. + This suggests that each serial section is at least an own NXevent_data_em + instance. The three-dimensional characterization as such demands a computational + step where the maps for each serial section get cleaned, aligned, and registered + into an image stack. This image stack represents a digital model of the + inspected microstructural volume. Often this volume is called a (representative) + volume element (RVE). Several software packages exists for performing + these post-processing tasks. + + This example may inspire users of other types of diffraction methods. + + + + Category which type of diffraction pattern is reported. + + + + + + + + Collected diffraction pattern as an image stack. As raw and closest to the + first retrievable measured data as possible, i.e. do not use this + container to store already averaged, filtered or whatever post-processed + pattern unless these are generated unmodifiably in such manner by the + instrument given the way how the instrument and control software + was configured for your microscope session. + + + + Array which resolves the scan point to which each pattern belongs. + + Scan points are evaluated in sequence starting from scan point zero + until scan point n_sc - 1. Evaluating the cumulated of this array + decodes which pattern in intensity belongs to which scan point. + + Take an example with three scan points: The first scan point has one + pattern, the second has three pattern, the last scan point has no + pattern. In this case the scan_point_identifier are 0, 1, 1, 1. + The length of the scan_point_identifier array is four because four + pattern were measured in total. + + In most cases usually one pattern is averaged by the detector for + some amount of time and then reported as one pattern. + + + + + + + + Intensity of the diffraction pattern. + + + + + + + + + + Pattern intensity + + + + + + + Pattern are enumerated starting from 0 to n_p - 1. + + + + + + + Pattern identifier + + + + + + + diff --git a/contributed_definitions/NXinteraction_vol_em.nxdl.xml b/contributed_definitions/NXinteraction_vol_em.nxdl.xml index a6beeb648..59c71c10e 100644 --- a/contributed_definitions/NXinteraction_vol_em.nxdl.xml +++ b/contributed_definitions/NXinteraction_vol_em.nxdl.xml @@ -1,36 +1,56 @@ - + - + + - Base class for storing details about a modelled shape of interaction volume. + Base class for describing the interaction volume of particle-matter interaction. - The interaction volume is mainly relevant in scanning electron microscopy - when the sample is thick enough so that the beam is unable to illuminate - through the specimen. - Computer models like Monte Carlo or molecular dynamics / electron beam - interaction simulations can be used to qualify and/or quantify the shape of - the interaction volume. + Computer models like Monte Carlo or molecular dynamics / electron- or ion-beam + interaction simulations can be used to qualify and (or) quantify the shape of + the interaction volume. Results of such simulations can be summary statistics + or single-particle resolved sets of trajectories. Explicit or implicit descriptions are possible. - * An implicit description is via a set of electron/specimen interactions - represented ideally as trajectory data from the computer simulation. - * An explicit description is via an iso-contour surface using either - a simulation grid or a triangulated surface mesh of the approximated - iso-contour surface evaluated at specific threshold values. - Iso-contours could be computed from electron or particle fluxes through - an imaginary control surface (the iso-surface). - Threshold values can be defined by particles passing through a unit control - volume (electrons) or energy-levels (e.g. the case of X-rays). - Details depend on the model. - * Another explicit description is via theoretical models which may - be relevant e.g. for X-ray spectroscopy + * An implicit description is via a set of electron/specimen interactions + represented ideally as trajectory data from the computer simulation. + * An explicit description is via an iso-contour surface using either + a simulation grid or a triangulated surface mesh of the approximated + iso-contour surface evaluated at specific threshold values. + Iso-contours could be computed from electron or particle fluxes through + an imaginary control surface (the iso-surface). + Threshold values can be defined by particles passing through a unit control + volume (electrons) or energy-levels (e.g. the case of X-rays). + Details depend on the model. + * Another explicit description is via theoretical models which may + be relevant e.g. for X-ray spectroscopy Further details on how the interaction volume can be quantified is available in the literature for example: - * `S. Richter et al. <https://doi.org/10.1088/1757-899X/109/1/012014>`_ - * `J. Bünger et al. <https://doi.org/10.1017/S1431927622000083>`_ + * `S. Richter et al. <https://doi.org/10.1088/1757-899X/109/1/012014>`_ + * `J. Bünger et al. <https://doi.org/10.1017/S1431927622000083>`_ + * `J. F. Ziegler et al. <https://doi.org/10.1007/978-3-642-68779-2_5>`_ diff --git a/contributed_definitions/NXms_ipf.nxdl.xml b/contributed_definitions/NXms_ipf.nxdl.xml new file mode 100644 index 000000000..49568b0ac --- /dev/null +++ b/contributed_definitions/NXms_ipf.nxdl.xml @@ -0,0 +1,383 @@ + + + + + + + + + Number of pixel along the z slowest direction. + + + + + Number of pixel along the y slow direction. + + + + + Number of pixel along the x fast direction. + + + + + Number of RGB values along the fastest direction, always three. + + + + + Dimensionality of the mapping (either 2 or 3). + + + + + Base class to store an inverse pole figure (IPF) mapping (IPF map). + + + + Reference to the coordinate system whereby the projection_direction is defined. + + If the field depends_on is not provided but a parent of the instance + of this base class or its specialization defines an :ref:`NXcoordinate_system_set` + and exactly one :ref:`NXcoordinate_system`, the reference points to this system. + + If nothing is provided and none of the above-mentioned references pointing + in a parent, McStas is assumed. + + + + + The direction along which orientations are projected. + + + + + + + + Details about the original grid. + + Here original grid means the one onto which the IPF map was computed + when exported from the tech partner's file format representation. + + + + + Details about the grid onto which the IPF is recomputed. + + Rescaling the visualization of the IPF map may be needed to enable + visualization in specific software tools like H5Web. + The value specifies the fractional change of the spacing between + the original mapping and the scaled one. + + + + + How where orientation values at the location of the output grid + positions computed. + + Nearest neighbour means the orientation of the closed (Euclidean distance) + grid point of the input_grid was taken. + + + + + + + + Inverse pole figure mapping. + + Default inverse pole figure (IPF) plot of the data specific for each + phase. No ipf_mapID instances for non-indexed scan points as these are + by definition assigned the null phase with phase_identifier 0. + Inspect the definition of :ref:`NXcrystal_structure` and its field + phase_identifier for further details. + + Details about possible regridding and associated interpolation + during the computation of the IPF map visualization can be stored + using the input_grid, output_grid, and interpolation fields. + + The main purpose of this map is to offer a normalized default representation + of the IPF map for consumption by a research data management system (RDMS). + This is aligned with the first aim of :ref:`NXms_ipf`, to bring colleagues and + users of IPF maps together to discuss which pieces of information + need to be stored together. We are convinced a step-by-step design and + community-driven discussion about which pieces of information should + and/or need to be included is a practical strategy to work towards an + interoperable description and data model for exchanging IPF maps as specific + community-accepted tools to convey orientation maps. + + With this design the individual RDMS solutions and tools can still continue + to support specific custom data analyses workflow and routes but at least + there is one common understanding which enables also those users who are + not necessarily experts in all the details of the underlying techniques + can understand and thus eventually judge if the dataset is worth to be + reused or repurposed. + + + + + + Inverse pole figure color code for each map coordinate. + + + + + + + + + + Pixel center coordinate calibrated for step size along the z axis of the map. + + + + + + + + + Pixel center coordinate calibrated for step size along the y axis of the map. + + + + + + + + + Pixel center coordinate calibrated for step size along the x axis of the map. + + + + + + + + + + The color code which maps colors into orientation into the fundamental zone. + + For each stereographic standard triangle (SST), i.e. a rendering of the + fundamental zone of the crystal-symmetry-reduced orientation space + SO3, it is possible to define a color model which assigns each point in + the fundamental zone a color. + + Different mapping models are used. These implement (slightly) different + scaling relations. Differences exist across representations of tech partners. + + Differences are which base colors of the RGB color model are placed in + which extremal position of the SST and where the white point is located. + + For further details see: + + * [G. Nolze et al.](https://doi.org/10.1107/S1600576716012942) + * Srikanth Patala and coworkers"'" work and of others. + + Details are implementation-specific and not standardized yet. + + Given that the SST has a complicated geometry, it cannot yet be + visualized using tools like H5Web, which is why for now the matrix + of a rasterized image which is rendered by the backend tool gets + copied into an RGB matrix to offer a default plot. + + + + + + Inverse pole figure color code for each map coordinate. + + + + + + + + + + Pixel along the y-axis. + + + + + + + + + Pixel along the x-axis. + + + + + + + + + diff --git a/contributed_definitions/NXms_ipf_set.nxdl.xml b/contributed_definitions/NXms_ipf_set.nxdl.xml new file mode 100644 index 000000000..776eb0a6c --- /dev/null +++ b/contributed_definitions/NXms_ipf_set.nxdl.xml @@ -0,0 +1,33 @@ + + + + + + + Base class to group multiple :ref:`NXms_ipf` instances. + + A collection of inverse pole figure approximations. + + + diff --git a/contributed_definitions/NXms_mtex_config.nxdl.xml b/contributed_definitions/NXms_mtex_config.nxdl.xml new file mode 100644 index 000000000..a810d12b3 --- /dev/null +++ b/contributed_definitions/NXms_mtex_config.nxdl.xml @@ -0,0 +1,310 @@ + + + + + + Base class to store the configuration when using the MTex/Matlab software. + + MTex is a Matlab package for texture analysis used in the Materials and Earth Sciences. + See `R. Hielscher et al. <https://mtex-toolbox.github.io/publications>`_ and + the `MTex source code <https://github.com/mtex-toolbox>`_ for details. + + + + Reference frame and orientation conventions. + Consult the `MTex docs <https://mtex-toolbox.github.io/EBSDReferenceFrame.html>`_ for details. + + + + TODO with MTex developers + + + + + + TODO with MTex developers + + + + + + TODO with MTex developers + + + + + + TODO with MTex developers + + + + + + TODO with MTex developers + + + + + + + + + + + Settings relevant for generating plots. + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + True if MTex renders a scale bar with figures. + + + + + True if MTex renders a grid with figures. + + + + + Code for the function handle used for annotating pole figure plots. + + + + + TODO with MTex developers + + + + + + + + + TODO with MTex developers + + + + + + + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + + Miscellaneous other settings of MTex. + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + + + Miscellaneous settings relevant for numerics. + + + + Return value of the Matlab eps command. + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + + Miscellaneous settings relevant of the system where MTex runs. + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + TODO with MTex developers + + + + + + Collection of paths from where MTex reads information and code. + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + Absolute path to specific component of MTex source code. + + + + + List of file type suffixes for which MTex assumes + texture/pole figure information. + + + + + List of file type suffixes for which MTex assumes EBSD content. + + + + + diff --git a/contributed_definitions/NXms_odf.nxdl.xml b/contributed_definitions/NXms_odf.nxdl.xml new file mode 100644 index 000000000..988034557 --- /dev/null +++ b/contributed_definitions/NXms_odf.nxdl.xml @@ -0,0 +1,171 @@ + + + + + + + + Number of pixel per varphi section plot along the varphi_one fastest direction. + + + + + Number of pixel per varphi section plot along the capital_phi slow direction. + + + + + Number of pixel per varphi section plot along the varphi_two slowest direction. + + + + + Number of local maxima evaluated in the component analysis. + + + + + Base class to store an orientation distribution function (ODF) computation. + + + + Details about the algorithm used for computing the ODF. + + + + Point group of the crystal structure (International Table of Crystallography) + of the phase for which the here documented phase-dependent ODF was computed. + + + + + Point group assumed for processing-induced *sample symmetries*. + (according to International Table of Crystallography). + + + + + Halfwidth of the kernel. + + + + + Name of the kernel. + + + + + Resolution of the kernel. + + + + + + + Number of local maxima evaluated for the ODF. + + + + + + Euler angle representation of the kth-most maxima of the ODF + in decreasing order of the intensity maximum. + + + + + + + + + Disorientation threshold within which intensity of the ODF + is integrated for the component analysis. + + + + + Integrated ODF intensity within a theta-ball of SO3 about + each location as specified for each location in the order + and reported in the order of these locations. + + + + + + + + + Visualization of the ODF intensity as orthogonal sections through Euler space. + + This is one example of typical default plots used in the texture + community in Materials Engineering. + + Mind that the Euler space is a distorted space. Therefore, equivalent + orientations show intensity contributions in eventually multiple + locations. + + + + + ODF intensity at probed locations relative to + null model of a completely random texture. + + + + + + + + + + Pixel center angular position along the :math:`\varphi_1` direction. + + + + + + + + + Pixel center angular position along the :math:`\varphi_2` direction. + + + + + + + + + Pixel center angular position along the :math:`\Phi` direction. + + + + + + + + diff --git a/contributed_definitions/NXms_odf_set.nxdl.xml b/contributed_definitions/NXms_odf_set.nxdl.xml new file mode 100644 index 000000000..d41a609a8 --- /dev/null +++ b/contributed_definitions/NXms_odf_set.nxdl.xml @@ -0,0 +1,33 @@ + + + + + + + Base class to group multiple :ref:`NXms_odf` instances. + + A collection of orientation distribution function approximations. + + + diff --git a/contributed_definitions/NXms_pf.nxdl.xml b/contributed_definitions/NXms_pf.nxdl.xml new file mode 100644 index 000000000..9a627ac62 --- /dev/null +++ b/contributed_definitions/NXms_pf.nxdl.xml @@ -0,0 +1,111 @@ + + + + + + + + Number of pixel per pole figure in the slow direction. + + + + + Number of pixel per pole figure in the fast direction. + + + + + Base class to store a pole figure (PF) computation. + + + + Details about the algorithm that was used to compute the pole figure. + + + + Point group of the crystal structure of the phase for which the + here documented phase-dependent pole figure was computed + (according to International Table of Crystallography). + + + + + Point group assumed for processing induced *sample symmetries* + (according to International Table of Crystallography). + + + + + Halfwidth of the kernel. + + + + + Miller indices (:math:`(hkl)[uvw]`) to specify the pole figure. + + + + + Resolution of the kernel. + + + + + + Pole figure. + + + + + Pole figure intensity. + + + + + + + + + Pixel center along y direction in the equatorial plane of + a stereographic projection of the unit sphere. + + + + + + + + + Pixel center along x direction in the equatorial plane of + a stereographic projection of the unit sphere. + + + + + + + + diff --git a/contributed_definitions/NXms_pf_set.nxdl.xml b/contributed_definitions/NXms_pf_set.nxdl.xml new file mode 100644 index 000000000..3ca5fc000 --- /dev/null +++ b/contributed_definitions/NXms_pf_set.nxdl.xml @@ -0,0 +1,33 @@ + + + + + + + Base class to group multiple :ref:`NXms_pf` instances. + + A collection of pole figure approximations. + + + diff --git a/contributed_definitions/NXms_recon.nxdl.xml b/contributed_definitions/NXms_recon.nxdl.xml new file mode 100644 index 000000000..99e629ba2 --- /dev/null +++ b/contributed_definitions/NXms_recon.nxdl.xml @@ -0,0 +1,454 @@ + + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + + The number of crystal projections. + + + + + The number of interface projections. + + + + + The number of assumed triple junction projections aka triple points. + + + + + + The number of crystals. + + + + + The number of interfaces + + + + + The number of triple lines + + + + + The number of quadruple junctions. + + + + + Base class to describe discretized (micro)structural features of a material. + + One instance of this base class can be used to describe the current configuration + the base class does not include time-dependent descriptions for the sake of + clarity and because of the fact that virtually all simulations or experiments + probe time by sampling. Therefore, time-dependent state descriptions should + be realized with creating a set of :ref:`NXms_snapshot_set` with instances of + :ref:`NXms_snapshot` using e.g. :ref:`NXms_recon` base class instances. + + + + + The configuration and parameterization of the reconstruction algorithm + whereby the microstructural features were identified. + + + + + Dimensionality of the analysis. + + This field can be used e.g. by a research data management system + to identify if the described feature set specifies a + one-, two-, or three-dimensional feature set. + + + + + + + + + + Which algorithm is used to reconstruct the features. + + + + + + + + + + + Threshold to define at which disorientation angle to assume + two crystalline regions have a significant orientation difference + which warrants to argue that there is an interface between the + two regions. + + + + + + + + + + + + + Projections of crystals on the sample surface as typically + characterized with optical or electron microscopy. + + + + Reference to lines(NXcg_polyline_set) which supports the + discretized shape of each cross-sectioned crystal. + + Most microscopy techniques support to generate only a two-dimensional + representation (projection) of the characterized material. + + For true volumetric techniques use the specifically + specialized crystals :ref:`NXms_feature_set` instead. + See stereology literature for more details e.g. + E.E. Underwood's book entitled Quantitative Stereology + + + + + Number of crystals. + + + + + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + + + + + Identifier used for crystals for explicit indexing. + + + + + + + + How many phases are distinguished + + + + + Integer offset whereby the identifier of the first member + of the set differs from zero. + + + + + + Identifier used for phase for explicit indexing. + + + + + + + + + True, if the crystal makes contact with the edge of the ROI, + false otherwise. + + + + + + + + Average disorientation angle between individual orientation of the + crystal at probed positions (weighted by area of that position) versus + the average disorientation of the crystal. + + + + + + + + + Calibrated area of surrounded by the polyline about each crystal. + + + + + + + + + + Projections of grain or phase boundaries as typically sectioned + with optical or electron microscopy characterization. + + + + Reference to lines(NXcg_polyline_set) which supports the + discretized shape of each cross-sectioned crystal. + + Set of tuples of polyline segments which build the interface. + + + + + + Set of pairs of crystal_identifier resolved via depends_on which + are adjacent to each interface. + + + + + + + + The specific crystal_projections(NXms_feature_set) instance + to resolve crystal identifier. + + + + + + + Set of pairs of triple_point_identifier which the interface connects. + For 2D projections of 3D microstructural features a triple point is + physically only the projection of a triple line. + + + + + + + + The specific triple_line_projections(NXms_feature_set) instance + whereby to resolve triple_point identifier. + + + + + + + The length of the interface. + + This is not necessarily the same as the length of the individual + polyline segments whereby the interface is discretized. + + The actual coordinate system whereby the geometry is calibrated + with real physical dimensions is typically documented by the + depends_on attribute of the respective NXcg_primitive_set. + This depends_on attribute should point explicitly to an + instance of a :ref:`NXcoordinate_system` to support users as + much as possible with interpreting how and where the lines are + located in the reference frame. + + + + + + + + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + + + + + Identifier for each interface using explicit indexing. + + + + + + + + + + Projections of triple lines as typically characterized with optical + or electron microscopy. + + Mind that most specimens are thermo-chemo-mechanically treated before + they are characterized. Therefore, the projected crystal defects are + have physically no longer the same structure as in the bulk. + + Examples are manifest as effects such as thermal grooving, or relaxation + effects of an intersection between a triple line that is cut + by the specimen surface as these defects are then exposed typically + to a different atmosphere and hence have different thermodynamic boundary + conditions than of their true volumetric defects in the bulk. + + + + Reference to points(NXcg_point_set) which supports the + locations of these triple points. + + + + + + Number of triple points. + + + + + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + + + + + Identifier for each triple point using explicit indexing. + + + + + + + + Set of triple point identifiers. + + + + + + + The relevant points(NXcg_point_set) instance whereby to + resolve interface identifiers. + + + + + + Set of triplets of identifier of line-like features. + Each triplet resolves which three interface projections + the triple point connects. + + + + + + + + The specific interface_projections(NXms_feature_set) + instance whereby to resolve interface identifiers. + + + + + + + Triplet of identifier of polyline segments. Each triplet resolves + which three segments of polyline segments the triple junction connects. + + + + + + + + The specific lines(NXcg_polyline_set) instance to resolve + polyline segments. + + + + + + diff --git a/contributed_definitions/NXroi.nxdl.xml b/contributed_definitions/NXroi.nxdl.xml new file mode 100644 index 000000000..b77834bb6 --- /dev/null +++ b/contributed_definitions/NXroi.nxdl.xml @@ -0,0 +1,34 @@ + + + + + + Base class to describe a region-of-interest analyzed. + + + + Details about processing steps. + + + + diff --git a/contributed_definitions/nyaml/NXcg_primitive_set.yaml b/contributed_definitions/nyaml/NXcg_primitive_set.yaml new file mode 100644 index 000000000..586929596 --- /dev/null +++ b/contributed_definitions/nyaml/NXcg_primitive_set.yaml @@ -0,0 +1,136 @@ +category: base +doc: | + Computational geometry description of a set of primitives in Euclidean space. + + Primitives must neither be degenerated nor self-intersect. + Individual primitives can differ in their properties (e.g. size, shape, rotation). +# this base class defines common fields and properties of geometric primitives +# more complex primitive sets like NXcg_cylinder_set are considered specializations +# of NXcg_primitive_set. They contain all fields and groups which NXcg_primitive_set +# defines. This is an action of compositing an information set; an act of inheriting +# TODO:: many properties of non-degenerate primitives are in the number set +# R+ instead of in R+0 but currently NeXus does not allow for such value range +# constraints unless the coarsely discretized NX_INT, NX_POSINT, NX_FLOAT +# but there is no say NX_FLOAT+0 +# MK::but in computational geometry numerical precision matters as it defines +# whether objects numerically intersect or not and thus it can make a real difference +# if one stores triangles with 16, 32, or 64 bit precision, however: +# are two triangle_set instance A and B no longer conceptually triangle sets +# because A stores the positions of vertices using int8 while B stores such using float64 ? +# we here assume that we still conceptually talk that A and B are triangle sets +# but this brings at the level of the application definition the problem that if the +# precision is not properly constrainted a consuming application will not obtain +# the instances of the concept triangle_set with relevant high enough precision +# and thus neither the base class nor the application definition is specific enough +# for what it was designed in the first place - be specific about the requirements +# on your data... +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. + d: | + The dimensionality of the space. + c: | + The cardinality of the set, i.e. the number of members. +type: group +NXcg_primitive_set(NXobject): + # individual specializations like NXcg_polyline_set typically overwrite + # the meaning of the depends_on concept to build consistent inference chains + # to enable an instantiation of the actual geometric primitives + \@depends_on(NX_CHAR): + doc: | + Hint to help resolve in which Euclidean coordinate system field values + like center or orientation are defined. + dimensionality(NX_POSINT): + doc: | + The dimensionality of the primitive set. + unit: NX_UNITLESS + enumeration: [1, 2, 3] + cardinality(NX_POSINT): + doc: | + The cardinality of the primitive set. + unit: NX_UNITLESS + identifier_offset(NX_INT): + doc: | + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + + Therefore, implicit identifier are completely defined by the value of + identifier_offset and cardinality. For example if identifier run from + -2 to 3 the value for identifier_offset is -2. + + For explicit indexing the field identifier has to be used. + Fortran-/Matlab- and C-/Python-style indexing have specific implicit + identifier conventions where identifier_offset is 1 and 0 respectively. + unit: NX_UNITLESS + identifier(NX_INT): + doc: | + Identifier of each member for explicit indexing. + dim: (c,) # numpy style indexing + center(NX_NUMBER): + doc: | + The center of mass position of each primitive. + unit: NX_ANY + dim: (c, d) + # a depends_on to define in which coordinate system + is_center_of_mass(NX_BOOLEAN): + doc: | + True if the center is a center of mass. + dim: (c,) + shape(NX_NUMBER): + doc: | + A qualitative description of the shape of each primitive. + unit: NX_LENGTH + dim: (c, d) + length(NX_NUMBER): + doc: | + Qualifier for the length of characteristic features of the primitive. + + Often the term length is associated with the assumption that one + edge is parallel to an axis of the coordinate system. + unit: NX_LENGTH + dim: (c,) + width(NX_NUMBER): + doc: | + Qualifier often used to describe the length of one characteristic edge + within the coordinate system. + unit: NX_LENGTH + dim: (c,) + is_closed(NX_BOOLEAN): + doc: | + True if primitive is closed such that it has properties like area or volume. + dim: (c,) + volume(NX_NUMBER): + doc: | + Volume of each primitive. + + Set to NaN if does not apply for primitives for which is_closed is False. + unit: NX_VOLUME + dim: (c,) + area(NX_NUMBER): + doc: | + Alias for surface_area of each primitive. + + Set to NaN if does not apply for primitives for which is_closed is False. + unit: NX_AREA + dim: (c,) + orientation(NX_NUMBER): + doc: | + Direction unit vector which points along the + longest principal axis of each primitive. + + Use the depends_on attribute to specify in which coordinate system + these direction unit vectors are defined. + unit: NX_DIMENSIONLESS + dim: (c, d) + vertex_normal(NXcg_unit_normal_set): + edge_normal(NXcg_unit_normal_set): + face_normal(NXcg_unit_normal_set): + # roi(NXcg_parallelogram_set or NXcg_hexahedron_set) + # aabb(NXcg_parallelogram_set or NXcg_hexahedron_set) + # obb(NXcg_parallelogram_set or NXcg_hexahedron_set) + # MK::one could add (NXcg_parallelogram_set) and/or (NXcg_hexahedron_set) + # but then one would not give any hint at the base class level how to name diff --git a/contributed_definitions/nyaml/NXcomponent_em.yaml b/contributed_definitions/nyaml/NXcomponent_em.yaml new file mode 100644 index 000000000..78870cc26 --- /dev/null +++ b/contributed_definitions/nyaml/NXcomponent_em.yaml @@ -0,0 +1,39 @@ +category: base +doc: | + Base class for components used in an electron microscope. + + The electron microscope can be a real one or a simulated microscope. + The key motivation behind this generalization is the observation that in all + cases a controlled electron beam is generated in reality or that beam is simulated + and this beam is then used or modified in a controlled manner for the purpose + of studying physical interaction mechanisms of the beam with matter. + Here it does not matter whether one considers a real specimen or a simulated one. + + Using a common description for the real experiment in the lab and - what is + typically a simplification of it - via a computer simulation, has the benefit + that many pieces of information can be stored in the same way. In effect, + users are guided with finding information and unnecessary descriptive + variety for what are exactly the same concept is avoided to work towards + more interoperability. + + Another motivation to make no fundamental distinction between a scanning and + a transmission electron microscope is that both are electron microscopes whose + components are often very similar. +# `point Electronic GmbH `_ +type: group +NXcomponent_em(NXobject): + name(NX_CHAR): + doc: | + Given name to the component e.g stage, lens C1, etc. + description(NX_CHAR): # NXidentifier + doc: | + Ideally, a (globally) unique persistent identifier, link, or text to a + resource which gives further details to this component. + If such resource does not exist, a free-text field to report + further details about the component is possible. + (NXfabrication): + (NXprogram): + (NXtransformations): + doc: | + Collection of axis-based translations and rotations to describe the + location and geometry of the component in the instrument. diff --git a/contributed_definitions/nyaml/NXcoordinate_system.yaml b/contributed_definitions/nyaml/NXcoordinate_system.yaml new file mode 100644 index 000000000..b21939900 --- /dev/null +++ b/contributed_definitions/nyaml/NXcoordinate_system.yaml @@ -0,0 +1,86 @@ +category: base +doc: | + Base class to detail a coordinate system (CS). + + Whenever possible, an instance of :ref:`NXcoordinate_system` should be used as + a member in an :ref:`NXcoordinate_system_set` and the name of the instance + should be this alias. This may support a process whereby jargon when talking + about coordinate systems and conventions may become cleaner for users + because it is not evident for people outside a lab that terms like e.g. + tip space or specimen space refer to the same coordinate system. + This is an example of jargon used in e.g. the field of atom + probe tomography. +type: group +NXcoordinate_system(NXobject): + origin(NX_CHAR): + doc: | + Human-readable field telling where the origin of this CS is. + Exemplar values could be *left corner of the lab bench*, *door-handle* + *pinhole through which the electron beam exists the pole piece*. + *barycenter of the triangle*, *center of mass of the stone*. + # implementing a proposal for "a common base table" along thoughts like: + # https://manual.nexusformat.org/classes/base_classes/NXtransformations.html#nxtransformations + # similar to a place where all transformations are stored + # https://www.zenodo.org/record/3526738/files/lyso009a_0087.JF07T32V01_master.h5?download=1 + alias(NX_CHAR): + doc: | + An alternative name given to that coordinate system. + type(NX_CHAR): + doc: | + Coordinate system type. + enumeration: [cartesian] + handedness(NX_CHAR): + doc: | + Handedness of the coordinate system if it is a Cartesian. + enumeration: [right_handed, left_handed] + x_alias(NX_CHAR): + doc: | + Possibility to define an alias for the name of the x-axis. + x_direction(NX_CHAR): + doc: | + Human-readable field telling in which direction the x-axis points if that + instance of :ref:`NXcoordinate_system` has no reference to any parent and as such + is the mighty world reference frame. + + Exemplar values could be direction of gravity. + x(NX_NUMBER): + doc: | + Base unit vector along the first axis which spans the coordinate system. + This axis is frequently referred to as the x-axis in real space and + the i-axis in reciprocal space. + unit: NX_LENGTH + dim: (3,) + y_alias(NX_CHAR): + doc: | + Possibility to define an alias for the name of the y-axis. + y_direction(NX_CHAR): + doc: | + Human-readable field telling in which direction the y-axis points if that + instance of :ref:`NXcoordinate_system` has no reference to any parent and as such + is the mighty world reference frame. + + See docstring of x_alias for further details. + y(NX_NUMBER): + doc: | + Base unit vector along the second axis which spans the coordinate system. + This axis is frequently referred to as the y-axis in real space and + the j-axis in reciprocal space. + unit: NX_LENGTH + dim: (3,) + z_alias(NX_CHAR): + doc: | + Possibility to define an alias for the name of the z-axis. + z_direction(NX_CHAR): + doc: | + Human-readable field telling in which direction the z-axis points if that + instance of :ref:`NXcoordinate_system` has no reference to any parent and as such + is the mighty world reference frame. + + See docstring of x_alias for further details. + z(NX_NUMBER): + doc: | + Base unit vector along the second axis which spans the coordinate system. + This axis is frequently referred to as the z-axis in real space and + the k-axis in reciprocal space. + unit: NX_LENGTH + dim: (3,) diff --git a/contributed_definitions/nyaml/NXcrystal_structure.yaml b/contributed_definitions/nyaml/NXcrystal_structure.yaml new file mode 100644 index 000000000..796ac83d3 --- /dev/null +++ b/contributed_definitions/nyaml/NXcrystal_structure.yaml @@ -0,0 +1,178 @@ +category: base +doc: | + Base class to describe the atomic crystal structure of a phase. + + This base class contains key metadata that are relevant parameter to every + physics-based model to simulate radiation matter interaction. + + Examples where such base class is useful are kinematic or dynamic + diffraction simulations of e.g. (Kikuchi or other type of) patterns. +# The actual indexing of Kikuchi patterns may use different algorithms. +# Such are used within different workflows where simulated and measured +# Kikuchi pattern are compared to rate which phase and orientation is the most +# likely candidate describing the pattern measured at that each scan point +# respectively. If this evaluation yields scan points without any solutions, +# these are represented using the null-phase model phase0, aka n/a aka notIndexed. +# Traditionally, Hough transformation-based indexing has been the most frequently +# used algorithm. Dictionary-based alternatives are emerging. +symbols: + n_hkl: | + Number of reflectors (Miller crystallographic plane triplets). + n_pos: | + Number of atom positions. + d: | + Dimensionality of the lattice. +type: group +NXcrystal_structure(NXobject): + \@depends_on(NX_CHAR): + doc: | + Detail in which reference frame the unit cell is defined. + dimensionality(NX_POSINT): + doc: | + Dimensionality of the lattice. + enumeration: [1, 2, 3] + reference(NXidentifier): + doc: | + Reference to another resource that was used for + instantiating this structure model. + a_b_c(NX_NUMBER): + doc: | + Crystallography unit cell parameters a, b, and c. + unit: NX_LENGTH + dim: (d,) + # defined using which convention? + alpha_beta_gamma(NX_NUMBER): + doc: | + Crystallography unit cell parameters alpha, beta, and gamma. + unit: NX_ANGLE + dim: (d,) + area(NX_NUMBER): + doc: | + Area of the unit cell considering that d = 2. + unit: NX_AREA + volume(NX_NUMBER): + doc: | + Volume of the unit cell considering that d = 3. + unit: NX_VOLUME + crystal_system(NX_CHAR): + doc: | + Crystal system + enumeration: [triclinic, monoclinic, orthorhombic, tetragonal, rhombohedral, hexagonal, cubic] + # 2d + laue_group(NX_CHAR): + doc: | + Laue group using International Table of Crystallography Notation. + # add enumeration of all possible + point_group(NX_CHAR): + doc: | + Point group using International Table of Crystallography Notation. + # add enumeration all possible + # 3d + space_group(NX_CHAR): + doc: | + Space group from the International Table of Crystallography Notation. + # add enumeration of all possible + is_centrosymmetric(NX_BOOLEAN): + doc: | + True if space group is considered a centrosymmetric one. + False if space group is considered a non-centrosymmetric one. + Centrosymmetric has all types and combinations of symmetry elements + (translation, rotational axis, mirror planes, center of inversion) + Non-centrosymmetric compared to centrosymmetric is constrained (no inversion). + Chiral compared to non-centrosymmetric is constrained (no mirror planes). + is_chiral(NX_BOOLEAN): + doc: | + True if space group is considered a chiral one. + False if space group is consider a non-chiral one. + phase_identifier(NX_INT): + doc: | + Identifier for each phase. + + The value 0 is reserved for the unknown phase that represents the + null-model no sufficiently significant confirmation. In other words, + the phase_name is n/a, notIndexed. + + The phase identifier value has to match with the integer postfix of the + group name which represents that instance in a NeXus/HDF5 file, i.e. + if two phases were used e.g. 0 and 1, two instances of an + :ref:`NXcrystal_structure` named phase0 and phase1 + should be stored in the HDF5 file. + unit: NX_UNITLESS + # \@depends_on(NX_CHAR): + # doc: | + # Refers to the specific identifier_offset to consider. + # + # If not provided assume identifier_offset is 0. + phase_name(NX_CHAR): + doc: | + Name of the phase/alias. + + If the phase_identifier is 0 and one would like to use the field + phase_name the value should be n/a. + atom_identifier(NX_CHAR): + doc: | + Label for each atom position. + dim: (n_pos,) + atom_type(NX_UINT): + doc: | + The hash value :math:`H` is :math:`H = Z + N*256` with :math:`Z` + the number of protons and :math:`N` the number of neutrons + of each isotope respectively. Z and N have to be 8-bit unsigned integers. + For the rationale behind this `M. Kühbach et al. (2021) `_ + unit: NX_UNITLESS + dim: (n_pos,) + # atom_position(NXcg_point_set): + atom_position(NX_NUMBER): + doc: | + Atom positions. + dim: (n_pos, d) + unit: NX_ANY + \@depends_on(NX_CHAR): + doc: | + Reference to an instance of :ref:`NXcoordinate_system` + whereby the positions can be resolved. + # in addition we need to have a physical model e.g. kinematic or dynamical e-diffraction theory + # to describe the simulated Kikuchi pattern generated from such a model + atom_occupancy(NX_NUMBER): + doc: | + Relative occupancy of the atom position. + unit: NX_DIMENSIONLESS + dim: (n_pos,) + number_of_planes(NX_UINT): + doc: | + How many reflectors are distinguished. + + Value has to match value for symbol n_hkl. + unit: NX_UNITLESS + # Miller indices :math:`(hkl)[uvw]`. + miller(NX_NUMBER): + unit: NX_UNITLESS + doc: | + Miller indices :math:`(hkl)[uvw]` of the planes. + + The first triplet specify :math:`(hkl)` the second triplet :math:`[uvw]`. + Miller indices refer to the Cartesian right-handed coordinate system + of the unit cell. + dim: (n_hkl, 6) + dspacing(NX_NUMBER): + doc: | + Spacing between crystallographic planes as defined by field miller. + unit: NX_LENGTH + dim: (n_hkl,) + relative_intensity(NX_NUMBER): + doc: | + Relative intensity of the signal for the plane. + unit: NX_DIMENSIONLESS + dim: (n_hkl,) + number_of_scan_points(NX_UINT): + doc: | + In case the :ref:`NXcrystal_structure` base class is used + with analyzed orientation maps this field stores how many scan points + of the map were identified as that phase. + unit: NX_UNITLESS + ipfID(NXms_ipf): + pfID(NXms_pf): + odfID(NXms_odf): +# here the theoreticians expert (Marc deGraeff, Aimo Winkelmann, Peter Rez) +# can give some good suggestions on how to improve and ideally make even +# more general this section diff --git a/contributed_definitions/nyaml/NXcs_cpu_obj.yaml b/contributed_definitions/nyaml/NXcs_cpu_obj.yaml new file mode 100644 index 000000000..73097d5ca --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_cpu_obj.yaml @@ -0,0 +1,12 @@ +category: base +doc: | + Computer science description of a (central) processing unit (C)PU of a computer. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_cpu_obj(NXobject): + name(NX_CHAR): + doc: | + Given name of the CPU. Users should be as specific as possible. + (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_cpu_sys.yaml b/contributed_definitions/nyaml/NXcs_cpu_sys.yaml new file mode 100644 index 000000000..5eaf8f0ea --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_cpu_sys.yaml @@ -0,0 +1,21 @@ +category: base +doc: | + Computer science description of a system of classical central processing units. + + For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_cpu_sys(NXobject): + cpuID(NXcs_cpu_obj): + doc: | + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single CPU one + could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of + :ref:`NXcs_cpu_sys`. + A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` + inside one instance of :ref:`NXcs_cpu_sys`. + A server with two dual-socket server nodes one could describe + with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml new file mode 100644 index 000000000..04468b7b2 --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml @@ -0,0 +1,12 @@ +category: base +doc: | + Computer science description of a graphic processing unit (GPU) of a computer. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_gpu_obj(NXobject): # NXcircuit_board ? + name(NX_CHAR): + doc: | + Given name of the GPU. Users should be as specific as possible. + (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_gpu_sys.yaml b/contributed_definitions/nyaml/NXcs_gpu_sys.yaml new file mode 100644 index 000000000..dee199330 --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_gpu_sys.yaml @@ -0,0 +1,20 @@ +category: base +doc: | + Computer science description of a system of coprocessor or graphics processors. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_gpu_sys(NXobject): + gpuID(NXcs_gpu_obj): + doc: | + Granularizing at the socket level. + + Typical examples follow: A desktop computer with a single GPU one + could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of + :ref:`NXcs_gpu_sys`. + A desktop computer with two GPUs one could describe using two instances + of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. + A GPU server like nowadays used for artificial intelligence + one could describe as a system with n instances of :ref:`NXcs_gpu_obj` + in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_mm_obj.yaml b/contributed_definitions/nyaml/NXcs_mm_obj.yaml new file mode 100644 index 000000000..d1fead8c8 --- /dev/null +++ b/contributed_definitions/nyaml/NXcs_mm_obj.yaml @@ -0,0 +1,21 @@ +category: base +doc: | + Computer science description of a memory in a memory system. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. +type: group +NXcs_mm_obj(NXobject): + technology(NX_CHAR): + doc: | + Qualifier for the type of random access memory. + # make an enumeration + max_physical_capacity(NX_NUMBER): + doc: | + Total amount of data which the medium can hold. + unit: NX_ANY + # NX_BIT + name(NX_CHAR): + doc: | + Given name to the I/O unit. + (NXfabrication): diff --git a/contributed_definitions/nyaml/NXem_adf.yaml b/contributed_definitions/nyaml/NXem_adf.yaml new file mode 100644 index 000000000..b7011639e --- /dev/null +++ b/contributed_definitions/nyaml/NXem_adf.yaml @@ -0,0 +1,28 @@ +category: base +doc: | + Base class method-specific for annular dark field imaging. + + In the majority of cases simple d-dimensional regular scan patterns are used + to probe a region-of-interest (ROI). Examples can be single point aka spot + measurements, line profiles, or (rectangular) surface mappings. + The latter pattern is the most frequently used. + + For now the base class provides for scans for which the settings, + binning, and energy resolution is the same for each scan point. +symbols: + n_images: | + Number of images in the stack. + n_y: | + Number of pixel per image in the slow direction. + n_x: | + Number of pixel per image in the fast direction. +type: group +NXem_adf(NXem_method): + IMAGE_R_SET(NXimage_r_set): + half_angle_interval(NX_NUMBER): + doc: | + Annulus inner (first value) and outer (second value) half angle. + unit: NX_ANGLE + dim: (2,) + # all information about annular dark field images is composed from + # the NXimage_r_set_em base class diff --git a/contributed_definitions/nyaml/NXem_base.yaml b/contributed_definitions/nyaml/NXem_base.yaml new file mode 100644 index 000000000..2de8081a8 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_base.yaml @@ -0,0 +1,297 @@ +category: base +# template to be used for an application definition +doc: | + Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. + + This base class combines a method-specific and technical-design-level base class + instance to provide a template for storing parameterized descriptions of + pieces of information collected when performing electron microscopy research. + + The base class here shows all possible branches without making any statements + as to which of these have to be used in an instance. Thereby, the base class + provides a template how to name and structure concepts in a hierarchy + to support finding information and reducing the need for renaming and + restructuring information for a research field where many scientists perform + very specific research but who all also share commonalities like usage of + controlled electron beams, a focus on studies of electron beam matter interaction + to explore physical mechanisms and phenomena, or the desire to characterize materials + using electron microscopy. +# flesh out the description of that to read the docs, because currently the +# description on the NeXus front-page is overwhelming +# considering what we learned from the diataxis workshop we write here a +# specification neither a how to nor a tutorial which explains all the context +# because we address here developers of software +type: group +NXem_base(NXroot): + (NXprogram): + doc: | + A collection of all programs and libraries which are considered relevant + to understand with which software tools this NeXus file instance was + generated. Ideally, to enable a binary recreation from the input data. + + Examples include the name and version of the libraries used to write the + instance. Ideally, the software that writes these :ref:`NXprogram` instances + also includes the version of the set of NeXus classes i.e. the specific + set of base classes, application definitions, and contributed definitions + with which the here described concepts can be resolved. + + For the `pynxtools library `_ + which is used by the `NOMAD `_ + research data management system, it makes sense to store e.g. the GitHub + repository commit and respective submodule references used. + # each NeXus file instance should have a default plot + # however as there are cases when this cannot be assured we cannot + # make the default required, one example is e.g. a NeXus instance + # where scientists just store conventions without a default plot + cs_profiling(NXcs_profiling): + doc: | + The configuration of the I/O writer software (e.g. `pynxtools `_) + which was used to generate this NeXus file instance. + (NXentry): # means ENTRY(NXentry) + \@version(NX_CHAR): + doc: | + An at least as strong as SHA256 hashvalue of the file + which specifies the application definition. + definition(NX_CHAR): + doc: | + NeXus NXDL schema to which this file conforms. + enumeration: [NXem] + experiment_identifier(NXidentifier): + doc: | + Ideally, a (globally) unique persistent identifier + for referring to this experiment. + + An experiment should be understood in that this can be an experiment + in reality or a computer simulation because also the latter is an + experiment (see the Cambridge Dictionary experiment: + *a test done in order to find out something, eg if an idea is correct*). + + The identifier is usually issued by the facility, laboratory, + or the principle investigator. The identifier enables to link + experiments/simulations to e.g. proposals. + experiment_description(NX_CHAR): + doc: | + Free-text description about the experiment. + + Users are strongly advised to parameterize their description of the + experiment by using the respective base classes instead of writing prose + into this field. + + The reason is that such free-text field is difficult to machine-interpret. + The motivation behind keeping this field for now is to learn through + the information entered in this field in how far the current base + classes are incomplete. + start_time(NX_DATE_TIME): + doc: | + ISO 8601 time code with local time zone offset to UTC information included + when the microscope session started. If the application demands that time + codes in this section of the application definition should only be used + for specifying when the experiment was performed - and the exact + duration is not relevant - this start_time field should be used. + + Often though it is useful to specify a time interval via setting both + a start_time and an end_time because this enables software tools and + users to collect a more detailed bookkeeping of the experiment. + + The user should be aware that even with having both time instances specified, + it may not be possible to infer how long the experiment took or for how + long data were acquired. + + More detailed timing data over the course of the experiment have + to be collected to compute this. These computations can take + advantage of individual time stamps start_time and end_time + in :ref:`NXevent_data_em` instances. + end_time(NX_DATE_TIME): + doc: | + ISO 8601 time code with local time zone offset to UTC included when + the microscope session ended. See docstring of the start_time field + to see how the start_time and end_time should be used together. + (NXcite): + (NXprogram): + doc: | + The program and eventual software libraries used with which the + NeXus instance was created. For the NOMAD OASIS research data + management system e.g. pynxtools and eventually all modules + if desired. + # the above-description overwrites the default description of the NXprogram base class + # this is composed from the NXprogram base class + # program: + # \@version: + # \@url: + # NXnote and thumbnail dropped for the reason that these are + # arbitrary binary containers without any clear provenance. + (NXserialized): + doc: | + Possibility to store a collection of data artifacts + associated with the experiment. + # using NXserialized here instead of NXnote as the former is more specific + (NXuser): + doc: | + Contact information and eventually details of at least one person + who performed or was involved in the session. This can be the + principle investigator who performed this experiment or the student + who performed the simulation. + Adding multiple users if relevant is recommended. + name(NX_CHAR): + doc: | + Given (first) name and surname of the user. + affiliation(NX_CHAR): + doc: | + Name of the affiliation of the user at the point in time + when the experiment was performed. + address(NX_CHAR): + doc: | + Postal address of the affiliation. + email(NX_CHAR): + doc: | + Email address of the user at the point in time when the experiment + was performed. Writing the most permanently used email is recommended. + identifier(NXidentifier): + doc: | + Service as another mean of identification of a user than by the name. + Examples could be details about an ORCID or social media account of + the user. + telephone_number(NX_CHAR): + doc: | + (Business) (tele)phone number of the user at the point + in time when the experiment was performed. + role(NX_CHAR): + doc: | + Which role does the user have in the place and at the point + in time when the experiment was performed? Technician operating + the microscope, student, postdoc, principle investigator, or guest + are common examples. + sample(NXsample): + # NEW ISSUE: inject the conclusion from the discussion with Andrea + # according to SAMPLE.yaml 0f8df14 2022/06/15 + # ID: -> maps to name + # name: -> short_title + # user: -> not matched right now + # citation: doi ->why relevant, should be solved by RDMS + doc: | + A description of the material characterized in the experiment. + Sample and specimen are threaded as de facto synonyms. + Samples can be real specimens or virtual (see method). + method(NX_CHAR): + doc: | + A qualifier whether the sample is a real one or a + virtual one (in a computer simulation) + enumeration: [experiment, simulation] + # MK:: declared_by_vendor I would rather expect this for a substance + # COMPONENT.yaml + # SUBSTANCE: + # QUANTIFY + identifier(NXidentifier): + doc: | + Ideally, (globally) unique persistent identifier which distinguishes + the specimen from all others and especially the predecessor/origin + from where the specimen was cut. + + This field must not be used for an alias! Instead, use name. + + In cases where multiple specimens were loaded into the microscope, + the identifier has to resolve the specific sample, whose results are + stored by this :ref:`NXentry` instance, because a single NXentry should be + used only for the characterization of a single specimen. + + Details about the specimen preparation should be + stored in resources referring to parent_identifier. + parent_identifier(NXidentifier): + doc: | + Identifier of the sample from which the sample was cut or the string + *None*. The purpose of this field is to support functionalities + for tracking sample provenance via a research data management system. + preparation_date(NX_DATE_TIME): + doc: | + ISO 8601 time code with local time zone offset to UTC information + when the specimen was prepared. + + Ideally, report the end of the preparation, i.e. the last known time + the measured specimen surface was actively prepared. Ideally, this + matches the last timestamp that is mentioned in the digital resource + pointed to by parent_identifier. + + Knowing when the specimen was exposed to e.g. specific atmosphere is + especially required for environmentally sensitive material such as + hydrogen charged specimens or experiments including tracers with a + short half time. Additional time stamps prior to preparation_date + should better be placed in resources which describe but which do not pollute + the description here with prose. Resolving these connected pieces of information + is considered within the responsibility of the research data management + system. + name(NX_CHAR): + doc: | + An alias used to refer to the specimen to please readability for humans. + atom_types(NX_CHAR): + doc: | + List of comma-separated elements from the periodic table that are + contained in the sample. If the sample substance has multiple + components, all elements from each component must be included in + `atom_types`. + + The purpose of the field is to offer research data management systems an + opportunity to parse the relevant elements without having to interpret + these from the resources pointed to by parent_identifier or walk through + eventually deeply nested groups in data instances. + # NEW ISSUE: use Andrea and MarkusK groups for describing the geometry of the sample + thickness(NX_NUMBER): + doc: | + (Measured) sample thickness. + + The information is recorded to qualify if the beam used was likely + able to shine through the specimen. For scanning electron microscopy, + in many cases the specimen is typically thicker than what is + illuminatable by the electron beam. + + In this case the value should be set to the actual thickness of + the specimen viewed for an illumination situation where the nominal + surface normal of the specimen is parallel to the optical axis. + unit: NX_LENGTH + # \@units: nm + # NEW ISSUE: error estimates of the thickness and origin, i.e. how the value was obtained would be useful + # NEW ISSUE: error model + # NEW ISSUE: the KIT/SCC SEM, TEM schemata further qualify samples whether they are conductive e/ibeam sensitive + # etc. The problem with this is that beam sensitivity is too vague but spatiotemporal electron dose integral dependent + # KIT/SCC distinguish further conductivity and magnetic properties. While the motivation is clear, making + # it thus simple is likely problematic when the data entered in such fields remaining qualitative. + # what are good or bad properties, it would make sense though to quantify these values + # this includes the description of eventual plasma cleaning steps, + # just knowing that a sample was plasma cleaned is insufficient, maybe it was not cleaned long enough + # if plasma cleaning is done outside the EM than its certainly history, if it happens inside the EM + # are the ibeam description capabilities not sufficient enough? + density(NX_NUMBER): + # NX_MASS_PER_VOLUME + doc: | + (Measured) density of the specimen. + + For multi-layered specimens this field should only be used to describe + the density of the excited volume. For scanning electron microscopy + the usage of this field is discouraged and instead an instance of an + :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` + instances can provide a cleaner description of the relevant details + why one may wish to store the density of the specimen. + unit: NX_ANY + description: + doc: | + Discouraged free-text field to provide further detail although adding + parent_identifier and having a working research data management system + should provide this contextualization. + # (NXmonitor): + (NXdata): + (NXcoordinate_system_set): + # link to an instance of an NXinstrument but that is anyway specialized for EM + measurement(NXem_msr): + simulation(NXem_sim): + (NXroi): + doc: | + A region-of-interest analyzed either during or after the session + for which specific processed data generated from the measured or the + simulated data are available. + se(NXem_img): + bse(NXem_img): + ebsd(NXem_ebsd): + eds(NXem_eds): + adf(NXem_adf): + eels(NXem_eels): + correlation(NXem_correlation): + # cl(NXem_cl): diff --git a/contributed_definitions/nyaml/NXem_conventions.yaml b/contributed_definitions/nyaml/NXem_conventions.yaml new file mode 100644 index 000000000..7835d9a65 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_conventions.yaml @@ -0,0 +1,296 @@ +category: base +# symbols: +doc: | + Conventions for rotations and coordinate systems to interpret crystal orientation + and other data and results collected with electron microscopy research. + + Documenting explicitly all used conventions and coordinate systems is + the decisive context whereby many results from electron microscopy are + at all interpretable. + +# This base class provides several sets of such assumptions and conventions. +# Further base classes should be defined when specific techniques and methods +# demand further specifications or have specialized demands. NXem_conventions_ebsd +# is an example for such method-specific base class to summarize key conventions +# for Electron Backscatter Diffraction (EBSD). + +# What is could be a best practice for application definition developers +# who would like to describe an electron microscopy case where multiple +# methods and/or detectors are used. In this case one should define a +# method-specific base class like the template NXem_conventions_ebsd. +# Even though this may come at a cost of some duplicated information where +# the same physical detector is used in different ways, i.e. the signal collect +# from the detector is interpreted in a different way. +# As in most cases established types of signal and thus detectors are used +# (secondary electron, backscattered electron, etc.) one could equally use +# just one NXem_conventions base class instance in an application definition +# and use detector_reference_frame as a template. For each method and detector +# one then creates one NXprocess group named detector_reference_frame1, +# detector_reference_frame2, detector_reference_frame3, and so on and so forth +# and adds inside that NXprocess and use the depends_on field. + +# What is considered best practice in an application definition with multiple +# NXentry instances? In this case each NXentry instance should have an own +# NXspecimen instance and thus the NXem_conventions instance should be place +# inside that NXentry. This enables to group multiple experiments on multiple +# samples together without setting a constraint that in all these instances +# the conventions have to be the same. + +# However, best practice is the conventions should be expressed explicitly +# and they should whenever possible be as simple as possible and as few +# as possible to support users with understanding the content of the application +# definition. +type: group +NXem_conventions(NXobject): + # mandatory information about used or + # assumed reference frame and rotation conventions + rotation_conventions(NXobject): + doc: | + Mathematical conventions and materials-science-specific conventions + required for interpreting every collection of orientation data. + rotation_handedness(NX_CHAR): + doc: | + Convention how a positive rotation angle is defined when viewing + from the end of the rotation unit vector towards its origin, + i.e. in accordance with convention 2 of + DOI: 10.1088/0965-0393/23/8/083501. + Counter_clockwise is equivalent to a right-handed choice. + Clockwise is equivalent to a left-handed choice. + enumeration: [undefined, counter_clockwise, clockwise] + rotation_convention(NX_CHAR): + doc: | + How are rotations interpreted into an orientation + according to convention 3 of + DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, passive, active] + euler_angle_convention(NX_CHAR): + doc: | + How are Euler angles interpreted given that there are several + choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of + DOI: 10.1088/0965-0393/23/8/083501. + The most frequently used convention is ZXZ which is based on + the work of H.-J. Bunge but other conventions are possible. + enumeration: [undefined, zxz] + axis_angle_convention(NX_CHAR): + doc: | + To which angular range is the rotation angle argument of an + axis-angle pair parameterization constrained according to + convention 5 of DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, rotation_angle_on_interval_zero_to_pi] + sign_convention(NX_CHAR): + doc: | + Which sign convention is followed when converting orientations + between different parameterizations/representations according + to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, p_plus_one, p_minus_one] + processing_reference_frame(NXcoordinate_system): + doc: | + Details about eventually relevant named directions that may + give reasons for anisotropies. The classical example is cold-rolling + where one has to specify which directions (rolling, transverse, and normal) + align how with the direction of the base vectors of the sample_reference_frame. + type(NX_CHAR): + doc: | + Type of coordinate system and reference frame according to + convention 1 of DOI: 10.1088/0965-0393/23/8/083501. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of coordinate system. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Location of the origin of the processing_reference_frame. + This specifies the location Xp = 0, Yp = 0, Zp = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] + x_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. rolling direction. + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing x-axis base vector of + the processing_reference_frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. + enumeration: [undefined, north, east, south, west, in, out] + y_alias(NX_CHAR): + doc: | + Name or alias assigned to the y-axis base vector, + e.g. transverse direction. + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing y-axis base vector of + the processing_reference_frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_alias(NX_CHAR): + doc: | + Name or alias assigned to the z-axis base vector, + e.g. normal direction. + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing z-axis base vector of + the processing_reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + sample_reference_frame(NXcoordinate_system): + doc: | + Details about the sample/specimen reference frame. + type(NX_CHAR): + doc: | + Type of coordinate system and reference frame according to + convention 1 of DOI: 10.1088/0965-0393/23/8/083501. + The reference frame for the sample surface reference is used for + identifying positions on a (virtual) image which is formed by + information collected from an electron beam scanning the + sample surface. We assume the configuration is inspected by + looking towards the sample surface from a position that is + located behind the detector. + Reference DOI: 10.1016/j.matchar.2016.04.008 + The sample surface reference frame has coordinates Xs, Ys, Zs. + In three dimensions these coordinates are not necessarily + located on the surface of the sample as there are multiple + faces/sides of the sample. Most frequently though the coordinate + system here is used to define the surface which the electron + beam scans. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of the coordinate system if it is a Cartesian. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Location of the origin of the sample surface reference frame. + This specifies the location Xs = 0, Ys = 0, Zs = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] + x_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. longest edge. + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing x-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + enumeration: [undefined, north, east, south, west, in, out] + y_alias(NX_CHAR): + doc: | + Name or alias assigned to the y-axis base vector, + e.g. long edge. + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing y-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_alias(NX_CHAR): + doc: | + Name or alias assigned to the z-axis base vector, + e.g. shortest edge. + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing z-axis base vector of + the sample surface reference frame. We assume the configuration + is inspected by looking towards the sample surface from a position + that is located behind the detector. For further information consult + also the help info for the xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + detector_reference_frameID(NXcoordinate_system): + doc: | + Details about the detector reference frame for a specific detector. + \@depends_on(NX_CHAR): + doc: | + Reference to the specifically named :ref:`NXdetector` instance + for which these conventions in this :ref:`NXprocess` group apply + (e.g. /entry1/instrument/detector1). + type(NX_CHAR): + doc: | + Type of coordinate system/reference frame used for + identifying positions in detector space Xd, Yd, Zd, + according to DOI: 10.1016/j.matchar.2016.04.008. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of the coordinate system if it is a Cartesian. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Where is the origin of the detector space reference + frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. + Assume regions-of-interest in this reference frame form a + rectangle or cuboid. + Edges are interpreted by inspecting the direction of their + outer unit normals (which point either parallel or antiparallel) + along respective base vector direction of the reference frame. + enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] + x_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. longest edge as some landmark on the detector. + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing x-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + enumeration: [undefined, north, east, south, west, in, out] + y_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. long edge as some landmark on the detector. + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing y-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_alias(NX_CHAR): + doc: | + Name or alias assigned to the x-axis base vector, + e.g. short edge as some landmark on the detector. + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing z-axis base vector of + the detector space reference frame. We assume the configuration + is inspected by looking towards the sample surface from a + position that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + # conventions specific for EBSD + (NXem_conventions_ebsd): \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml b/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml new file mode 100644 index 000000000..1ec180e23 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml @@ -0,0 +1,125 @@ +category: base +# symbols: +doc: | + Base class for method-specific conventions EBSD. + + This base class is expected to be used with :ref:`NXem_conventions`. + + This is the main issue which currently is not in all cases documented + and thus limits the interoperability and value of collected EBSD data. + Not communicating EBSD data with such contextual pieces of information + and the use of file formats which do not store this information is the + key unsolved problem. +type: group +NXem_conventions_ebsd(NXem_conventions): + gnomonic_projection_reference_frame(NXcoordinate_system): + doc: | + Details about the gnomonic projection reference frame. + type(NX_CHAR): + doc: | + Type of coordinate system/reference frame used for identifying + positions in the gnomonic projection space Xg, Yg, Zg + according to DOI: 10.1016/j.matchar.2016.04.008. + enumeration: [undefined, cartesian] + handedness(NX_CHAR): + doc: | + Handedness of coordinate system. + enumeration: [right_handed, left_handed] + origin(NX_CHAR): + doc: | + Is the origin of the gnomonic coordinate system located + where we assume the location of the pattern centre. + This is the location Xg = 0, Yg = 0, Zg = 0 according to + reference DOI: 10.1016/j.matchar.2016.04.008. + enumeration: [undefined, in_the_pattern_centre] + x_direction(NX_CHAR): + doc: | + Direction of the positively pointing "gnomomic" x-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + Different tools assume that different strategies can be used + and are perceived as differently convenient to enter + details about coordinate system definitions. In this ELN users + have to possibility to fill in what they assume is sufficient to + define the coordinate system directions unambiguously. + Software which works with this user input needs to offer parsing + capabilities which detect conflicting input and warn accordingly. + enumeration: [undefined, north, east, south, west, in, out] + y_direction(NX_CHAR): + doc: | + Direction of the positively pointing "gnomomic" y-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + z_direction(NX_CHAR): + doc: | + Direction of the positively pointing "gnomomic" z-axis base + vector when viewing how the diffraction pattern looks on the + detector screen. We assume the configuration is inspected by + looking towards the sample surface from a position + that is located behind the detector. + For further information consult also the help info for the + xaxis_direction field. + enumeration: [undefined, north, east, south, west, in, out] + pattern_centre(NXprocess): + doc: | + Details about the definition of the pattern centre + as a special point in the gnomonic projection reference frame. + x_boundary_convention(NX_CHAR): + doc: | + From which border of the EBSP (in the detector reference frame) + is the pattern centre's x-position (PCx) measured? + Keywords assume the region-of-interest is defined by + a rectangle. We observe this rectangle and inspect the + direction of the outer-unit normals to the edges of + this rectangle. + enumeration: [undefined, top, right, bottom, left] + x_normalization_direction(NX_CHAR): + doc: | + In which direction are positive values for PCx measured from + the specified boundary. Keep in mind that the gnomonic space + is in virtually all cases embedded in the detector space. + Specifically, the XgYg plane is defined such that it is + embedded/laying inside the XdYd plane (of the detector + reference frame). + When the normalization direction is the same as e.g. the + detector x-axis direction, we state that we effectively + normalize in fractions of the width of the detector. + + The issue with terms like width and height is that these + degenerate if the detector region-of-interest is square-shaped. + This is why we should better avoid talking about width and height but + state how we would measure distances practically with a ruler and + how we then measure positive distances. + enumeration: [undefined, north, east, south, west] + y_boundary_convention(NX_CHAR): + doc: | + From which border of the EBSP (in the detector reference + frame) is the pattern centre's y-position (PCy) measured? + For further details inspect the help button of + xaxis_boundary_convention. + enumeration: [undefined, top, right, bottom, left] + y_normalization_direction(NX_CHAR): + doc: | + In which direction are positive values for PCy measured from + the specified boundary. + For further details inspect the help button of + xaxis_normalization_direction. + enumeration: [undefined, north, east, south, west] + + # distance_convention: + # doc: | + # How is the third of the three pattern centre parameter values, + # the (distance) parameter DD, normalized. Which convention + # is followed. We are aware that specifying one of the options here + # also implicitly comes with conventions for some of the parameter + # requested in this ELN. For now we would rather like to ask + # the users though to be specific also to learn how such an ELN + # will be used in practice. + # enumeration: [undefined, Bruker, JEOL, FEI, Oxford] diff --git a/contributed_definitions/nyaml/NXem_correlation.yaml b/contributed_definitions/nyaml/NXem_correlation.yaml new file mode 100644 index 000000000..2acf65ec8 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_correlation.yaml @@ -0,0 +1,191 @@ +category: base +doc: | + Base class to combine different method-specific data in electron microscopy. + + This base class represent a template for documenting correlations + (spatial, temporal) between different method-specific results. +type: group +NXem_correlation(NXem_method): + (NXprocess): + doc: | + Details about processing steps. + sequence_index(NX_INT): + indexing(NXprocess): + doc: | + Details about correlated or logically connected EBSD datasets. + + One important class of such correlated experiments are the so-called + (quasi) in-situ experiments. In this case the same or nearly the same ROI + gets analyzed via a repetitive sequence of thermomechanical treatment, + sample preparation, measurement, on-the-fly-indexing. Phenomena + investigated are recrystallization, strain accumulation, material damage. + Post-processing is required to correlate and reidentify eventual + microstructural features or local ROIs across several orientation maps. + + Another important class of correlated experiments are the so-called + serial-sectioning experiments. Here the same sample is measured + repetitively after polishing each time, to create a stack of + orientation data which can be reconstructed to a + three-dimensional volume ROI. + + Data can be correlated in time, position (spatial), or both (spatiotemporal). + + Spatial correlations between repetitively characterized regions-of-interests + are typically correlated using image registration and alignment algorithms. + For this typically so-called landmarks are used. These can be grains with + a very large size or specific shape, i.e. grains which are qualitatively + different enough to be used as a guide how images are shifted relative to + one another. Other commonly used landmarks are fiducial marks which are + milled into the specimen surface using focus-ion beam milling and/or various + types of indentation methods. + + As far as the same physical region-of-interest is just measured several times, + the additional issue of the depth increment is not a concern. However, correct + assumptions for the depth increment, amount of material removed along the milling + direction is relevant for accurate and precise three-dimensional (serial-sectioning) + correlations. For these studies it can be tricky though to assume or estimate + useful depth increments. Different strategies have been proposed like + calibrations, wedged-shaped landmarks and computer simulation assisted + assumption making. + + Despite the use of landmarks, there are many practical issues which make the + processing of correlations imprecise and inaccurate. Among these are drift + and shift of the specimen, instabilities of the holder, the beam, irrespective + of the source of the drift, charging effects, here specifically causing local + image distortions and rotations which may require special processing algorithms + to reduce such imprecisions. + + Time correlations face all of the above-mentioned issues surplus the challenge + that specific experimental protocols have to be used to ensure the material state + is observed at specific physical time. The example of quasi in-situ characterization + of crystal growth phenomena, a common topic in engineering or modern catalysis research + makes it necessary to consider that e.g. the target value for the desired annealing + temperature is not just gauged based on macroscopic arguments but considers + that transient effects take place. Heating or quenching a sample might thus might + not have been executed under conditions in the interaction volume as they are + documented and/or assumed. + + These issue cause that correlations have an error margin as to how accurately + respective datasets were not only just synced based on the geometry of the + region-of-interests and the time markers but also to asssure which physical + conditions the specimen experienced over the course of the measurements. + + The fourth example of the em_om reference implementation explores the use of the + correlation group with a serial-sectioning datasets that was collected by the + classical Inconel 100 dataset collected by M. D. Uchic and colleagues + (M. Groeber M, Haley BK, Uchic MD, Dimiduk DM, Ghosh S 3d reconstruction and + characterization of polycrystalline microstructures using a fib-sem system data set. + Mater Charac 2006, 57 259–273. 10.1016/j.matchar.2006.01.019M). + + This dataset was specifically relevant in driving forward the implementation + of the DREAM.3D software. DREAM.3D is an open-source software project for + post-processing and reconstructing, i.e. correlating sets of orientation + microscopy data foremost spatially. One focus of the software is the + (post-)processing of EBSD datasets. Another cutting edge tool with similar + scope but a commercial solution by Bruker is QUBE which was developed by + P. Konijnenberg and coworkers. + + Conceptually, software like DREAM.3D supports users with creating linear + workflows of post-processing tasks. Workflows can be instructed via the + graphical user interface or via so-called pipeline processing via command line + calls. DREAM.3D is especially useful because its internal system documents all + input, output, and parameter of the processing steps. This makes DREAM.3D a + good candidate to interface with tools like em_om parser. Specifically, DREAM.3D + documents numerical results via a customized HDF5 file format called DREAM3D. + Workflow steps and settings are stored as nested dictionaries in JSON syntax + inside a supplementary JSON file or alongside the data in the DREAM3D file. + DREAM.3D has a few hundred algorithms implemented. These are called filters + in DREAM.3D terminology. + + Users configure a workflow which instructs DREAM.3D to send the data through + a chain of predefined and configured filters. Given that for each analysis + the filter is documented via its version tags surplus its parameter and setting + via a controlled vocabulary, interpreting the content of a DREAM3D HDF5 file + is possible in an automated manner using a parser. This makes DREAM.3D analyses + repeatable and self-descriptive. A key limitation though is that most frequently + the initial set of input data come from commercial files like ANG. + This missing link between the provenance of these input files, their associated + creation as electron microscope session, is also what NXem_ebsd solves. + + Nevertheless, as this can be solved with e.g. NXem_ebsd we are convinced that + the DREAM.3D and the em_om parser can work productively together to realize + RDMS-agnostic parsing of serial-section analyses. + + The internal documentation of the DREAM.3D workflow also simplifies the + provenance tracking represented by an instance of NXem_ebsd as not every + intermediate results has to be stored. Therefore, the fourth example + focuses on the key result obtained from DREAM.3D - the reconstructed + and aligned three-dimensional orientation map. + + Usually, this result is the starting point for further post-processing + and characterization of structural features. As here orientation microscopy + is insofar scale invariant using DREAM.3D, NXem_ebsd, and em_om should + be useful for different characterization methods, such as EBSD, Transmission + Kikuchi Diffraction (TKD), Automated Crystal Orientation Mapping (ACOM), + Nanobeam Electron Diffraction (using commercial systems like NanoMegas ASTAR) + or open-source implementations of these techniques (such as via pyxem/orix). + + The result of orientation microscopy methods are maps of local orientation + and thermodynamic phase (crystal structure) pieces of information. Virtually + all post-processing of such results for structural features includes again + a workflow of steps which are covered though by the NXms partner application + definition. The respective source of the data in an instance of NXms can + again be a link or reference to an instance of NXem_ebsd to complete the + chain of provenance. + (NXcrystal_structure): + roi(NXdata): + descriptor: + doc: | + Descriptor representing the image contrast. + # \@signal: # data + # \@axes: # [axis_y, axis_x] + # \@axis_x_indices: 0 + # \@axis_y_indices: 1 + # \@signal: + # \@axes: + # \@AXISNAME_indices: + # \@long_name: + title: + doc: | + Title of the default plot. + data(NX_NUMBER): + unit: NX_UNITLESS + doc: | + Descriptor values displaying the ROI. + dim: (n_z, n_y, n_x) + # n_0 slowest 3, n_1 slow 2, n_2 fast 1, rgb triplet is fastest 0 + # in axes fast to fastest + # while for _indices fastest to fast + \@long_name: + doc: | + Descriptor values. + axis_z(NX_NUMBER): + unit: NX_LENGTH + doc: | + Calibrated coordinate along the z-axis. + dim: (n_z,) + \@long_name: + doc: | + Label for the z axis + axis_y(NX_NUMBER): + unit: NX_LENGTH + doc: | + Calibrated coordinate along the y-axis. + dim: (n_y,) + \@long_name: + doc: | + Label for the y axis + axis_x(NX_NUMBER): + unit: NX_LENGTH + doc: | + Calibrated coordinate along the x-axis. + dim: (n_x,) + \@long_name: + doc: | + Label for the x axis + # NEW ISSUE: implement support for filters eventually many of them + # NEW ISSUE: for now only show that data from DREAM3D can be loaded. + # NEW ISSUE: how to handle landmarks + # NEW ISSUE: again an entire set of workflows such as rigid or non-rigid + # image registration etc. + # sequence_index(N0): diff --git a/contributed_definitions/nyaml/NXem_eds.yaml b/contributed_definitions/nyaml/NXem_eds.yaml new file mode 100644 index 000000000..9a5a97fcd --- /dev/null +++ b/contributed_definitions/nyaml/NXem_eds.yaml @@ -0,0 +1,80 @@ +category: base +doc: | + Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). + + `IUPAC instead of Siegbahn notation `_ should be used. + +# NEW ISSUE: use computational geometry to offer arbitrary scan pattern +# NEW ISSUE: make the binning flexible per scan point +symbols: + # n_p: Number of scan points + n_y: | + Number of pixel along the y direction, the slow direction + n_x: | + Number of pixel along the x direction, the fast direction + n_photon_energy: | + Number of X-ray photon energy (bins), the fastest direction. + n_elements: | + Number of identified elements + n_peaks: | + Number of peaks detected +type: group +NXem_eds(NXem_method): + # NXprocess is composed from NXem_method base class + # SPECTRUM_SET(NXspectrum_set) is composed from NXem_method base class + # for post-processing of/with the above-defined data entries + # including feedback from Christoph Pauly (from MX Uni Saarland, NFDI-MatWerk), + # Sabine Bergmann and Sebastian Brückner (both from FAIRmat, IKZ), + # and Adrien Teutrie, Cecile Hebert (EPFL) + indexing(NXprocess): + doc: | + Details about computational steps how peaks were indexed as elements. + (NXprogram): + doc: | + The program with which the indexing was performed. + PEAK(NXpeak): + doc: | + Name and location of each X-ray line which was indexed as a known ion. + For each ion, an NXion instance should be created which specifies + the origin of the signal. For each ion also the relevant IUPAC notation + X-ray lines should be specified. + (NXion): + energy_range(NX_NUMBER): + doc: | + Associated lower :math:`[e_{min}, e_{max}]` bounds of the + energy which is assumed associated with this peak. + unit: NX_ENERGY + dim: (2,) + energy(NX_NUMBER): + doc: | + Theoretical energy of the line according to IUPAC. + unit: NX_ENERGY + iupac_line_names(NX_CHAR): + doc: | + IUPAC notation identifier of the line which the peak represents. + + This can be a list of IUPAC notations for (the seldom) case that + multiple lines are grouped with the same peak. + dim: (i,) + element_names(NX_CHAR): + doc: | + List of the names of identified elements. + dim: (n_elements,) + IMAGE_R_SET(NXimage_r_set): + doc: | + Individual element-specific EDS/EDX/EDXS/SXES mapping + + A composition map is an image whose intensities for each pixel are the + accumulated X-ray quanta *under the curve(s)* of a set of peaks. + + These element-specific EDS maps are NXimage_r_set instances + and need to be named with the name of the element from the + element_names field. + (NXprocess): + peaks(NX_CHAR): + doc: | + A list of NXpeak instance names whose X-ray quanta + where accumulated for each pixel which yields an element-specific + EDS map. + dim: (n_peaks,) + # everything else is composed from NXimage_r_set diff --git a/contributed_definitions/nyaml/NXem_eels.yaml b/contributed_definitions/nyaml/NXem_eels.yaml new file mode 100644 index 000000000..4e5c69fe4 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_eels.yaml @@ -0,0 +1,39 @@ +category: base +doc: | + Base class method-specific for Electron Energy Loss Spectroscopy (EELS). +symbols: + n_energy_loss: | + Number of electron energy loss bins. +type: group +NXem_eels(NXem_method): + # NXem_method can offers to keep a SPECTRUM_SET + # NXem_method also has an NXprocess which in this base class can be + # specialized to include EELS-specific post-processing + SPECTRUM_SET(NXspectrum_set): + doc: | + NXspectrum_set_em specialized for EELS. + stack(NXdata): + # \@signal: data_counts + # \@axes: [axis_y, axis_x, axis_energy_loss] + # \@energy_loss_indices: 2 + # \@axis_x_indices: 1 + # \@axis_y_indices: 0 + axis_energy_loss(NX_NUMBER): + unit: NX_ENERGY + dim: (n_energy_loss,) + \@long_name(NX_CHAR): + doc: | + Energy loss. + summary(NXdata): + # \@signal: data_counts + # \@axes: [axis_energy_loss] + # \@energy_loss_indices: 0 + axis_energy_loss(NX_NUMBER): + unit: NX_ENERGY + doc: | + Energy loss. + dim: (n_energy_loss,) + \@long_name(NX_CHAR): + doc: | + Energy loss. + # collection if needed can be composed from NXspectrum_set diff --git a/contributed_definitions/nyaml/NXem_img.yaml b/contributed_definitions/nyaml/NXem_img.yaml new file mode 100644 index 000000000..8c257d121 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_img.yaml @@ -0,0 +1,25 @@ +category: base +doc: | + Base class for method-specific generic imaging. + + In the majority of cases simple d-dimensional regular scan patterns are used + to probe a region-of-interest (ROI). Examples can be single point aka spot + measurements, line profiles, or (rectangular) surface mappings. + The latter pattern is the most frequently used. + + For now the base class provides for scans for which the settings, + binning, and energy resolution is the same for each scan point. +symbols: + n_images: | + Number of images in the stack. + n_y: | + Number of pixel per image in the slow direction. + n_x: | + Number of pixel per image in the fast direction. +type: group +NXem_img(NXem_method): + imaging_mode(NX_CHAR): + doc: | + Which imaging mode was used? + enumeration: [secondary_electron, backscattered_electron] + IMAGE_R_SET(NXimage_r_set): diff --git a/contributed_definitions/nyaml/NXem_method.yaml b/contributed_definitions/nyaml/NXem_method.yaml new file mode 100644 index 000000000..afe91de97 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_method.yaml @@ -0,0 +1,21 @@ +category: base +doc: | + Base class to describe specific analysis methods in electron microscopy. + + This base class represent a template how specialized, deep, and method-specific + base classes can be defined with which an (NXem) application + definition gets equipped with specific groups to document method-specific + processing steps and report analyzed quantities. + + The template base class name :ref:`NXem_method` needs to be changed for each + method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. +# :ref:`NXem_se`, :ref:`NXem_bse`. +type: group +NXem_method(NXobject): + (NXprocess): + doc: | + Details about processing steps. + sequence_index(NX_INT): + IMAGE_R_SET(NXimage_r_set): + IMAGE_C_SET(NXimage_c_set): + SPECTRUM_SET(NXspectrum_set): diff --git a/contributed_definitions/nyaml/NXem_msr.yaml b/contributed_definitions/nyaml/NXem_msr.yaml new file mode 100644 index 000000000..16c349ca5 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_msr.yaml @@ -0,0 +1,63 @@ +category: base +doc: | + Base class for collecting a session with a real electron microscope. + + For collecting data and experiments which are simulations of an + electron microscope use the :ref:`NXem_sim` base class. +type: group +NXem_msr(NXem_method): + em_lab(NXinstrument): + doc: | + (Meta)data of the microscope and the lab in which it stands. + + This em_lab group differs from potential em_lab groups inside + :ref:`NXevent_data_em` instances in that here the more static descriptions + are kept while changing, i.e. time-dependent pieces of information are + logged, via the em_lab group inside the desired number of instances + of NXevent_data_em. + + While using an :ref:`NXevent_data_em` instance, users should store only those + settings about a component which are relevant to understand the current + state of the component. Here, current means for the time interval which + the event covers (as it is detailed via start_time and end_time) timestamps. + + For example it is not relevant to store in each :ref:`NXevent_data_em` + electron_source group again the details of the gun type and the manufacturer + but only the high-voltage value and that only if it is different from the value + that is specified in the em_lab section for the static settings. + + In effect, this defines an information inference hierarchy which starts + in an individual :ref:`NXevent_data_em` instance followed by a probing of the + static section. + instrument_name(NX_CHAR): + doc: | + Given name of the microscope at the hosting institution. + This is an alias. Examples could be NionHermes, Titan, JEOL, + Gemini, etc. + location(NX_CHAR): + doc: | + Location of the lab or place where the instrument is installed. + Using GEOREF is preferred. + (NXfabrication): + (NXchamber): + (NXebeam_column): + (NXibeam_column): + (NXoptical_system_em): + (NXdetector): + doc: | + Description of the type of the detector. + + Electron microscopes have typically multiple detectors. + Different technologies are in use like CCD, scintillator, + direct electron, CMOS, or image plate to name but a few. + local_name(NX_CHAR): + doc: | + Instrument-specific alias/name + # it is unfortunate that for NXdetector there are already many places + # how one can specify details which could equally end up in fabrications + # we should give better guidance which option to use, pr to niac + # (NXfabrication): + (NXpump): + (NXstage_lab): + (NXevent_data_em_set): +# (NXevent_data_em): diff --git a/contributed_definitions/nyaml/NXem_sim.yaml b/contributed_definitions/nyaml/NXem_sim.yaml new file mode 100644 index 000000000..81fe20db1 --- /dev/null +++ b/contributed_definitions/nyaml/NXem_sim.yaml @@ -0,0 +1,34 @@ +category: base +doc: | + Base class for simulating electron microscopy relevant beam-matter interaction. + + The concept behind this base class is to keep it as generic as possible + that simulations of electron/ion beam interaction with matter can be + represented. This base class is envisioned as the twin of the :ref:`NXem_msr` + base class. + + It is an attempt to test the idea if at some point one might even use the + same base class template to describe measurements and computer simulations + of electron microscopy. This idea is attractive because the only practical + difference between a description of a measurement with a microscope and a + computer simulation is that the latter is typically a substantially simplified + representation of the real microscope surplus the focus of the research + in such cases on specific questions. + + Such simplification can be with respect to the optical setup, typically the + ignoring of the fact that the electron beam is produced by a complex setup + of lenses while in simulations often single Einzel lenses are considered. + Dynamics of the environment like temperature fluctuation in a lab, vibrations, + users, and multiple detectors are typically either ignored or reduced in + complexity and number and coming with idealizations to keep the simulations + focused on the specific reason questions and efficiently numerically executable. +# abTEM and other simulation packages, TEMgym, etc. +type: group +NXem_sim(NXem_method): + simulation(NXprocess): + doc: | + Details about the simulation. + # sequence_index(N): + (NXprogram): + (NXcg_geodesic_mesh): + (NXimage_r_set_diff): diff --git a/contributed_definitions/nyaml/NXimage_c_set.yaml b/contributed_definitions/nyaml/NXimage_c_set.yaml new file mode 100644 index 000000000..8dcd85706 --- /dev/null +++ b/contributed_definitions/nyaml/NXimage_c_set.yaml @@ -0,0 +1,140 @@ +category: base +doc: | + Specialized base class container for reporting a set of images in reciprocal space. + + In practice, complex numbers are encoded via some formatted pair of real values. + Typically, fast Algorithms for computing Fourier Transformations (FFT) are + used to encode images in reciprocal (frequency) space. FFT libraries are used + for implementing the key functionalities of these mathematical operations. + + Different libraries use different representations and encoding of the + image computed. Details can be found in the respective sections of the + typical FFT libraries: + + * `FFTW by M. Frigo and S. G. Johnson `_ + * `Intel MKL by the Intel Co. `_ + * `cuFFT by the NVidia Co. `_ + + Users are strongly advised to inspect carefully which specific conventions + their library uses to be able to store and modify the implementation of their + code so that the serialized representations as it is detailed + here for NeXus matches with their intention. + + One- and two-dimensional FFTs should use the stack(NXdata) instances. + Three-dimensional FFTs should use the hyperstack(NXdata) instances. +symbols: + n_images: | + Number of images in the (hyper)stack. + n_k: | + Number of pixel per image in the slowest direction. + n_j: | + Number of pixel per image in the slow direction. + n_i: | + Number of pixel per image in the fast direction. +type: group +NXimage_c_set(NXimage_set): + # details about the FFT library used could for instance be stored in the + # NXprocess group which the NXimage_c_set base class can borrow from its + # NXimage_set parent base class + # process information are composable from the NXimage_set base class + stack(NXdata): + doc: | + Image stack. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_images, n_j, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_images, n_j, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_images, n_j, n_i) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + # axis_k(NX_NUMBER): + # doc: | + # Pixel coordinate center along k direction. + # unit: NX_ANY # NX_RECIPROCAL_LENGTH + # dim: (n_k,) + # \@long_name(NX_CHAR): + # doc: | + # Coordinate along j direction. + axis_j(NX_NUMBER): + doc: | + Pixel coordinate center along j direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_j,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. + + hyperstack(NXdata): + doc: | + Image hyperstack. + real(NX_NUMBER): + doc: | + Image intensity of the real part. + unit: NX_UNITLESS + dim: (n_images, n_k, n_j, n_i) + imag(NX_NUMBER): + doc: | + Image intensity of the imaginary part. + unit: NX_UNITLESS + dim: (n_images, n_k, n_j, n_i) + magnitude(NX_NUMBER): + doc: | + Magnitude of the image intensity. + unit: NX_UNITLESS + dim: (n_images, n_k, n_j, n_i) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_k(NX_NUMBER): + doc: | + Pixel coordinate center along k direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_k,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_j(NX_NUMBER): + doc: | + Pixel coordinate center along j direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_j,) + \@long_name(NX_CHAR): + doc: | + Coordinate along j direction. + axis_i(NX_NUMBER): + doc: | + Pixel coordinate center along i direction. + unit: NX_ANY # NX_RECIPROCAL_LENGTH + dim: (n_i,) + \@long_name(NX_CHAR): + doc: | + Coordinate along i direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set.yaml b/contributed_definitions/nyaml/NXimage_r_set.yaml new file mode 100644 index 000000000..f0437e6e6 --- /dev/null +++ b/contributed_definitions/nyaml/NXimage_r_set.yaml @@ -0,0 +1,45 @@ +category: base +doc: | + Specialized base class container for reporting a set of images in real space. +symbols: + n_images: | + Number of images in the stack. + n_y: | + Number of pixel per image in the slow direction. + n_x: | + Number of pixel per image in the fast direction. +type: group +NXimage_r_set(NXimage_set): + # process information are composable from the NXimage_set base class + stack(NXdata): + doc: | + Image (stack). + intensity(NX_NUMBER): + doc: | + Image intensity values. + unit: NX_UNITLESS + dim: (n_images, n_y, n_x) + axis_image_identifier(NX_INT): + doc: | + Image identifier + unit: NX_UNITLESS + dim: (n_images,) + \@long_name(NX_CHAR): + doc: | + Image identifier. + axis_y(NX_NUMBER): + doc: | + Pixel coordinate center along y direction. + unit: NX_LENGTH + dim: (n_y,) + \@long_name(NX_CHAR): + doc: | + Coordinate along y direction. + axis_x(NX_NUMBER): + doc: | + Pixel coordinate center along x direction. + unit: NX_LENGTH + dim: (n_x,) + \@long_name(NX_CHAR): + doc: | + Coordinate along x direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml new file mode 100644 index 000000000..79ca31b16 --- /dev/null +++ b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml @@ -0,0 +1,123 @@ +category: base +doc: | + Base class specialized for reporting a cuboidal stack of diffraction pattern. + + Diffraction pattern, whether they were simulated or measured are the raw data + for computational workflows to characterize the phase and orientation + of crystalline regions in matter. + + Steps of post-processing the diffraction patterns should be documented using + method-specific specialized base classes. All eventual post-processing of + resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. + + To implement an example how this base class can be used we focused in FAIRmat + on Kikuchi diffraction pattern here specifically the research community + of Electron Backscatter Diffraction (EBSD). + + For this reason, this base class and related :ref:`NXem_base` classes extend the + work of `M. A. Jackson et al. `_ + (one of the developers of DREAM.3D) and the H5OINA public file format developed by + `P. Pinard et al. `_ with Oxford Instruments. + + Kikuchi pattern are typically collected with FIB/SEM microscopes, + for two- and three-dimensional orientation microscopy. + + For a detailed overview of these techniques see e.g. + + * `M. A. Groeber et al. `_ + * `A. J. Schwartz et al. `_ + * `P. A. Rottman et al. `_ + + Serial-sectioning demands a recurrent sequence of ion milling and measuring. + This suggests that each serial section is at least an own NXevent_data_em + instance. The three-dimensional characterization as such demands a computational + step where the maps for each serial section get cleaned, aligned, and registered + into an image stack. This image stack represents a digital model of the + inspected microstructural volume. Often this volume is called a (representative) + volume element (RVE). Several software packages exists for performing + these post-processing tasks. + + This example may inspire users of other types of diffraction methods. +symbols: + n_sc: | + Number of scanned points. Scan point may have none, one, or more pattern. + n_p: | + Number of diffraction pattern. + n_y: | + Number of pixel per pattern in the slow direction. + n_x: | + Number of pixel per pattern in the fast direction. +type: group +NXimage_r_set_diff(NXimage_r_set): + pattern_type(NX_CHAR): + doc: | + Category which type of diffraction pattern is reported. + enumeration: [kikuchi] + stack(NXdata): + doc: | + Collected diffraction pattern as an image stack. As raw and closest to the + first retrievable measured data as possible, i.e. do not use this + container to store already averaged, filtered or whatever post-processed + pattern unless these are generated unmodifiably in such manner by the + instrument given the way how the instrument and control software + was configured for your microscope session. + scan_point_identifier(NX_INT): + doc: | + Array which resolves the scan point to which each pattern belongs. + + Scan points are evaluated in sequence starting from scan point zero + until scan point n_sc - 1. Evaluating the cumulated of this array + decodes which pattern in intensity belongs to which scan point. + + Take an example with three scan points: The first scan point has one + pattern, the second has three pattern, the last scan point has no + pattern. In this case the scan_point_identifier are 0, 1, 1, 1. + The length of the scan_point_identifier array is four because four + pattern were measured in total. + + In most cases usually one pattern is averaged by the detector for + some amount of time and then reported as one pattern. + unit: NX_UNITLESS + dim: (n_p,) + intensity(NX_NUMBER): + doc: | + Intensity of the diffraction pattern. + unit: NX_UNITLESS + dim: (n_p, n_y, n_x) + # n_p fast 2, n_y faster 1, n_x fastest 0 + # in axes fast to fastest + # while for _indices fastest to fast + \@long_name(NX_CHAR): + doc: | + Pattern intensity + # \@signal: intensity + # \@axes: [pattern_identifier, ypos, xpos] + # \@xpos_indices: 0 + # \@ypos_indices: 1 + # \@pattern_identifier_indices: 2 + pattern_identifier(NX_INT): + doc: | + Pattern are enumerated starting from 0 to n_p - 1. + unit: NX_UNITLESS + dim: (n_p,) + \@long_name(NX_CHAR): + doc: | + Pattern identifier + # the following fields are taken from the NXimage_r_set base class + # axis_y(R): + # axis_x(R): + +# If we envision a (knowledge) graph for EBSD it consists of individual sub-graphs +# which convey information about the specimen preparation, the measurement of +# the specimen in the electron microscope, the indexing of the collected +# Kikuchi pattern stack, eventual post-processing of the indexed orientation +# images via similarity grouping algorithms to yield (grains, texture). +# Conceptually, these post-processing steps are most frequently serving +# the idea how can one reconstruct so-called microstructural features +# (grains, phases, interfaces) to infer material properties. +# In practice this calls for workflows which quantify correlations between +# the spatial arrangement of the microstructural features, the individual +# (thermodynamic, chemo-mechanical) properties of the features with the +# properties of materials at a coarser scale. +# With NXem and related NXms base classes we propose a covering +# and general solution how to handle such (meta)data with NeXus. diff --git a/contributed_definitions/nyaml/NXms_ipf.yaml b/contributed_definitions/nyaml/NXms_ipf.yaml new file mode 100644 index 000000000..11bfc5983 --- /dev/null +++ b/contributed_definitions/nyaml/NXms_ipf.yaml @@ -0,0 +1,299 @@ +category: base +doc: | + Base class to store an inverse pole figure (IPF) mapping (IPF map). +symbols: + # how to make this optional + n_z: | + Number of pixel along the z slowest direction. + n_y: | + Number of pixel along the y slow direction. + n_x: | + Number of pixel along the x fast direction. + n_rgb: | + Number of RGB values along the fastest direction, always three. + d: | + Dimensionality of the mapping (either 2 or 3). +type: group +NXms_ipf(NXprocess): + \@depends_on(NX_CHAR): + doc: | + Reference to the coordinate system whereby the projection_direction is defined. + + If the field depends_on is not provided but a parent of the instance + of this base class or its specialization defines an :ref:`NXcoordinate_system_set` + and exactly one :ref:`NXcoordinate_system`, the reference points to this system. + + If nothing is provided and none of the above-mentioned references pointing + in a parent, McStas is assumed. + projection_direction(NX_NUMBER): + doc: | + The direction along which orientations are projected. + unit: NX_UNITLESS + dim: (3,) + input_grid(NXcg_grid): + doc: | + Details about the original grid. + + Here original grid means the one onto which the IPF map was computed + when exported from the tech partner's file format representation. + output_grid(NXcg_grid): + doc: | + Details about the grid onto which the IPF is recomputed. + + Rescaling the visualization of the IPF map may be needed to enable + visualization in specific software tools like H5Web. + The value specifies the fractional change of the spacing between + the original mapping and the scaled one. + interpolation(NX_CHAR): + doc: | + How where orientation values at the location of the output grid + positions computed. + + Nearest neighbour means the orientation of the closed (Euclidean distance) + grid point of the input_grid was taken. + enumeration: [nearest_neighbour] + map(NXdata): + doc: | + Inverse pole figure mapping. + + Default inverse pole figure (IPF) plot of the data specific for each + phase. No ipf_mapID instances for non-indexed scan points as these are + by definition assigned the null phase with phase_identifier 0. + Inspect the definition of :ref:`NXcrystal_structure` and its field + phase_identifier for further details. + + Details about possible regridding and associated interpolation + during the computation of the IPF map visualization can be stored + using the input_grid, output_grid, and interpolation fields. + + The main purpose of this map is to offer a normalized default representation + of the IPF map for consumption by a research data management system (RDMS). + This is aligned with the first aim of :ref:`NXms_ipf`, to bring colleagues and + users of IPF maps together to discuss which pieces of information + need to be stored together. We are convinced a step-by-step design and + community-driven discussion about which pieces of information should + and/or need to be included is a practical strategy to work towards an + interoperable description and data model for exchanging IPF maps as specific + community-accepted tools to convey orientation maps. + + With this design the individual RDMS solutions and tools can still continue + to support specific custom data analyses workflow and routes but at least + there is one common understanding which enables also those users who are + not necessarily experts in all the details of the underlying techniques + can understand and thus eventually judge if the dataset is worth to be + reused or repurposed. + # \@signal: data + # \@axes: [axis_y, axis_x] + # \@axis_x_indices: 0 + # \@axis_y_indices: 1 + data(NX_NUMBER): + # assume a mapping with step size 0.5 micron + # we need to distinguish + # pixel position, i.e. 0, 1, 2, 3, unit px + # answers in which pixel on the map but map is disconnected from sample surface context + # calibrated pixel position 0., 0.5, 1.0, 1.5, unit micron + # answers in addition physical dimensions (relevant to get crystal extent etc.) but still disconnected from sample surface context + # calibrated pixel position including the offset of the original coordinate system + # answers everything would enable one to point if still in the microscope where on the sample surface each pixel is located + # tech partners oftentimes do not report to more than calibrated pixel position + doc: | + Inverse pole figure color code for each map coordinate. + unit: NX_UNITLESS + dim: (n_y, n_x, 3) # | (n_z, n_y, n_x, 3) + axis_z(NX_NUMBER): + doc: | + Pixel center coordinate calibrated for step size along the z axis of the map. + unit: NX_LENGTH + dim: (n_z,) + # \@long_name(NX_CHAR): + axis_y(NX_NUMBER): + unit: NX_LENGTH + doc: | + Pixel center coordinate calibrated for step size along the y axis of the map. + dim: (n_y,) + # \@long_name(NX_CHAR): + axis_x(NX_NUMBER): + unit: NX_LENGTH + doc: | + Pixel center coordinate calibrated for step size along the x axis of the map. + dim: (n_x,) + # \@long_name(NX_CHAR): + # title: + legend(NXdata): + doc: | + The color code which maps colors into orientation into the fundamental zone. + + For each stereographic standard triangle (SST), i.e. a rendering of the + fundamental zone of the crystal-symmetry-reduced orientation space + SO3, it is possible to define a color model which assigns each point in + the fundamental zone a color. + + Different mapping models are used. These implement (slightly) different + scaling relations. Differences exist across representations of tech partners. + + Differences are which base colors of the RGB color model are placed in + which extremal position of the SST and where the white point is located. + + For further details see: + + * [G. Nolze et al.](https://doi.org/10.1107/S1600576716012942) + * Srikanth Patala and coworkers"'" work and of others. + + Details are implementation-specific and not standardized yet. + + Given that the SST has a complicated geometry, it cannot yet be + visualized using tools like H5Web, which is why for now the matrix + of a rasterized image which is rendered by the backend tool gets + copied into an RGB matrix to offer a default plot. + # \@signal: data + # \@axes: [axis_y, axis_x] + # \@axis_x_indices: 0 + # \@axis_y_indices: 1 + data(NX_NUMBER): + # hehe, but can be larger than one but could also be an NX_DIMENSIONLESS ! + doc: | + Inverse pole figure color code for each map coordinate. + unit: NX_UNITLESS + dim: (n_y, n_x, 3) + axis_y(NX_NUMBER): + doc: | + Pixel along the y-axis. + unit: NX_UNITLESS + dim: (n_y,) + # \@long_name(NX_CHAR): + axis_x(NX_NUMBER): + doc: | + Pixel along the x-axis. + unit: NX_UNITLESS + dim: (n_x,) + # \@long_name(NX_CHAR): + # title: + +# keep this for now for FAIRmat internal documentation +# It is important to mention that we cannot assume, at least for now, +# that the parser which writes to an NXem_ebsd-compliant file is also +# responsible or capable at all of computing the inverse pole figure +# color keys and maps itself. This cannot be assumed working because +# this mapping of orientation data uses involved mathematical algorithms +# and functions which not every tools used in the EBSD community is capable +# of using or is for sure not using in exactly the same way. +# +# Currently, we assume it is the responsibilty of the tool used which +# generated the data under on_the_fly_indexing to compute these +# plots and deliver these to the parser. +# +# Specific case studies have been explored by the experiment team of +# Area B of the FAIRmat project to realize and implement such mapping. +# +# The first case study uses the H5OINA format and the pyxem/orix library. +# As orix is a Python library, the coloring is performed by the em_om parser. +# +# The second case study uses MTex and its EBSD color coding model. +# As MTex is a Matlab tool, an intermediate format is written from MTex +# first which stores these pieces of information. The parser then pulls +# these data from the intermediate Matlab-agnostic representation and +# supplements the file with missing pieces of information as it is +# required by NXem_ebsd. +# +# The third case study shows how a generic set of Kikuchi pattern +# can be loaded with the em_om parser. The pattern are loaded directly +# from a ZIP file and mapped to an simulation image section for now. +# +# The fourth case study uses the DREAM.3D package which provides an own +# set of EBSD data post-processing procedures. DREAM.3D documents the +# processing steps with a pipeline file which is stored inside DREAM.3D +# output files. In this case study, the parser reads the DREAM.3D file +# and maps data relevant from the perspective of NXem_ebsd plus adds +# relevant IPF color maps as they were computed by DREAM.3D. +# Given that in this case the origin of the data is the DREAM.3D file +# again provenance is kept and more details can be followed upon when +# resolving origin. +# +# These examples offer a first set of suggestions on how to make EBSD +# data injectable into research data management system using schemes +# which themselves are agnostic to the specific RDMS and interoperable. +# Steps of collecting the raw data and post-processing these with custom +# scripts like MTex or commercial tools so far are mainly undocumented. +# The limitation is that a program which consumes results or dump files +# from these tools may not have necessarily all the sufficient information +# available to check if the injected orientation data and color models +# are matching the conventions which a user or automated system has +# injected into an electronic lab notebook from which currently the em_om +# parser collects the conventions and stores them into this NXem_ebsd instance. +# The immediate benefit of the here presented NXem_ebsd concept though +# is that the conventions and reference frame definitions are expected +# in an ELN-agnostic representation to make NXem_ebsd a generally useful +# data scheme for EBSD. +# +# Ideally, the em_om parser would load convention-compliant EBSD data +# and use subsequently a community library to transcode/convert orientation +# conventions and parameterized orientation values. Thereafter, convention- +# compliant default plot(s) could be created that would be truely interoperable. +# +# However, given the variety of post-processing tools available surplus +# the fact that these are not usually executed along standardized +# post-processing workflows which perform exactly the same algorithmic steps, +# this is currently not a practically implementable option. Indeed, first +# developers who wish to implement this would first have to create a library +# for performing such tasks, mapping generally between conventions, +# i.e. map and rotate coordinate systems at the parser level. +# +# The unfortunate situation in EBSD is that due to historical reasons +# and competitive strategies, different players in the field have +# implemented (slightly) different approaches each of which misses +# some part of a complete workflow description which is behind EBSD analyses: +# Sample preparation, measurement, indexing, post-processing, paper... +# +# The here exemplified default plot do not so far apply relevant rotations +# but takes the orientation values as they come from the origin and using +# coloring them as they come. It is thus the scientists responsibility to +# enter and check if the respective dataset is rotation-conventions-wise +# consistent and fit for a particular task. +# +# Ideally, with all conventions defined it can be possible to develop +# a converter which rotates the input data. This application definition +# does not assume this and users should be aware of this limitation. +# +# The key point is that the conventions however are captured and this is +# the most important step to the development of such a generic transcoder +# for creating interoperable EBSD datasets. +# +# Currently the conventions remain in the mind or manual lab book of the +# respective scientists or technicians instead of getting stored and +# communicated with research papers that are written based on +# specific dataset, i.e. database entries. +# +# The default gridded representation of the data should not be +# misinterpreted as the only possible way how EBSD data and OIM +# maps can be created! +# +# Indeed, the most general case is that patterns are collected for +# scan points. The scan generator of an electron microscope is instructed +# to steer the beam in such a way across the specimen surface that the +# beam illuminates certain positions for a certain amount time (usually +# equally-spaced and spending about the same amount of time at each +# position). +# +# Therefore, scan positions can be due to such regular flight plans and +# represent sampling on lines, line stacks, rectangular regions-of- +# interests, but also could instruct spiral, random, or adaptive scans +# instead of tessellations with square or hexagonal pixels. +# +# The majority of EBSD maps is though is reporting results for a regular +# grid (square, hexagon). What matters though in terms of damage induced +# by the electron beam and signal quality is the real electron dose +# history, i.e. for how long the beam exposed which location of the +# specimen. Especially when electron charging occurs (i.e. an excess +# amount of charge accumulates due to e.g. poor conducting away of this +# charge or an improper mounting, too high dose, etc. such details are +# relevant. +# +# Specifically, the default visualization is an inverse pole-figure (IPF) +# map with the usual RGB color coding. Different strategies and +# normalization schemes are in use to define such color coding. +# +# Finally, we should mention that each ipf_map represents data for +# scan points indexed as one phase. The alias/name of this phase should +# be stored in phase_name, the phase_identifier give an ID which must +# not be zero as this value is reserved for non-indexed / null model scan +# points. \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXms_ipf_set.yaml b/contributed_definitions/nyaml/NXms_ipf_set.yaml new file mode 100644 index 000000000..a783655a2 --- /dev/null +++ b/contributed_definitions/nyaml/NXms_ipf_set.yaml @@ -0,0 +1,9 @@ +category: base +doc: | + Base class to group multiple :ref:`NXms_ipf` instances. + + A collection of inverse pole figure approximations. +# symbols: +type: group +NXms_ipf_set(NXprocess): + (NXms_ipf): diff --git a/contributed_definitions/nyaml/NXms_mtex_config.yaml b/contributed_definitions/nyaml/NXms_mtex_config.yaml new file mode 100644 index 000000000..b8fee982d --- /dev/null +++ b/contributed_definitions/nyaml/NXms_mtex_config.yaml @@ -0,0 +1,187 @@ +category: base +doc: | + Base class to store the configuration when using the MTex/Matlab software. + + MTex is a Matlab package for texture analysis used in the Materials and Earth Sciences. + See `R. Hielscher et al. `_ and + the `MTex source code `_ for details. +type: group +NXms_mtex_config(NXobject): + conventions(NXcollection): + doc: | + Reference frame and orientation conventions. + Consult the `MTex docs `_ for details. + x_axis_direction(NX_CHAR): + doc: | + TODO with MTex developers + # enumeration: + # check against v5.12 + z_axis_direction(NX_CHAR): + doc: | + TODO with MTex developers + # enumeration: + a_axis_direction(NX_CHAR): + doc: | + TODO with MTex developers + # enumeration: + b_axis_direction(NX_CHAR): + doc: | + TODO with MTex developers + # enumeration: + euler_angle(NX_CHAR): + doc: | + TODO with MTex developers + enumeration: [unknown, undefined, bunge] + plotting(NXcollection): + doc: | + Settings relevant for generating plots. + font_size(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY + inner_plot_spacing(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY + outer_plot_spacing(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY + marker_size(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY + figure_size(NX_NUMBER): + doc: | + TODO with MTex developers + show_micron_bar(NX_BOOLEAN): + doc: | + True if MTex renders a scale bar with figures. + show_coordinates(NX_BOOLEAN): + doc: | + True if MTex renders a grid with figures. + pf_anno_fun_hdl: + doc: | + Code for the function handle used for annotating pole figure plots. + color_map(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_UNITLESS + dim: (i, 3) + default_color_map(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_UNITLESS + dim: (i, 3) + # phase_color_order: + # doc: | + # TODO with MTex developers + # unit: NX_UNITLESS + # dim: (i,) + color_palette(NX_CHAR): + degree_char(NX_CHAR): + doc: | + TODO with MTex developers + arrow_char(NX_CHAR): + doc: | + TODO with MTex developers + marker(NX_CHAR): + doc: | + TODO with MTex developers + marker_edge_color(NX_CHAR): + doc: | + TODO with MTex developers + marker_face_color(NX_CHAR): + doc: | + TODO with MTex developers + hit_test(NX_BOOLEAN): + doc: | + TODO with MTex developers + miscellaneous(NXcollection): + doc: | + Miscellaneous other settings of MTex. + mosek(NX_BOOLEAN): + doc: | + TODO with MTex developers + generating_help_mode(NX_BOOLEAN): + doc: | + TODO with MTex developers + methods_advise(NX_BOOLEAN): + doc: | + TODO with MTex developers + stop_on_symmetry_mismatch(NX_BOOLEAN): + doc: | + TODO with MTex developers + inside_poly(NX_BOOLEAN): + doc: | + TODO with MTex developers + text_interpreter: + numerics(NXcollection): + doc: | + Miscellaneous settings relevant for numerics. + eps(NX_NUMBER): + doc: | + Return value of the Matlab eps command. + unit: NX_UNITLESS + fft_accuracy(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY # NX_LENGTH or NX_RECIPROCAL_LENGTH? + max_stwo_bandwidth(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY # radiant? + max_sothree_bandwidth(NX_NUMBER): + doc: | + TODO with MTex developers + unit: NX_ANY # radiant? + system(NXcollection): + doc: | + Miscellaneous settings relevant of the system where MTex runs. + memory(NX_NUMBER): + doc: | + TODO with MTex developers + open_gl_bug(NX_BOOLEAN): + doc: | + TODO with MTex developers + save_to_file(NX_BOOLEAN): + doc: | + TODO with MTex developers + path(NXcollection): + doc: | + Collection of paths from where MTex reads information and code. + mtex(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + data(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + cif(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + ebsd(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + pf(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + odf(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + tensor(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + example(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + import_wizard(NX_CHAR): + doc: | + Absolute path to specific component of MTex source code. + pf_extensions(NX_CHAR): + doc: | + List of file type suffixes for which MTex assumes + texture/pole figure information. + ebsd_extensions(NX_CHAR): + doc: | + List of file type suffixes for which MTex assumes EBSD content. + # version as an instance of (NXprogram) one for MTex one for Matlab diff --git a/contributed_definitions/nyaml/NXms_odf.yaml b/contributed_definitions/nyaml/NXms_odf.yaml new file mode 100644 index 000000000..92ad96589 --- /dev/null +++ b/contributed_definitions/nyaml/NXms_odf.yaml @@ -0,0 +1,99 @@ +category: base +doc: | + Base class to store an orientation distribution function (ODF) computation. +symbols: + n_varphi_one: | + Number of pixel per varphi section plot along the varphi_one fastest direction. + n_capital_phi: | + Number of pixel per varphi section plot along the capital_phi slow direction. + n_varphi_two: | + Number of pixel per varphi section plot along the varphi_two slowest direction. + k: | + Number of local maxima evaluated in the component analysis. +type: group +NXms_odf(NXprocess): + configuration(NXobject): + doc: | + Details about the algorithm used for computing the ODF. + crystal_symmetry_point_group(NX_CHAR): + doc: | + Point group of the crystal structure (International Table of Crystallography) + of the phase for which the here documented phase-dependent ODF was computed. + specimen_symmetry_point_group(NX_CHAR): + doc: | + Point group assumed for processing-induced *sample symmetries*. + (according to International Table of Crystallography). + kernel_halfwidth(NX_NUMBER): + doc: | + Halfwidth of the kernel. + unit: NX_ANGLE + kernel_name(NX_CHAR): + doc: | + Name of the kernel. + resolution(NX_NUMBER): + doc: | + Resolution of the kernel. + unit: NX_ANGLE + kth_extrema(NXobject): + kth(NX_UINT): + doc: | + Number of local maxima evaluated for the ODF. + unit: NX_UNITLESS + # value of kth should be k + location(NX_NUMBER): + doc: | + Euler angle representation of the kth-most maxima of the ODF + in decreasing order of the intensity maximum. + unit: NX_ANGLE + dim: (k, 3) + theta(NX_NUMBER): + doc: | + Disorientation threshold within which intensity of the ODF + is integrated for the component analysis. + unit: NX_ANGLE + volume_fraction(NX_NUMBER): + doc: | + Integrated ODF intensity within a theta-ball of SO3 about + each location as specified for each location in the order + and reported in the order of these locations. + unit: NX_ANY + dim: (k,) + phi_two_plot(NXdata): + doc: | + Visualization of the ODF intensity as orthogonal sections through Euler space. + + This is one example of typical default plots used in the texture + community in Materials Engineering. + + Mind that the Euler space is a distorted space. Therefore, equivalent + orientations show intensity contributions in eventually multiple + locations. + # \@signal: intensity + # \@axes: [varphi_two, capital_phi, varphi_one] + # \@varphi_one_indices: 0 + # \@capital_phi: 1 + # \@varphi_two_indices: 2 + intensity(NX_NUMBER): + doc: | + ODF intensity at probed locations relative to + null model of a completely random texture. + unit: NX_DIMENSIONLESS + dim: (n_varphi_two, n_capital_phi, n_varphi_one) + varphi_one(NX_NUMBER): + doc: | + Pixel center angular position along the :math:`\varphi_1` direction. + unit: NX_ANGLE + dim: (n_varphi_one,) + # \@long_name(NX_CHAR): + varphi_two(NX_NUMBER): + doc: | + Pixel center angular position along the :math:`\varphi_2` direction. + unit: NX_ANGLE + dim: (n_varphi_two,) + # \@long_name(NX_CHAR): + capital_phi(NX_NUMBER): + doc: | + Pixel center angular position along the :math:`\Phi` direction. + unit: NX_ANGLE + dim: (n_capital_phi,) + # \@long_name(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXms_odf_set.yaml b/contributed_definitions/nyaml/NXms_odf_set.yaml new file mode 100644 index 000000000..5ea1c4d6c --- /dev/null +++ b/contributed_definitions/nyaml/NXms_odf_set.yaml @@ -0,0 +1,9 @@ +category: base +doc: | + Base class to group multiple :ref:`NXms_odf` instances. + + A collection of orientation distribution function approximations. +# symbols: +type: group +NXms_odf_set(NXprocess): + (NXms_odf): diff --git a/contributed_definitions/nyaml/NXms_pf.yaml b/contributed_definitions/nyaml/NXms_pf.yaml new file mode 100644 index 000000000..09ab12f78 --- /dev/null +++ b/contributed_definitions/nyaml/NXms_pf.yaml @@ -0,0 +1,59 @@ +category: base +doc: | + Base class to store a pole figure (PF) computation. +symbols: + n_y: | + Number of pixel per pole figure in the slow direction. + n_x: | + Number of pixel per pole figure in the fast direction. +type: group +NXms_pf(NXprocess): + configuration(NXobject): + doc: | + Details about the algorithm that was used to compute the pole figure. + crystal_symmetry_point_group(NX_CHAR): + doc: | + Point group of the crystal structure of the phase for which the + here documented phase-dependent pole figure was computed + (according to International Table of Crystallography). + specimen_symmetry_point_group(NX_CHAR): + doc: | + Point group assumed for processing induced *sample symmetries* + (according to International Table of Crystallography). + halfwidth(NX_NUMBER): + doc: | + Halfwidth of the kernel. + unit: NX_ANGLE + miller_indices(NX_CHAR): + doc: | + Miller indices (:math:`(hkl)[uvw]`) to specify the pole figure. + resolution(NX_NUMBER): + doc: | + Resolution of the kernel. + unit: NX_ANGLE + pf(NXdata): + doc: | + Pole figure. + # \@signal: intensity + # \@axes: [axis_y, axis_x] + # \@axis_x_indices: 0 + # \@axis_y_indices: 1 + intensity(NX_NUMBER): + doc: | + Pole figure intensity. + unit: NX_UNITLESS + dim: (n_y, n_x) + axis_y(NX_NUMBER): + doc: | + Pixel center along y direction in the equatorial plane of + a stereographic projection of the unit sphere. + unit: NX_ANY + dim: (n_y,) + # \@long_name(NX_CHAR): + axis_x(NX_NUMBER): + doc: | + Pixel center along x direction in the equatorial plane of + a stereographic projection of the unit sphere. + unit: NX_ANY + dim: (n_x,) + # \@long_name(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXms_pf_set.yaml b/contributed_definitions/nyaml/NXms_pf_set.yaml new file mode 100644 index 000000000..afd785f15 --- /dev/null +++ b/contributed_definitions/nyaml/NXms_pf_set.yaml @@ -0,0 +1,9 @@ +category: base +doc: | + Base class to group multiple :ref:`NXms_pf` instances. + + A collection of pole figure approximations. +# symbols: +type: group +NXms_pf_set(NXprocess): + (NXms_pf): diff --git a/contributed_definitions/nyaml/NXms_recon.yaml b/contributed_definitions/nyaml/NXms_recon.yaml new file mode 100644 index 000000000..bd6825bac --- /dev/null +++ b/contributed_definitions/nyaml/NXms_recon.yaml @@ -0,0 +1,315 @@ +# position would need another depends_on the specific coordinate system used, currently we assume McStas +# roi1/ebsd/microstructure1 +category: base +doc: | + Base class to describe discretized (micro)structural features of a material. + + One instance of this base class can be used to describe the current configuration + the base class does not include time-dependent descriptions for the sake of + clarity and because of the fact that virtually all simulations or experiments + probe time by sampling. Therefore, time-dependent state descriptions should + be realized with creating a set of :ref:`NXms_snapshot_set` with instances of + :ref:`NXms_snapshot` using e.g. :ref:`NXms_recon` base class instances. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. + # in so-called linear intercept analysis we observe + # one-dimensional sections of either projections (see below) + # or true one-dimensional cuts across a volume of material + # n_icept: | + # The number of linear intercepts defined. + # n_c_one: | + # The number of crystal projections segmented by crossing (projected or real) interfaces + # n_i_one: | + # The number of crossings + # two-dimensional projections of characterized in reality three-dimensional objects + # using E. E. Underwood notation + # crystals/grains are projections that are delineated by projections of interface, i.e. interface lines which meet at projections of triple lines i.e. triple "points" + n_c_two: | + The number of crystal projections. + n_i_two: | + The number of interface projections. + n_t_two: | + The number of assumed triple junction projections aka triple points. + # three-dimensional real objects, volumetrically characterized + # crystals are delineated by interfaces that are delineated by triple lines that meet at quad junctions + n_c: | + The number of crystals. + n_i: | + The number of interfaces + n_t: | + The number of triple lines + n_q: | + The number of quadruple junctions. +type: group +NXms_recon(NXobject): + # as e.g. a result of one grain reconstruction with MTex or othe + # grain reconstruction software in commercial tools + # the idea is we may wish to run as many grain reconstructions as we want... + # add details about the processing + configuration(NXprocess): + doc: | + The configuration and parameterization of the reconstruction algorithm + whereby the microstructural features were identified. + # maybe a depends_on what was the input however if the group is injected + # in an roi1/ebsd instance isnt this information implicit? + dimensionality(NX_POSINT): + doc: | + Dimensionality of the analysis. + + This field can be used e.g. by a research data management system + to identify if the described feature set specifies a + one-, two-, or three-dimensional feature set. + unit: NX_UNITLESS + enumeration: [1, 2, 3] + algorithm(NX_CHAR): + doc: | + Which algorithm is used to reconstruct the features. + enumeration: [unknown, disorientation_clustering, fast_multiscale_clustering, markov_chain_clustering] + disorientation_threshold(NX_NUMBER): + doc: | + Threshold to define at which disorientation angle to assume + two crystalline regions have a significant orientation difference + which warrants to argue that there is an interface between the + two regions. + unit: NX_ANGLE + # the result of running one grain reconstruction + # ms_feature_set1 + # we could also enumerate instances ms_feature_setID here because configuration + # may specify a range of different parameter resulting in multiple ms_feature_sets + # dimensionality(N) composed from NXms_feature_set base: + # controlled vocabulary of base class instances to be used to inform about the + # discretization of these features instances to discretize the features + # wherever possible the computational geometry specific instances whose + # purpose is only to support/represent the discretization of the features should + # be separated out from the materials engineering interpretation of what these + # features are, i.e. a grain that is measured with a 2d section ends up + # modelled as an projection of that real 3d grain object + # the model is discretized usign a polyline which models the location of the + # interface at the required here coarse-grained continuum picture + points(NXcg_point_set): + lines(NXcg_polyline_set): + surfaces(NXcg_triangle_set): + volumes(NXcg_polyhedron_set): + + # domain-specific, i.e. microstructural features + # ONE DIMENSIONAL FEATURES + + # TWO DIMENSIONAL FEATURES + crystal_projections(NXms_feature_set): + doc: | + Projections of crystals on the sample surface as typically + characterized with optical or electron microscopy. + \@discretization(NX_CHAR): + doc: | + Reference to lines(NXcg_polyline_set) which supports the + discretized shape of each cross-sectioned crystal. + + Most microscopy techniques support to generate only a two-dimensional + representation (projection) of the characterized material. + + For true volumetric techniques use the specifically + specialized crystals :ref:`NXms_feature_set` instead. + See stereology literature for more details e.g. + E.E. Underwood's book entitled Quantitative Stereology + number_of_crystals(NX_UINT): + doc: | + Number of crystals. + unit: NX_UNITLESS + crystal_identifier_offset(NX_INT): + doc: | + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + unit: NX_UNITLESS + crystal_identifier(NX_INT): + doc: | + Identifier used for crystals for explicit indexing. + unit: NX_UNITLESS + dim: (n_c_two,) + number_of_phases(NX_UINT): + doc: | + How many phases are distinguished + unit: NX_UNITLESS + phase_identifier_offset(NX_INT): + doc: | + Integer offset whereby the identifier of the first member + of the set differs from zero. + unit: NX_UNITLESS + phase_identifier(NX_INT): + # \@depends_on(NX_CHAR): + doc: | + Identifier used for phase for explicit indexing. + unit: NX_UNITLESS + dim: (n_c_two,) + # properties of crystal_projections aka grain properties + boundary_contact(NX_BOOLEAN): + doc: | + True, if the crystal makes contact with the edge of the ROI, + false otherwise. + dim: (n_c_two,) + orientation_spread(NX_NUMBER): + doc: | + Average disorientation angle between individual orientation of the + crystal at probed positions (weighted by area of that position) versus + the average disorientation of the crystal. + unit: NX_ANGLE + dim: (n_c_two,) + (NXrotation_set): + area(NX_NUMBER): + doc: | + Calibrated area of surrounded by the polyline about each crystal. + unit: NX_AREA + dim: (n_c_two,) + interface_projections(NXms_feature_set): + # grain boundaries have a network of line-like defects, its explicit description + # often generates unnecessary information duplication and cluttering, + # therefore here a compact and suggestion how to store such data + doc: | + Projections of grain or phase boundaries as typically sectioned + with optical or electron microscopy characterization. + \@discretization(NX_CHAR): + doc: | + Reference to lines(NXcg_polyline_set) which supports the + discretized shape of each cross-sectioned crystal. + + Set of tuples of polyline segments which build the interface. + # topology + # i) Set of pair of crystals sharing an interface + crystals(NX_INT): + doc: | + Set of pairs of crystal_identifier resolved via depends_on which + are adjacent to each interface. + unit: NX_UNITLESS + dim: (n_i_two, 2) + \@depends_on(NX_CHAR): + doc: | + The specific crystal_projections(NXms_feature_set) instance + to resolve crystal identifier. + # ii) Set of pair of topologically connected triple points + triple_points(NX_INT): + doc: | + Set of pairs of triple_point_identifier which the interface connects. + For 2D projections of 3D microstructural features a triple point is + physically only the projection of a triple line. + unit: NX_UNITLESS + dim: (n_i_two, 2) + \@depends_on(NX_CHAR): + doc: | + The specific triple_line_projections(NXms_feature_set) instance + whereby to resolve triple_point identifier. + # alternatively which polyline of adjoining interfaces + # properties, descriptors + length(NX_NUMBER): + doc: | + The length of the interface. + + This is not necessarily the same as the length of the individual + polyline segments whereby the interface is discretized. + + The actual coordinate system whereby the geometry is calibrated + with real physical dimensions is typically documented by the + depends_on attribute of the respective NXcg_primitive_set. + This depends_on attribute should point explicitly to an + instance of a :ref:`NXcoordinate_system` to support users as + much as possible with interpreting how and where the lines are + located in the reference frame. + unit: NX_LENGTH + dim: (n_i_two,) + interface_identifier_offset(NX_INT): + doc: | + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + unit: NX_UNITLESS + interface_identifier(NX_INT): + doc: | + Identifier for each interface using explicit indexing. + unit: NX_UNITLESS + dim: (n_i_two,) + triple_line_projections(NXms_feature_set): + # only for 2D, quad junction is the equivalent for 3D is not a triple_line + # four alternative descriptors with different strength to specify spatial + # or logical information about the triple junction feature set. + # the explicit description often generating unnecessary information duplication + doc: | + Projections of triple lines as typically characterized with optical + or electron microscopy. + + Mind that most specimens are thermo-chemo-mechanically treated before + they are characterized. Therefore, the projected crystal defects are + have physically no longer the same structure as in the bulk. + + Examples are manifest as effects such as thermal grooving, or relaxation + effects of an intersection between a triple line that is cut + by the specimen surface as these defects are then exposed typically + to a different atmosphere and hence have different thermodynamic boundary + conditions than of their true volumetric defects in the bulk. + \@discretization(NX_CHAR): + doc: | + Reference to points(NXcg_point_set) which supports the + locations of these triple points. + # another view to describe a triple junction is via its topology/connection expressed either via + # i) triplet of interface identifier + number_of_triple_points(NX_UINT): + doc: | + Number of triple points. + unit: NX_UNITLESS + triple_point_identifier_offset(NX_INT): + doc: | + Integer offset whereby the identifier of the first member + of the set differs from zero. + + Identifiers can be defined either implicitly or explicitly. + For implicit indexing identifiers are defined on the interval + :math:`[identifier_offset, identifier_offset + c - 1]`. + unit: NX_UNITLESS + triple_point_identifier(NX_INT): + doc: | + Identifier for each triple point using explicit indexing. + unit: NX_UNITLESS + dim: (n_t_two,) + location(NX_INT): + doc: | + Set of triple point identifiers. + unit: NX_UNITLESS + dim: (n_t_two,) + \@depends_on(NX_CHAR): + doc: | + The relevant points(NXcg_point_set) instance whereby to + resolve interface identifiers. + interfaces(NX_INT): # aka topology or interfaces + doc: | + Set of triplets of identifier of line-like features. + Each triplet resolves which three interface projections + the triple point connects. + unit: NX_UNITLESS + dim: (n_t_two, 3) + \@depends_on(NX_CHAR): + doc: | + The specific interface_projections(NXms_feature_set) + instance whereby to resolve interface identifiers. + # ii) a triplet of line segment identifier whereby the point-like features + # is assumed discretized via three polylines representing interfaces + polylines(NX_INT): + doc: | + Triplet of identifier of polyline segments. Each triplet resolves + which three segments of polyline segments the triple junction connects. + unit: NX_UNITLESS + dim: (n_t_two, 3) + \@depends_on(NX_CHAR): + doc: | + The specific lines(NXcg_polyline_set) instance to resolve + polyline segments. + # the difference in the interpretation of interfaces and polylines + # is that the interface resolves interface (e.g. phase boundary names) + # while polylines resolves segments within the set of named geometric primitive + # instances! + # add all sort of other qualitative or quantitive descriptors (triple junction + # energy, volume etc), i.e properties of that triple point diff --git a/contributed_definitions/nyaml/NXroi.yaml b/contributed_definitions/nyaml/NXroi.yaml new file mode 100644 index 000000000..a8ba2426a --- /dev/null +++ b/contributed_definitions/nyaml/NXroi.yaml @@ -0,0 +1,9 @@ +category: base +doc: | + Base class to describe a region-of-interest analyzed. +type: group +NXroi(NXobject): + (NXprocess): + doc: | + Details about processing steps. + sequence_index(NX_INT): diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index b21ad199e..07aa6ee4e 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -19,19 +19,22 @@ a design strategy and workflow whereby physics-based modelling of microstructure evolution is used to understand the relations between the microstructure and its technologically relevant descriptors to understand and tailor properties of materials. -The following application definitions are proposed to support the discussion -how materials engineering-specific data schemas can connect to or be mapped on +The following application definitions are proposed to support the discussion on how +materials-engineering-specific data schemas can connect to or be mapped on concepts which are equally modellable with NeXus: :ref:`NXms`: An application definition for arbitrary spatiotemporally resolved simulations. + :ref:`NXms_recon`: + A base class for documenting results of reconstructed microstructures. + :ref:`NXms_score_config`: - A specific example how :ref:`NXapm_paraprobe_config_ranger` can be + A specific example of how :ref:`NXapm_paraprobe_config_ranger` can be specialized for documenting the configuration of a computer simulation with the static recrystallization cellular automata model SCORE. :ref:`NXms_score_results`: - A specific example how :ref:`NXms` can be specialized for documenting + A specific example of how :ref:`NXms` can be specialized for documenting results of computer simulations with the static recrystallization cellular automata model SCORE. From 7b060afd7e934b7564ec037b8de76eb949cccba3 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 13 Dec 2023 13:20:56 +0100 Subject: [PATCH 017/136] Fixed missing references to EM/CGMS/ICME-related base classes in the documentation, adding first round of changes relevant for the implementation of the refactoring of the em-related readers in pynxtools # Conflicts: # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXserialized.nxdl.xml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXserialized.yaml # manual/source/classes/contributed_definitions/cgms-structure.rst # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXem_base.nxdl.xml | 85 ++++++++++---------- contributed_definitions/nyaml/NXem_base.yaml | 75 ++++++++--------- manual/source/cgms-structure.rst | 12 ++- 3 files changed, 90 insertions(+), 82 deletions(-) diff --git a/contributed_definitions/NXem_base.nxdl.xml b/contributed_definitions/NXem_base.nxdl.xml index 479819893..e1add30bd 100644 --- a/contributed_definitions/NXem_base.nxdl.xml +++ b/contributed_definitions/NXem_base.nxdl.xml @@ -27,7 +27,7 @@ description on the NeXus front-page is overwhelming considering what we learned from the diataxis workshop we write here a specification neither a how to nor a tutorial which explains all the context because we address here developers of software--> - + @@ -48,34 +48,10 @@ template to be used for an application definition to explore physical mechanisms and phenomena, or the desire to characterize materials using electron microscopy. - - - A collection of all programs and libraries which are considered relevant - to understand with which software tools this NeXus file instance was - generated. Ideally, to enable a binary recreation from the input data. - - Examples include the name and version of the libraries used to write the - instance. Ideally, the software that writes these :ref:`NXprogram` instances - also includes the version of the set of NeXus classes i.e. the specific - set of base classes, application definitions, and contributed definitions - with which the here described concepts can be resolved. - - For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ - which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ - research data management system, it makes sense to store e.g. the GitHub - repository commit and respective submodule references used. - - - - - The configuration of the I/O writer software (e.g. `pynxtools <https://github.com/FAIRmat-NFDI/pynxtools>`_) - which was used to generate this NeXus file instance. - - @@ -91,6 +67,30 @@ where scientists just store conventions without a default plot--> + + + The configuration of the I/O writer software (e.g. `pynxtools <https://github.com/FAIRmat-NFDI/pynxtools>`_) + which was used to generate this NeXus file instance. + + + + A collection of all programs and libraries which are considered relevant + to understand with which software tools this NeXus file instance was + generated. Ideally, to enable a binary recreation from the input data. + + Examples include the name and version of the libraries used to write the + instance. Ideally, the software which writes these NXprogram instances + also includes the version of the set of NeXus classes i.e. the specific + set of base classes, application definitions, and contributed definitions + with which the here described concepts can be resolved. + + For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ + which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ + research data management system, it makes sense to store e.g. the GitHub + repository commit and respective submodule references used. + + + Ideally, a (globally) unique persistent identifier @@ -150,25 +150,26 @@ where scientists just store conventions without a default plot--> - - - The program and eventual software libraries used with which the - NeXus instance was created. For the NOMAD OASIS research data - management system e.g. pynxtools and eventually all modules - if desired. - - - - Possibility to store a collection of data artifacts - associated with the experiment. + Possibility to store a collection of serialized resources + that are associated with the experiment. + + An example how to use this set could be to document + from which files generated by software of technology partners + the information in an instance of NXem was filled. + + If resources from technology partners would also be documented + semantically annotated there would not even be a necessity to + copy over specific information in NeXus files as one could write + a inference and information/fact/knowledge retrieval algorithm whereby + a specific piece of information that is related to an experiment or simulation + is just read directly from the respective file of the technology partner. + + The reason why currently this works convincingly in hardly any research + data management system is the strong heterogeneity of the information contained + in such files and the fact that often context and documentation specifically + rich semantic documentation and contextualization is missing. diff --git a/contributed_definitions/nyaml/NXem_base.yaml b/contributed_definitions/nyaml/NXem_base.yaml index 2de8081a8..90461471f 100644 --- a/contributed_definitions/nyaml/NXem_base.yaml +++ b/contributed_definitions/nyaml/NXem_base.yaml @@ -22,31 +22,11 @@ doc: | # specification neither a how to nor a tutorial which explains all the context # because we address here developers of software type: group -NXem_base(NXroot): - (NXprogram): - doc: | - A collection of all programs and libraries which are considered relevant - to understand with which software tools this NeXus file instance was - generated. Ideally, to enable a binary recreation from the input data. - - Examples include the name and version of the libraries used to write the - instance. Ideally, the software that writes these :ref:`NXprogram` instances - also includes the version of the set of NeXus classes i.e. the specific - set of base classes, application definitions, and contributed definitions - with which the here described concepts can be resolved. - - For the `pynxtools library `_ - which is used by the `NOMAD `_ - research data management system, it makes sense to store e.g. the GitHub - repository commit and respective submodule references used. +NXem_base(NXobject): # but should inherit from NXroot # each NeXus file instance should have a default plot # however as there are cases when this cannot be assured we cannot # make the default required, one example is e.g. a NeXus instance # where scientists just store conventions without a default plot - cs_profiling(NXcs_profiling): - doc: | - The configuration of the I/O writer software (e.g. `pynxtools `_) - which was used to generate this NeXus file instance. (NXentry): # means ENTRY(NXentry) \@version(NX_CHAR): doc: | @@ -56,6 +36,26 @@ NXem_base(NXroot): doc: | NeXus NXDL schema to which this file conforms. enumeration: [NXem] + cs_profiling(NXcs_profiling): + doc: | + The configuration of the I/O writer software (e.g. `pynxtools `_) + which was used to generate this NeXus file instance. + (NXprogram): # understood by default as PROGRAM(NXprogram), i.e. program1, program2, ... + doc: | + A collection of all programs and libraries which are considered relevant + to understand with which software tools this NeXus file instance was + generated. Ideally, to enable a binary recreation from the input data. + + Examples include the name and version of the libraries used to write the + instance. Ideally, the software which writes these NXprogram instances + also includes the version of the set of NeXus classes i.e. the specific + set of base classes, application definitions, and contributed definitions + with which the here described concepts can be resolved. + + For the `pynxtools library `_ + which is used by the `NOMAD `_ + research data management system, it makes sense to store e.g. the GitHub + repository commit and respective submodule references used. experiment_identifier(NXidentifier): doc: | Ideally, a (globally) unique persistent identifier @@ -107,23 +107,26 @@ NXem_base(NXroot): the microscope session ended. See docstring of the start_time field to see how the start_time and end_time should be used together. (NXcite): - (NXprogram): - doc: | - The program and eventual software libraries used with which the - NeXus instance was created. For the NOMAD OASIS research data - management system e.g. pynxtools and eventually all modules - if desired. - # the above-description overwrites the default description of the NXprogram base class - # this is composed from the NXprogram base class - # program: - # \@version: - # \@url: - # NXnote and thumbnail dropped for the reason that these are - # arbitrary binary containers without any clear provenance. (NXserialized): doc: | - Possibility to store a collection of data artifacts - associated with the experiment. + Possibility to store a collection of serialized resources + that are associated with the experiment. + + An example how to use this set could be to document + from which files generated by software of technology partners + the information in an instance of NXem was filled. + + If resources from technology partners would also be documented + semantically annotated there would not even be a necessity to + copy over specific information in NeXus files as one could write + a inference and information/fact/knowledge retrieval algorithm whereby + a specific piece of information that is related to an experiment or simulation + is just read directly from the respective file of the technology partner. + + The reason why currently this works convincingly in hardly any research + data management system is the strong heterogeneity of the information contained + in such files and the fact that often context and documentation specifically + rich semantic documentation and contextualization is missing. # using NXserialized here instead of NXnote as the former is more specific (NXuser): doc: | diff --git a/manual/source/cgms-structure.rst b/manual/source/cgms-structure.rst index 4a4950933..563479b17 100644 --- a/manual/source/cgms-structure.rst +++ b/manual/source/cgms-structure.rst @@ -1,9 +1,13 @@ .. _Cg-Structure-Fairmat: -====================== -Computational geometry -====================== +============================ +Geometry and microstructures +============================ -Computational geometry is a frequently used tool for describing the shape and geometry of structural features in materials and components of instruments used for materials characterization. NeXus has a long history of base classes which serve these purposes. Upon closer inspection during the first year of the FAIRmat project, we found though that the collection of base classes could profit from an extension to make working with computational geometry data in NeXus simpler and more fine-grained. +Computational geometry is a frequently used tool for describing the shape and geometry of structural features in materials and components of instruments used for materials characterization. +NeXus has a long history of base classes which serve specifically the former tasks. Upon closer inspection during the first year of the FAIRmat project we found though that the collection of +base classes could profit from an extension to make working with computational geometry data in NeXus simpler and more fine-grained. A status report of this ongoing work is available here: :ref:`CgmsFeatures-Structure`. + +A status report of how these definitions can be of value for the field of Integrated Materials Engineering (ICME) is available here: :ref:`Icme-Structure`. From 6577373df9acf1111335987fb1b74ca84c411d48 Mon Sep 17 00:00:00 2001 From: domna Date: Mon, 8 Jan 2024 16:11:50 +0100 Subject: [PATCH 018/136] Adds proper inputenc # Conflicts: # manual/source/conf.py --- impatient-guide/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/impatient-guide/conf.py b/impatient-guide/conf.py index 5b25e6f16..316e50226 100644 --- a/impatient-guide/conf.py +++ b/impatient-guide/conf.py @@ -185,6 +185,7 @@ 'preamble': '''% \pagestyle{plain} \pagenumbering{arabic} + \usepackage[utf8]{inputenc} ''', } From 975aa69b4792e4fb14b966050f2417170509d042 Mon Sep 17 00:00:00 2001 From: domna Date: Mon, 8 Jan 2024 16:17:43 +0100 Subject: [PATCH 019/136] Fixes config.py bugs # Conflicts: # manual/source/conf.py --- impatient-guide/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impatient-guide/conf.py b/impatient-guide/conf.py index 316e50226..12ce65fc0 100644 --- a/impatient-guide/conf.py +++ b/impatient-guide/conf.py @@ -182,7 +182,7 @@ # FIXME: roman page numbers in TOC, and no page numbers later # http://osdir.com/ml/sphinx-dev/2011-03/msg00036.html # BUT, latex does not recognize these two lines when in the preamble -'preamble': '''% +'preamble': r'''% \pagestyle{plain} \pagenumbering{arabic} \usepackage[utf8]{inputenc} From dc4d9f6ba1225d1b484d37c046c31cec21b73179 Mon Sep 17 00:00:00 2001 From: domna Date: Mon, 8 Jan 2024 16:26:17 +0100 Subject: [PATCH 020/136] Use xelatex for unicode support again # Conflicts: # manual/source/conf.py --- .github/workflows/ci.yaml | 1 + impatient-guide/conf.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7450c7833..055b7eb75 100755 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -76,6 +76,7 @@ jobs: sudo apt-get update -y && \ sudo apt-get install -y \ latexmk \ + texlive-xetex \ texlive-latex-recommended \ texlive-latex-extra \ texlive-fonts-recommended diff --git a/impatient-guide/conf.py b/impatient-guide/conf.py index 12ce65fc0..5b25e6f16 100644 --- a/impatient-guide/conf.py +++ b/impatient-guide/conf.py @@ -182,10 +182,9 @@ # FIXME: roman page numbers in TOC, and no page numbers later # http://osdir.com/ml/sphinx-dev/2011-03/msg00036.html # BUT, latex does not recognize these two lines when in the preamble -'preamble': r'''% +'preamble': '''% \pagestyle{plain} \pagenumbering{arabic} - \usepackage[utf8]{inputenc} ''', } From d6109cf58158c72c92783bf63695b40d2c855b93 Mon Sep 17 00:00:00 2001 From: domna Date: Thu, 11 Jan 2024 08:59:23 +0100 Subject: [PATCH 021/136] mpes-structure.rst cleaned --- manual/source/mpes-structure.rst | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index 809dd3401..f2917cb35 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -4,18 +4,23 @@ Photoemission & core-level spectroscopy ======================================= -The NXmpes application definition aims at describing data and metadata obtained with any possible multidimensional PES setup. -Hence, it is very general and currently the only limitation to the data is that an energy -axis has to be present. -The general experimental techniques described by this application definitions are -photon-in and photoelectron-out. -If you want NXmpes for such a techniques, changes are good you find something useful here. +The NXmpes application definition is designed to describe data and metadata obtained from +various multidimensional photoemission spectroscopy (mpes) techniques. +It is highly versatile, with the only requirement being the presence of an energy axis. -Example techniques covered by this application definition include x-ray/UV photoelectron spectroscopy (XPS/UPS), -angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) or -photoemission electron microscopy (PEEM). -We also include descriptors for advanced specializations, such as spin- and time-resolution, near-ambient pressure conditions, -dichroism and many more. +The experimental techniques covered by this application definition are primarily limited +to photon-in and photoelectron-out methods. If you are searching for related techniques, +there is a good chance you will find valuable information here. + +Example techniques covered by this application definition include: + +- X-ray/UV photoelectron spectroscopy (XPS/UPS) +- Angle-resolved photoemission spectroscopy (ARPES) +- Two-photon photoemission (2PPE) +- Photoemission electron microscopy (PEEM) + +Additionally, we offer descriptors for specialized applications, +such as spin- and time-resolution, near-ambient pressure conditions, dichroism, and more. :ref:`NXmpes`: - A general appdef with minimalistic metadata requirements to describe all photemission experiments. + A universal application definition with minimal metadata requirements for describing all photoemission experiments. From b2845aa9dbf8a407648fab9234165a92beb9702b Mon Sep 17 00:00:00 2001 From: domna Date: Thu, 11 Jan 2024 10:57:36 +0100 Subject: [PATCH 022/136] Add an introductory sentence of appdef list --- manual/source/mpes-structure.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index f2917cb35..f28f6f67e 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -22,5 +22,7 @@ Example techniques covered by this application definition include: Additionally, we offer descriptors for specialized applications, such as spin- and time-resolution, near-ambient pressure conditions, dichroism, and more. +Here's a list of application definitions related to photoemission spectroscopy: + :ref:`NXmpes`: A universal application definition with minimal metadata requirements for describing all photoemission experiments. From 8bb07a9aa685e43e3718b346978c1427e69315d9 Mon Sep 17 00:00:00 2001 From: domna Date: Thu, 11 Jan 2024 14:27:49 +0100 Subject: [PATCH 023/136] Updates docs from Lukas comments --- manual/source/mpes-structure.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index f28f6f67e..e3dc850f0 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -5,11 +5,13 @@ Photoemission & core-level spectroscopy ======================================= The NXmpes application definition is designed to describe data and metadata obtained from -various multidimensional photoemission spectroscopy (mpes) techniques. -It is highly versatile, with the only requirement being the presence of an energy axis. +various multidimensional photoemission spectroscopy (MPES) techniques. +This definition is very flexible and requires just a reasonable amount of +metadata to make the stored data interoperable and reproducible. +The only thing needed for the actual data is the presence of an energy axis. The experimental techniques covered by this application definition are primarily limited -to photon-in and photoelectron-out methods. If you are searching for related techniques, +to photon-in photoelectron-out methods. If you are searching for related techniques, there is a good chance you will find valuable information here. Example techniques covered by this application definition include: From fbbe018f162f6a3a8221a0693153536b5607b70d Mon Sep 17 00:00:00 2001 From: domna Date: Fri, 12 Jan 2024 09:33:15 +0100 Subject: [PATCH 024/136] mpes overview text refined from review comment --- manual/source/mpes-structure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst index e3dc850f0..73a1768c2 100644 --- a/manual/source/mpes-structure.rst +++ b/manual/source/mpes-structure.rst @@ -8,7 +8,7 @@ The NXmpes application definition is designed to describe data and metadata obta various multidimensional photoemission spectroscopy (MPES) techniques. This definition is very flexible and requires just a reasonable amount of metadata to make the stored data interoperable and reproducible. -The only thing needed for the actual data is the presence of an energy axis. +The only requirement for the actual data is the existence of an energy axis. The experimental techniques covered by this application definition are primarily limited to photon-in photoelectron-out methods. If you are searching for related techniques, From 0ff279fb421142ef38c1c6b9c14c941de04603db Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 23 Jan 2024 13:07:09 +0100 Subject: [PATCH 025/136] Updated apm-specific documentation for new base classes and refactoring changes, plus add consistency changes for deprecated isotope_vector # Conflicts: # contributed_definitions/NXapm.nxdl.xml # contributed_definitions/NXapm_charge_state_analysis.nxdl.xml # contributed_definitions/NXapm_paraprobe_config_ranger.nxdl.xml # contributed_definitions/NXapm_paraprobe_config_transcoder.nxdl.xml # contributed_definitions/NXapm_paraprobe_ranger_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_results_ranger.nxdl.xml # contributed_definitions/NXapm_paraprobe_results_transcoder.nxdl.xml # contributed_definitions/NXapm_paraprobe_transcoder_results.nxdl.xml # contributed_definitions/NXion.nxdl.xml # contributed_definitions/nyaml/NXapm.yaml # contributed_definitions/nyaml/NXapm_charge_state_analysis.yaml # contributed_definitions/nyaml/NXapm_paraprobe_ranger_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_transcoder_results.yaml # contributed_definitions/nyaml/NXion.yaml --- .../contributed_definitions/apm-structure.rst | 131 +++++++++--------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index 1e8b36152..aec8883be 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -10,8 +10,6 @@ Atom-probe tomography ApmBC StatusQuoApm ApmParaprobeAppDef - ApmParaprobeNewBC - .. _IntroductionApm: @@ -19,8 +17,7 @@ Introduction ############ Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, -steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, -i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. +steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. .. _ApmAppDef: @@ -29,7 +26,9 @@ Application Definition ###################### :ref:`NXapm`: - A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. + A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. The structure of the schema has been designed to also document a simulation of an atom probe + experiment. Having a combined schema for the measurement and the simulation is beneficial to document that + there are many similarities between the measurement and a computer simulation of it. .. _ApmBC: @@ -43,15 +42,15 @@ The following base classes are proposed to support modularizing the storage of p A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities for storing and loading specimens. - :ref:`NXcoordinate_system_set` - A base class to describe different coordinate systems used and/or to be harmonized + :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`: + Base classes to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. :ref:`NXion`: A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. For the usage in atom probe research the maximum number of atoms supported building a molecular ion is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with - which all possible isotopes (stable, radioactive, or synthetically generated ones) can be described. + which all possible nuclides (stable, radioactive, or synthetically generated ones) can be described. :ref:`NXfabrication`: A base class to bundle manufacturer/technology-partner-specific details about @@ -84,17 +83,53 @@ Microscopy experiments, not only taking into account those performed on commerci data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named instances of the :ref:`NXprocess` base class. -Data processing steps are essential to transform measurements into knowledge. Therefore, these steps -should be documented to enable reproducible research, ideally numerically, and learn how pieces of information are connected. -In what follows, an example is presented how an open-source community software can be modified to use descriptions -of these computational steps. +Several base classes were defined to document processing of atom probe data with established algorithms: + + :ref:`NXapm_hit_finding`: + A base class to describe hit finding algorithm. + + :ref:`NXapm_volt_and_bowl`: + A base class to describe the voltage-and-bowl correction. + + :ref:`NXapm_charge_state_analysis`: + A base class to document the resolving of the charge_state. + + :ref:`NXapm_reconstruction`: + A base class to document the tomographic reconstruction algorithm. + + :ref:`NXapm_ranging`: + A base class to document the ranging process. + + :ref:`NXapm_msr`, :ref:`NXapm_sim`: + Respective base classes that serve as templates to compose the :ref:`NXapm` application definition from. + +These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented +to enable reproducible research, if possible even numerical reproducibility of the results, +and learn how pieces of information are connected. In what follows, an example is presented how an +open-source community software can be modified to use descriptions of these computational steps. + +A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe +data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: + + :ref:`NXspatial_filter`: + A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. + This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, + and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. + The primitives are used for defining the shape and extent of a region of interest (ROI). + + :ref:`NXsubsampling_filter`: + A base class for a filter that can also be used for specifying how entries + like ions can be filtered via sub-sampling. + + :ref:`NXmatch_filter`: + A base class for a filter that can also be used for specifying how entries + like ions can be filtered based on their type or other descriptors like hit multiplicity. The respective research software here is the `paraprobe-toolbox `_ The software is developed by `M. Kühbach et al. `_. For atom probe research the proposal can also serve as a blue print how computational steps of other software tool including commercial ones could be developed further to benefit from NeXus. - .. _IntroductionApmParaprobe: apmtools @@ -167,7 +202,17 @@ combined to generate new results. We are convinced that defining, documenting, using, and sharing application definitions is useful and future-proof strategy for software development and data analyses as it enables -automated provenance tracking which happens silently in the background +automated provenance tracking which happens silently in the background. + +Base classes have been defined to group common pieces of information for each tool of the +toolbox. These base classes are: + + :ref:`NXapm_paraprobe_tool_config`: + Common parts of configuration settings useful for several tools of the paraprobe-toolbox. + + :ref:`NXapm_paraprobe_tool_results`: + Common parts of results useful for several tools of the paraprobe-toolbox. + .. _ApmParaprobeAppDef: @@ -178,23 +223,17 @@ NXapm_paraprobe application definitions are in fact pairs of application definit One for the configuration (input) side and one for the results (output) side. For each tool one such pair is proposed: - :ref:`NXapm_paraprobe_config_transcoder`: - Configuration of paraprobe-transcoder - Load POS, ePOS, APSuite APT, RRNG, RNG, and NXapm HDF5 files. - - :ref:`NXapm_paraprobe_results_transcoder`: - Results of paraprobe-transcoder + :ref:`NXapm_paraprobe_transcoder_config`, :ref:`NXapm_paraprobe_transcoder_results`: + Configuration and the results respectively of the paraprobe-transcoder tool. + Load POS, ePOS, APSuite APT, RRNG, RNG, and NeXus NXapm files. Store reconstructed positions, ions, and charge states. - - :ref:`NXapm_paraprobe_config_ranger`: - Configuration of paraprobe-ranger + :ref:`NXapm_paraprobe_ranger_config`, :ref:`NXapm_paraprobe_ranger_results`: + Configuration and results respectively of the paraprobe-ranger tool. Apply ranging definitions and explore possible molecular ions. + Store applied ranging definitions and combinatorial analyses of possible iontypes. - :ref:`NXapm_paraprobe_results_ranger`: - Results of paraprobe-ranger - Store applied ranging definitions and combinatorial analyses of all possible iontypes. - +The definitions of the following tools remain to become refactored like those for the above-mentioned tools: :ref:`NXapm_paraprobe_config_selector`: Configuration of paraprobe-selector @@ -272,41 +311,3 @@ tool one such pair is proposed: :ref:`NXapm_paraprobe_results_clusterer`: Results of paraprobe-clusterer Store results of cluster analyses. - -.. _ApmParaprobeNewBC: - -Base Classes -############ - -We envision that the above-mentioned definitions can be useful not only to take -inspiration for other software tools in the field of atom probe but also to support -a discussion towards a stronger standardization of the vocabulary used. This is an -ongoing discussion in the field emission community `IFES `_. -We are happy for taking comments and suggestions. The use of base classes for atom probe -is motivated by the observation that the majority of data analyses in atom probe -use a common set of operations and conditions on the input data: - - :ref:`NXapm_input_reconstruction`: - A base class documenting from where reconstructed ion positions are imported. - - :ref:`NXapm_input_ranging`: - A base class documenting from where ranging definitions are imported. - The design of the ranging definitions is, thanks to :ref:`NXion`, so - general that all possible nuclids can be considered. - -A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe -data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: - - :ref:`NXspatial_filter`: - A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. - This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, - and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. - The primitives are used for defining the shape and extent of a region of interest (ROI). - - :ref:`NXsubsampling_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered via sub-sampling. - - :ref:`NXmatch_filter`: - A base class for a filter that can also be used for specifying how entries - like ions can be filtered based on their type or other descriptors like hit multiplicity. From 5738ab9ffc13cc23b78a2004a26557ce103fee9a Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 26 Jan 2024 18:13:27 +0100 Subject: [PATCH 026/136] Refactored surfacer to use APMv2 # Conflicts: # contributed_definitions/NXapm_paraprobe_ranger_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_selector_config.nxdl.xml # contributed_definitions/nyaml/NXapm_paraprobe_ranger_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_selector_config.yaml --- .../NXapm_paraprobe_surfacer_config.nxdl.xml | 229 +++++++++++++++ .../NXapm_paraprobe_surfacer_results.nxdl.xml | 270 ++++++++++++++++++ .../NXapm_paraprobe_surfacer_config.yaml | 167 +++++++++++ .../NXapm_paraprobe_surfacer_results.yaml | 180 ++++++++++++ .../contributed_definitions/apm-structure.rst | 10 +- .../icme-structure.rst | 13 +- 6 files changed, 853 insertions(+), 16 deletions(-) create mode 100644 contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml create mode 100644 contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml create mode 100644 contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml create mode 100644 contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml diff --git a/contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml b/contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml new file mode 100644 index 000000000..a31d15d6e --- /dev/null +++ b/contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml @@ -0,0 +1,229 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Number of alpha values (and offset values) to probe. + + + + + How many different match values does the filter specify. + + + + + Application definition for a configuration file of the paraprobe-surfacer tool. + + This tool is part of the paraprobe-toolbox. Inspect :ref:`NXapm_paraprobe_tool_config` for details. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specifies the method that is used to preprocess the point cloud + prior to the alpha-shape computation. + + The option *default* specifies that no such filtering is applied. + The option *kuehbach* specifies that a Hoshen-Kopelman + percolation analysis is used to identify points that lie closer + to the edge of the dataset. Details about the methods are reported + in `M. Kühbach et al. <https://doi.org/10.1038/s41524-020-00486-1>`_. + + + + + + + + + When using the kuehbach preprocessing, this is the width of the + kernel for identifying which ions are in voxels close to the + edge of the point cloud. + + + + + + Specifies which method to use to define the alpha value. + + The value *convex_hull_naive* is the default. The setting instructs + the tool to use a fast specialized algorithm for computing only + the convex hull. The resulting triangles can be skinny. + + The value *convex_hull_refine* instructs to tool to refine the + quality of the mesh resulting from *convex_hull_naive* + via triangle flipping and splitting. + + The value *smallest_solid* instructs the CGAL library to choose a + value which realizes an alpha-shape that is the smallest solid. + + The value *cgal_optimal* instructs the CGAL library to choose a + value which the library considers as to be an optimal value. + Details are defined in the respective section of the CGAL library + on 3D alpha shapes. + + The value *set_of_values* instructs the tool to compute a list + collection of alpha-shapes for the specified alpha-values. + + The value *set_of_alpha_wrappings* instructs the tool to generate + a set of so-called alpha wrappings. These are similar to alpha-shapes + but provide additional guarantees (such as watertightness and + proximity constraints) on the resulting wrapping. + + + + + + + + + + + + + Array of alpha values to use when alpha_value_choice is + set_of_values or when alpha_value_choice is set_of_alpha_wrappings. + + + + + + + + Array of offset values to use when alpha_value_choice is set_of_alpha_wrappings. + The array of alpha_values and offset_values define a sequence of (alpha and offset value). + + + + + + + + Specifies if the tool should compute the set of exterior triangle facets + for each alpha complex (for convex hull, alpha shapes, and wrappings). + + + + + Specifies if the tool should check if the alpha complex of + exterior triangular facets is a closed polyhedron. + + + + + Specifies if the tool should compute all interior tetrahedra + of the alpha complex (currently only for alpha shapes). + + + + + + + + + + + + + + + + diff --git a/contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml b/contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml new file mode 100644 index 000000000..499628aa3 --- /dev/null +++ b/contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml @@ -0,0 +1,270 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + The total number of ions in the reconstruction. + + + + + The number of vertices of the alpha complex. + + + + + The number of faces of the alpha complex. + + + + + The total number of XDMF values to represent all faces of triangles via XDMF. + + + + + The total number of XDMF values to represent all faces of tetrahedra via XDMF. + + + + + Application definition for results files of the paraprobe-surfacer tool. + + This tool is part of the paraprobe-toolbox. Inspect the base class :ref:`NXapm_paraprobe_tool_results`. + The purpose and need of the paraprobe-surfacer tool is the generation of meshed + representation of the surface of the the reconstructed volume (or a portion) of it + using different algorithms from the computational geometry community. + + + + + + + + + + + + Paraprobe-surfacer can be used to load a ROI that is the entire or a + sub-set of the ion point cloud. In the point_cloud_wrapping process + the tool computes a triangulated surface mesh which encloses the + ROI/point cloud. This mesh can be seen as a model for the edge of + the dataset. + + Different algorithms can be used with paraprobe-surfacer to create + this mesh such as convex hulls, alpha-shapes as their generalization, + or alpha wrappings. + + Ideally, the resulting mesh should be a watertight polyhedron. + This polyhedron is not necessarily convex. For some algorithms there + is no guarantee that the resulting mesh yields a watertight mesh. + + + + + + + + + + + + + + + + + + + + A bitmask which identifies exactly all those ions whose positions + were considered when defining the filtered point set from which + that alpha_complex instance was computed. + + This window can be different to the window of the *point_set_wrapping* + parent group because irrelevant ions might have been filtered out in addition + to the window defined in *point_set_wrapping* to reduce e.g. computational + costs of the alpha complex computation. + + + + + Number of ions covered by the mask. + + + + + Number of bits assumed matching on a default datatype. + + + + + The bitfield of the mask. See :ref:`NXcs_filter_boolean_mask` for + how this bitfield is to be interpreted. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The set of triangles in the coordinate system paraprobe + which discretizes the exterior surface of the alpha complex. + + + + + + + + + + + + + + + + + + + + + + + A list of as many tuples of XDMF topology key, XDMF number + of vertices and a triple of vertex indices specifying each + triangle. The total number of entries is n_f_tri * (1+1+3). + + + + + + + + Do the triangles define a triangulated surface mesh that is watertight? + + + + + The volume which the triangulated surface mesh + encloses if that mesh is watertight. + + + + + + + The set of tetrahedra which represent the interior volume + of the complex if that is a closed two-manifold. + + + + + The accumulated volume of all interior tetrahedra. + + + + + + + + + + + + + + + + A list of as many tuples of XDMF topology key, XDMF number + of vertices and a triple of vertex indices specifying each + triangle. The total number of entries is n_f_tet * (1+1+4). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml b/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml new file mode 100644 index 000000000..b72b66e52 --- /dev/null +++ b/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml @@ -0,0 +1,167 @@ +category: application +doc: | + Application definition for a configuration file of the paraprobe-surfacer tool. + + This tool is part of the paraprobe-toolbox. Inspect :ref:`NXapm_paraprobe_tool_config` for details. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. + n_alpha_values: | + Number of alpha values (and offset values) to probe. + n_values: | + How many different match values does the filter specify. +type: group +NXapm_paraprobe_surfacer_config(NXobject): + (NXentry): + exists: [min, 1, max, 1] + definition(NX_CHAR): + \@version(NX_CHAR): + enumeration: [NXapm_paraprobe_surfacer_config] + surface_meshing(NXapm_paraprobe_tool_config): + exists: [min, 1, max, 1] + (NXidentifier): + exists: optional + analysis_identifier(NX_UINT): + exists: recommended + reconstruction(NXserialized): + type(NX_CHAR): + path(NX_CHAR): + checksum(NX_CHAR): + algorithm(NX_CHAR): + position(NX_CHAR): + mass_to_charge(NX_CHAR): + ranging(NXserialized): + type(NX_CHAR): + path(NX_CHAR): + checksum(NX_CHAR): + algorithm(NX_CHAR): + ranging_definitions(NX_CHAR): + # filter that are here tool-specific parameter + spatial_filter(NXspatial_filter): + windowing_method(NX_CHAR): + hexahedron_set(NXcg_hexahedron_set): + exists: optional + dimensionality(NX_POSINT): + cardinality(NX_POSINT): + identifier_offset(NX_INT): + hexahedra(NXcg_face_list_data_structure): + vertices(NX_UINT): + cylinder_set(NXcg_cylinder_set): + exists: optional + dimensionality(NX_POSINT): + cardinality(NX_POSINT): + identifier_offset(NX_INT): + center(NX_NUMBER): + height(NX_NUMBER): + radii(NX_NUMBER): + ellipsoid_set(NXcg_ellipsoid_set): + exists: optional + dimensionality(NX_POSINT): + cardinality(NX_POSINT): + identifier_offset(NX_INT): + center(NX_NUMBER): + half_axes_radii(NX_NUMBER): + orientation(NX_NUMBER): + polyhedron_set(NXcg_polyhedron_set): + exists: optional + # TODO + bitmask(NXcs_filter_boolean_mask): + exists: optional + number_of_objects(NX_UINT): + bitdepth(NX_UINT): + mask(NX_UINT): + # leave open if scalar or matrix + # dim: (i,) + identifier(NX_UINT): + evaporation_id_filter(NXsubsampling_filter): + exists: optional + min_incr_max(NX_INT): + iontype_filter(NXmatch_filter): + exists: optional + method(NX_CHAR): + match(NX_NUMBER): + hit_multiplicity_filter(NXmatch_filter): + # config + preprocessing(NXprocess): + method(NX_CHAR): + doc: | + Specifies the method that is used to preprocess the point cloud + prior to the alpha-shape computation. + + The option *default* specifies that no such filtering is applied. + The option *kuehbach* specifies that a Hoshen-Kopelman + percolation analysis is used to identify points that lie closer + to the edge of the dataset. Details about the methods are reported + in `M. Kühbach et al. `_. + enumeration: [default, kuehbach] + kernel_width(NX_UINT): + doc: | + When using the kuehbach preprocessing, this is the width of the + kernel for identifying which ions are in voxels close to the + edge of the point cloud. + unit: NX_UNITLESS + alpha_value_choice(NX_CHAR): + doc: | + Specifies which method to use to define the alpha value. + + The value *convex_hull_naive* is the default. The setting instructs + the tool to use a fast specialized algorithm for computing only + the convex hull. The resulting triangles can be skinny. + + The value *convex_hull_refine* instructs to tool to refine the + quality of the mesh resulting from *convex_hull_naive* + via triangle flipping and splitting. + + The value *smallest_solid* instructs the CGAL library to choose a + value which realizes an alpha-shape that is the smallest solid. + + The value *cgal_optimal* instructs the CGAL library to choose a + value which the library considers as to be an optimal value. + Details are defined in the respective section of the CGAL library + on 3D alpha shapes. + + The value *set_of_values* instructs the tool to compute a list + collection of alpha-shapes for the specified alpha-values. + + The value *set_of_alpha_wrappings* instructs the tool to generate + a set of so-called alpha wrappings. These are similar to alpha-shapes + but provide additional guarantees (such as watertightness and + proximity constraints) on the resulting wrapping. + enumeration: [convex_hull_naive, convex_hull_refine, smallest_solid, cgal_optimal, set_of_values, set_of_alpha_wrappings] + alpha_values(NX_FLOAT): + doc: | + Array of alpha values to use when alpha_value_choice is + set_of_values or when alpha_value_choice is set_of_alpha_wrappings. + unit: NX_ANY + # \@units: nm^2 + dim: (n_alpha_values,) + offset_values(NX_FLOAT): + doc: | + Array of offset values to use when alpha_value_choice is set_of_alpha_wrappings. + The array of alpha_values and offset_values define a sequence of (alpha and offset value). + unit: NX_LENGTH + # \@units: nm + dim: (n_alpha_values,) + has_exterior_facets(NX_BOOLEAN): + doc: | + Specifies if the tool should compute the set of exterior triangle facets + for each alpha complex (for convex hull, alpha shapes, and wrappings). + has_closure(NX_BOOLEAN): + doc: | + Specifies if the tool should check if the alpha complex of + exterior triangular facets is a closed polyhedron. + has_interior_tetrahedra(NX_BOOLEAN): + doc: | + Specifies if the tool should compute all interior tetrahedra + of the alpha complex (currently only for alpha shapes). + # NEW ISSUE: has_facet_appearance(NX_BOOLEAN): + # profiling + (NXprogram): + exists: [min, 1, max, infty] + program(NX_CHAR): + \@version(NX_CHAR): + profiling(NXcs_profiling): + exists: recommended + start_time(NX_DATE_TIME): + end_time(NX_DATE_TIME): + current_working_directory(NX_CHAR): \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml b/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml new file mode 100644 index 000000000..cc4e0c98a --- /dev/null +++ b/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml @@ -0,0 +1,180 @@ +category: application +doc: | + Application definition for results files of the paraprobe-surfacer tool. + + This tool is part of the paraprobe-toolbox. Inspect the base class :ref:`NXapm_paraprobe_tool_results`. + The purpose and need of the paraprobe-surfacer tool is the generation of meshed + representation of the surface of the the reconstructed volume (or a portion) of it + using different algorithms from the computational geometry community. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. + n_ions: | + The total number of ions in the reconstruction. + n_v_tri: | + The number of vertices of the alpha complex. + n_f_tri: | + The number of faces of the alpha complex. + n_f_tri_xdmf: | + The total number of XDMF values to represent all faces of triangles via XDMF. + n_f_tet_xdmf: | + The total number of XDMF values to represent all faces of tetrahedra via XDMF. +type: group +NXapm_paraprobe_surfacer_results(NXobject): + (NXentry): + exists: [min, 1, max, 1] + definition(NX_CHAR): + \@version(NX_CHAR): + enumeration: [NXapm_paraprobe_surfacer_results] + # tasks + point_set_wrapping(NXapm_paraprobe_tool_results): + doc: | + Paraprobe-surfacer can be used to load a ROI that is the entire or a + sub-set of the ion point cloud. In the point_cloud_wrapping process + the tool computes a triangulated surface mesh which encloses the + ROI/point cloud. This mesh can be seen as a model for the edge of + the dataset. + + Different algorithms can be used with paraprobe-surfacer to create + this mesh such as convex hulls, alpha-shapes as their generalization, + or alpha wrappings. + + Ideally, the resulting mesh should be a watertight polyhedron. + This polyhedron is not necessarily convex. For some algorithms there + is no guarantee that the resulting mesh yields a watertight mesh. + # config + analysis_identifier(NX_UINT): + config(NXserialized): + type(NX_CHAR): + path(NX_CHAR): + checksum(NX_CHAR): + algorithm(NX_CHAR): + window(NXcs_filter_boolean_mask): + number_of_ions(NX_UINT): + bitdepth(NX_UINT): + mask(NX_UINT): + # results + alpha_complexID(NXcg_alpha_complex): + exists: [min, 0, max, infty] + # (NXcg_grid): currently we do not store the underlying grid + # for eventually performed preprocessing + window(NXcs_filter_boolean_mask): + doc: | + A bitmask which identifies exactly all those ions whose positions + were considered when defining the filtered point set from which + that alpha_complex instance was computed. + + This window can be different to the window of the *point_set_wrapping* + parent group because irrelevant ions might have been filtered out in addition + to the window defined in *point_set_wrapping* to reduce e.g. computational + costs of the alpha complex computation. + # filtered in addition to the ROI or again the entire dataset + number_of_ions(NX_UINT): + doc: | + Number of ions covered by the mask. + unit: NX_UNITLESS + bitdepth(NX_UINT): + doc: | + Number of bits assumed matching on a default datatype. + unit: NX_UNITLESS + mask(NX_UINT): + doc: | + The bitfield of the mask. See :ref:`NXcs_filter_boolean_mask` for + how this bitfield is to be interpreted. + unit: NX_UNITLESS + dim: (n_ions,) + dimensionality(NX_UINT): + enumeration: [2, 3] + unit: NX_UNITLESS + type(NX_CHAR): + enumeration: [convex_hull, alpha_shape, alpha_wrapping, other, undefined] + mode(NX_CHAR): + enumeration: [general, regularized] + alpha(NX_NUMBER): + unit: NX_ANY + offset(NX_NUMBER): + exists: optional + unit: NX_LENGTH + triangle_set(NXcg_triangle_set): + exists: optional + doc: | + The set of triangles in the coordinate system paraprobe + which discretizes the exterior surface of the alpha complex. + identifier_offset(NX_INT): + triangles(NXcg_face_list_data_structure): + dimensionality(NX_POSINT): + number_of_vertices(NX_POSINT): + number_of_faces(NX_POSINT): + vertex_identifier_offset(NX_INT): + face_identifier_offset(NX_INT): + vertices(NX_FLOAT): + unit: NX_LENGTH + dim: (n_v_tri, 3) + faces(NX_UINT): + unit: NX_UNITLESS + dim: (n_f_tri, 3) + xdmf_topology(NX_UINT): + doc: | + A list of as many tuples of XDMF topology key, XDMF number + of vertices and a triple of vertex indices specifying each + triangle. The total number of entries is n_f_tri * (1+1+3). + unit: NX_UNITLESS + dim: (n_f_tri_xdmf,) + is_watertight(NX_BOOLEAN): + exists: optional + doc: | + Do the triangles define a triangulated surface mesh that is watertight? + volume(NX_FLOAT): + exists: optional + doc: | + The volume which the triangulated surface mesh + encloses if that mesh is watertight. + unit: NX_VOLUME + + interior_tetrahedra(NXcg_tetrahedron_set): + exists: optional + doc: | + The set of tetrahedra which represent the interior volume + of the complex if that is a closed two-manifold. + identifier_offset(NX_INT): + unit: NX_UNITLESS + volume(NX_FLOAT): + exists: optional + doc: | + The accumulated volume of all interior tetrahedra. + unit: NX_VOLUME + tetrahedra(NXcg_face_list_data_structure): + exists: optional + number_of_vertices(NX_POSINT): + number_of_faces(NX_POSINT): + vertex_identifier_offset(NX_INT): + face_identifier_offset(NX_INT): + vertices(NX_FLOAT): + unit: NX_LENGTH + dim: (n_v_tet, 3) + xdmf_topology(NX_UINT): + doc: | + A list of as many tuples of XDMF topology key, XDMF number + of vertices and a triple of vertex indices specifying each + triangle. The total number of entries is n_f_tet * (1+1+4). + unit: NX_UNITLESS + dim: (n_f_tet_xdmf,) + # TRIANGLE_SET_WRAPPING(NXprocess): + # For the future as we may wish to wrap primitives other like triangles or polylines. + # global + (NXuser): + exists: [min, 0, max, infty] + name(NX_CHAR): + (NXcoordinate_system_set): + paraprobe(NXcoordinate_system): + type(NX_CHAR): + handedness(NX_CHAR): + x(NX_NUMBER): + unit: NX_LENGTH + dim: (3,) + y(NX_NUMBER): + unit: NX_LENGTH + dim: (3,) + z(NX_NUMBER): + unit: NX_LENGTH + dim: (3,) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index aec8883be..580258ccd 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -233,16 +233,12 @@ tool one such pair is proposed: Apply ranging definitions and explore possible molecular ions. Store applied ranging definitions and combinatorial analyses of possible iontypes. -The definitions of the following tools remain to become refactored like those for the above-mentioned tools: - - :ref:`NXapm_paraprobe_config_selector`: - Configuration of paraprobe-selector + :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: + Configuration and results respectively of paraprobe-selector tool. Defining complex spatial regions-of-interest to filter reconstructed datasets. - - :ref:`NXapm_paraprobe_results_selector`: - Results of paraprobe-selector Store which points are inside or on the boundary of complex spatial regions-of-interest. +The definitions of the following tools remain to become refactored like those for the above-mentioned tools: :ref:`NXapm_paraprobe_config_surfacer`: Configuration of paraprobe-surfacer diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index 07aa6ee4e..8c067978d 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -29,12 +29,7 @@ concepts which are equally modellable with NeXus: :ref:`NXms_recon`: A base class for documenting results of reconstructed microstructures. - :ref:`NXms_score_config`: - A specific example of how :ref:`NXapm_paraprobe_config_ranger` can be - specialized for documenting the configuration of a computer simulation - with the static recrystallization cellular automata model SCORE. - - :ref:`NXms_score_results`: - A specific example of how :ref:`NXms` can be specialized for documenting - results of computer simulations with the static recrystallization - cellular automata model SCORE. + :ref:`NXms_score_config`, :ref:`NXms_score_results`: + A specific example of an application definition for documenting the + configuration and results respectively of a computer simulation with + the static recrystallization cellular automata model SCORE. From e51cdbcb407f8231888a339b8a68c5b01c052e9f Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Sun, 28 Jan 2024 17:44:21 +0100 Subject: [PATCH 027/136] Fixes to complete distancer and tessellator APMv2 refactoring # Conflicts: # contributed_definitions/NXapm_paraprobe_distancer_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_tessellator_config.nxdl.xml # contributed_definitions/nyaml/NXapm_paraprobe_distancer_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_tessellator_config.yaml --- .../contributed_definitions/apm-structure.rst | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index 580258ccd..4cae11b02 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -234,38 +234,24 @@ tool one such pair is proposed: Store applied ranging definitions and combinatorial analyses of possible iontypes. :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: - Configuration and results respectively of paraprobe-selector tool. + Configuration and results respectively of the paraprobe-selector tool. Defining complex spatial regions-of-interest to filter reconstructed datasets. Store which points are inside or on the boundary of complex spatial regions-of-interest. -The definitions of the following tools remain to become refactored like those for the above-mentioned tools: - - :ref:`NXapm_paraprobe_config_surfacer`: - Configuration of paraprobe-surfacer - Create a model for the edge of a point cloud via convex hulls, alpha shapes. - - :ref:`NXapm_paraprobe_results_surfacer`: - Results of paraprobe-surfacer + :ref:`NXapm_paraprobe_surfacer_config`, :ref:`NXapm_paraprobe_surfacer_results`: + Configuration and results respectively of the paraprobe-surfacer tool. + Create a model for the edge of a point cloud via convex hulls, alpha shapes, or alpha-wrappings. Store triangulated surface meshes of models for the edge of a dataset. + :ref:`NXapm_paraprobe_distancer_config`, :ref:`NXapm_paraprobe_distancer_results`: + Configuration and results respectively of the paraprobe-distancer tool. + Compute and store analytical distances between ions to a set of triangles. - :ref:`NXapm_paraprobe_config_distancer`: - Configuration of paraprobe-distancer - Compute analytical distances between ions to a set of triangles. - - :ref:`NXapm_paraprobe_results_distancer`: - Results of paraprobe-distancer - Store analytical distances between ions to a set of triangles. - - - :ref:`NXapm_paraprobe_config_tessellator`: - Configuration of paraprobe-tessellator - Compute Voronoi cells for if desired all ions in a dataset. - - :ref:`NXapm_paraprobe_results_tessellator`: - Results of paraprobe-tessellator - Store volume of all Voronoi cells about each ion in the dataset. + :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: + Configuration and results respectively of the of paraprobe-tessellator tool. + Compute and store Voronoi cells and properties of these for all ions in a dataset. +The definitions of the following tools remain to become refactored like those for the above-mentioned tools: :ref:`NXapm_paraprobe_config_nanochem`: Configuration of paraprobe-nanochem @@ -277,7 +263,6 @@ The definitions of the following tools remain to become refactored like those fo store all extracted triangulated surface meshes of found microstructural features, store composition profiles and corresponding geometric primitives (ROIs). - :ref:`NXapm_paraprobe_config_intersector`: Configuration of paraprobe-intersector Assess intersections and proximity of 3D triangulated surface meshes in From e16983cf90e3ee37856bb7ce4096f572d9412083 Mon Sep 17 00:00:00 2001 From: domna Date: Mon, 29 Jan 2024 12:32:29 +0100 Subject: [PATCH 028/136] Adds NXmpes_arpes to overview page # Conflicts: # manual/source/mpes-structure.rst --- manual/source/mpes-structure.rst | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 manual/source/mpes-structure.rst diff --git a/manual/source/mpes-structure.rst b/manual/source/mpes-structure.rst deleted file mode 100644 index 73a1768c2..000000000 --- a/manual/source/mpes-structure.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _Mpes-Structure-Fairmat: - -======================================= -Photoemission & core-level spectroscopy -======================================= - -The NXmpes application definition is designed to describe data and metadata obtained from -various multidimensional photoemission spectroscopy (MPES) techniques. -This definition is very flexible and requires just a reasonable amount of -metadata to make the stored data interoperable and reproducible. -The only requirement for the actual data is the existence of an energy axis. - -The experimental techniques covered by this application definition are primarily limited -to photon-in photoelectron-out methods. If you are searching for related techniques, -there is a good chance you will find valuable information here. - -Example techniques covered by this application definition include: - -- X-ray/UV photoelectron spectroscopy (XPS/UPS) -- Angle-resolved photoemission spectroscopy (ARPES) -- Two-photon photoemission (2PPE) -- Photoemission electron microscopy (PEEM) - -Additionally, we offer descriptors for specialized applications, -such as spin- and time-resolution, near-ambient pressure conditions, dichroism, and more. - -Here's a list of application definitions related to photoemission spectroscopy: - - :ref:`NXmpes`: - A universal application definition with minimal metadata requirements for describing all photoemission experiments. From 91c1ead76e3f957927dbb0d90541c1b3618373e8 Mon Sep 17 00:00:00 2001 From: Florian Dobener Date: Tue, 30 Jan 2024 11:23:58 +0100 Subject: [PATCH 029/136] Fix URLs and formats with black>24 (#152) * Updates URLs * Update ci/cd to deploy on tags * Updates url and reverst ci/cd changes * Reformat according to black>24 * Update black version in requirements # Conflicts: # dev_tools/tests/test_nxdl_utils.py # manual/source/conf.py --- dev_tools/globals/urls.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev_tools/globals/urls.py b/dev_tools/globals/urls.py index 729b7d102..2929070cc 100644 --- a/dev_tools/globals/urls.py +++ b/dev_tools/globals/urls.py @@ -1,2 +1,2 @@ -REPO_URL = "https://github.com/nexusformat/definitions/blob/main" +REPO_URL = "https://github.com/FAIRmat-NFDI/nexus_definitions/tree/fairmat" MANUAL_URL = "https://manual.nexusformat.org" diff --git a/requirements.txt b/requirements.txt index ba1f751d3..74c736824 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,6 @@ sphinx-toolbox pytest # Code style and auto-formatting -black>=22.3 +black>=24.1.1 flake8>=4 isort>=5.10 From 4f086f3384d2017223d3ba0154b25ac3c8a3b610 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 16 Feb 2024 01:20:59 +0100 Subject: [PATCH 030/136] Updated apm-specific landing page # Conflicts: # contributed_definitions/NXapm_paraprobe_nanochem_config.nxdl.xml # contributed_definitions/nyaml/NXapm_paraprobe_nanochem_config.yaml --- .../contributed_definitions/apm-structure.rst | 54 ++++++------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index 4cae11b02..be56ed064 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -248,47 +248,23 @@ tool one such pair is proposed: Compute and store analytical distances between ions to a set of triangles. :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: - Configuration and results respectively of the of paraprobe-tessellator tool. + Configuration and results respectively of the paraprobe-tessellator tool. Compute and store Voronoi cells and properties of these for all ions in a dataset. -The definitions of the following tools remain to become refactored like those for the above-mentioned tools: + :ref:`NXapm_paraprobe_spatstat_config`, :ref:`NXapm_paraprobe_spatstat_results`: + Configuration and results respectively of the paraprobe-spatstat tool. + Compute spatial statistics on the entire or selected regions of the reconstructed dataset. - :ref:`NXapm_paraprobe_config_nanochem`: - Configuration of paraprobe-nanochem - Compute delocalization, iso-surfaces, analyze 3D objects, and composition profiles. + :ref:`NXapm_paraprobe_clusterer_config`, :ref:`NXapm_paraprobe_clusterer_results`: + Configuration and results resepctively of the paraprobe-clusterer tool. + Compute cluster analyses with established machine learning algorithms using CPU or GPUs. - :ref:`NXapm_paraprobe_results_nanochem`: - Results of paraprobe-nanochem - Store all results of delocalization, isosurface, and interface detection algorithms, - store all extracted triangulated surface meshes of found microstructural features, - store composition profiles and corresponding geometric primitives (ROIs). + :ref:`NXapm_paraprobe_nanochem_config`, :ref:`NXapm_paraprobe_nanochem_results`: + Configuration and results resepctively of the paraprobe-nanochem tool. + Compute delocalization, iso-surfaces, analyze 3D objects, composition profiles, and mesh interfaces. - :ref:`NXapm_paraprobe_config_intersector`: - Configuration of paraprobe-intersector - Assess intersections and proximity of 3D triangulated surface meshes in - continuum space to study the effect the parameterization of surface - extraction algorithms on the resulting shape, spatial arrangement, - and colocation of 3D objects via graph-based techniques. - - :ref:`NXapm_paraprobe_results_intersector`: - Results of paraprobe-intersector - Store graph of microstructural features and relations/link identified between them. - - - :ref:`NXapm_paraprobe_config_spatstat`: - Configuration of paraprobe-spatstat - Spatial statistics on the entire or selected regions of the reconstructed dataset. - - :ref:`NXapm_paraprobe_results_spatstat`: - Results of paraprobe-spatstat - Store spatial correlation functions. - - - :ref:`NXapm_paraprobe_config_clusterer`: - Configuration of paraprobe-clusterer - Import cluster analysis results of IVAS/APSuite and perform clustering - analyses in a Python ecosystem. - - :ref:`NXapm_paraprobe_results_clusterer`: - Results of paraprobe-clusterer - Store results of cluster analyses. + :ref:`NXapm_paraprobe_intersector_config`, :ref:`NXapm_paraprobe_intersector_results`: + Configuration and results resepctively of the paraprobe-intersector tool. + Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes + in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, + spatial arrangement, and colocation of 3D objects via graph-based techniques. From 4bd17ecd55a60bba8fa4e44ec8f32389481d7120 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 16 Feb 2024 01:34:34 +0100 Subject: [PATCH 031/136] Minor edits and fixes apm-structure # Conflicts: # contributed_definitions/NXapm_paraprobe_nanochem_config.nxdl.xml # contributed_definitions/nyaml/NXapm_paraprobe_intersector_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_nanochem_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_nanochem_results.yaml --- .../classes/contributed_definitions/apm-structure.rst | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index be56ed064..a36a94ad7 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -205,14 +205,11 @@ is useful and future-proof strategy for software development and data analyses a automated provenance tracking which happens silently in the background. Base classes have been defined to group common pieces of information for each tool of the -toolbox. These base classes are: - - :ref:`NXapm_paraprobe_tool_config`: - Common parts of configuration settings useful for several tools of the paraprobe-toolbox. - - :ref:`NXapm_paraprobe_tool_results`: - Common parts of results useful for several tools of the paraprobe-toolbox. +toolbox. For each tool we define a pair of base classes. One for the configuration (input) side +and one for the results (output) side: + :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`: + Common parts of configuration settings and results respectively useful for several tools of the paraprobe-toolbox. .. _ApmParaprobeAppDef: From 707a227f9ae475493426091c8b787423a73f912f Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Fri, 16 Feb 2024 23:37:49 +0100 Subject: [PATCH 032/136] Refactored NXapm_paraprobe_intersector_results, fixed formatting issues with math envs, removed obsolete FAIRmat Area B numbering schemes # Conflicts: # contributed_definitions/NXapm_paraprobe_intersector_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_nanochem_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_results_intersector.nxdl.xml # contributed_definitions/nyaml/NXapm_paraprobe_intersector_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_intersector_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_nanochem_results.yaml # manual/source/mpes-structure.rst --- manual/source/apm-structure.rst | 6 +++--- manual/source/ellipsometry-structure.rst | 6 +++--- manual/source/em-structure.rst | 6 +++--- manual/source/examples/index.rst | 6 +++--- manual/source/transport-structure.rst | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manual/source/apm-structure.rst b/manual/source/apm-structure.rst index 84ff91a11..581e2ec5b 100644 --- a/manual/source/apm-structure.rst +++ b/manual/source/apm-structure.rst @@ -1,8 +1,8 @@ .. _Apm-Structure-Fairmat: -========================= -B5: Atom-probe tomography -========================= +===================== +Atom-probe tomography +===================== Atom probe tomography and related field-ion microscopy, aka atom probe microscopy (techniques) cover metrology methods with an origin in the materials science and condensed-matter physics communities. With its maturation and commercialization in the last two decades atom probe is increasingly being used for characterization of bio materials and fundamental science of field evaporation physics. diff --git a/manual/source/ellipsometry-structure.rst b/manual/source/ellipsometry-structure.rst index 223643d68..255c3c582 100644 --- a/manual/source/ellipsometry-structure.rst +++ b/manual/source/ellipsometry-structure.rst @@ -1,8 +1,8 @@ .. _Ellipsometry-Structure-Fairmat: -======================== -B4: Optical spectroscopy -======================== +==================== +Optical spectroscopy +==================== .. index:: Ellipsometry1 diff --git a/manual/source/em-structure.rst b/manual/source/em-structure.rst index ae9fed2f7..148e513aa 100644 --- a/manual/source/em-structure.rst +++ b/manual/source/em-structure.rst @@ -1,8 +1,8 @@ .. _Em-Structure-Fairmat: -======================= -B1: Electron microscopy -======================= +=================== +Electron microscopy +=================== Electron microscopy is a cross-cutting characterization technique of key demand and relevance within materials science, materials engineering, and bio-science/omics research communities. diff --git a/manual/source/examples/index.rst b/manual/source/examples/index.rst index dbea811c4..52407feb0 100644 --- a/manual/source/examples/index.rst +++ b/manual/source/examples/index.rst @@ -1,8 +1,8 @@ .. _Examples: -================================================ -Examples of writing and reading NeXus data files -================================================ +============================== +NeXus: Examples data files I/O +============================== .. .. image:: ../img/NeXus.png diff --git a/manual/source/transport-structure.rst b/manual/source/transport-structure.rst index d75649a1f..80cbcc1c8 100644 --- a/manual/source/transport-structure.rst +++ b/manual/source/transport-structure.rst @@ -1,7 +1,7 @@ .. _Transport-Structure-Fairmat: =================== -Transport Phenomena +Transport phenomena =================== Work of scientists within FAIRmat how to handshake between instrument control software like EPICS and CAMELS using NeXus resulted in an application definition for exemplar temperature dependent IV curve measurements. From 27cc7f85d62d23c3d41a50cc55d2f16ad2d06b23 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Mon, 26 Feb 2024 12:12:17 +0100 Subject: [PATCH 033/136] Moved profiling and other common information out of task specific groups as this was cumbersome to use. This essentially concludes the refactoring for appdefs for the paraprobe-toolbox, the remaining fixes can be implemented via bugfix PR to enable merging these definitions now from the too long v2 refactoring branches # Conflicts: # contributed_definitions/NXapm_paraprobe_clusterer_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_clusterer_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_distancer_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_distancer_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_intersector_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_intersector_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_nanochem_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_nanochem_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_ranger_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_ranger_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_selector_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_selector_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_spatstat_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_spatstat_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_tessellator_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_tessellator_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_tool_common.nxdl.xml # contributed_definitions/NXapm_paraprobe_tool_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_tool_results.nxdl.xml # contributed_definitions/NXapm_paraprobe_transcoder_config.nxdl.xml # contributed_definitions/NXapm_paraprobe_transcoder_results.nxdl.xml # contributed_definitions/nyaml/NXapm_paraprobe_clusterer_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_clusterer_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_distancer_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_distancer_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_intersector_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_intersector_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_nanochem_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_nanochem_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_ranger_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_ranger_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_selector_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_selector_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_spatstat_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_spatstat_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_tessellator_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_tessellator_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_tool_common.yaml # contributed_definitions/nyaml/NXapm_paraprobe_tool_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_tool_results.yaml # contributed_definitions/nyaml/NXapm_paraprobe_transcoder_config.yaml # contributed_definitions/nyaml/NXapm_paraprobe_transcoder_results.yaml --- .../NXapm_paraprobe_surfacer_config.nxdl.xml | 229 --------------- .../NXapm_paraprobe_surfacer_results.nxdl.xml | 270 ------------------ .../NXapm_paraprobe_surfacer_config.yaml | 167 ----------- .../NXapm_paraprobe_surfacer_results.yaml | 180 ------------ .../contributed_definitions/apm-structure.rst | 4 +- 5 files changed, 2 insertions(+), 848 deletions(-) delete mode 100644 contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml delete mode 100644 contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml delete mode 100644 contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml diff --git a/contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml b/contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml deleted file mode 100644 index a31d15d6e..000000000 --- a/contributed_definitions/NXapm_paraprobe_surfacer_config.nxdl.xml +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Number of alpha values (and offset values) to probe. - - - - - How many different match values does the filter specify. - - - - - Application definition for a configuration file of the paraprobe-surfacer tool. - - This tool is part of the paraprobe-toolbox. Inspect :ref:`NXapm_paraprobe_tool_config` for details. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Specifies the method that is used to preprocess the point cloud - prior to the alpha-shape computation. - - The option *default* specifies that no such filtering is applied. - The option *kuehbach* specifies that a Hoshen-Kopelman - percolation analysis is used to identify points that lie closer - to the edge of the dataset. Details about the methods are reported - in `M. Kühbach et al. <https://doi.org/10.1038/s41524-020-00486-1>`_. - - - - - - - - - When using the kuehbach preprocessing, this is the width of the - kernel for identifying which ions are in voxels close to the - edge of the point cloud. - - - - - - Specifies which method to use to define the alpha value. - - The value *convex_hull_naive* is the default. The setting instructs - the tool to use a fast specialized algorithm for computing only - the convex hull. The resulting triangles can be skinny. - - The value *convex_hull_refine* instructs to tool to refine the - quality of the mesh resulting from *convex_hull_naive* - via triangle flipping and splitting. - - The value *smallest_solid* instructs the CGAL library to choose a - value which realizes an alpha-shape that is the smallest solid. - - The value *cgal_optimal* instructs the CGAL library to choose a - value which the library considers as to be an optimal value. - Details are defined in the respective section of the CGAL library - on 3D alpha shapes. - - The value *set_of_values* instructs the tool to compute a list - collection of alpha-shapes for the specified alpha-values. - - The value *set_of_alpha_wrappings* instructs the tool to generate - a set of so-called alpha wrappings. These are similar to alpha-shapes - but provide additional guarantees (such as watertightness and - proximity constraints) on the resulting wrapping. - - - - - - - - - - - - - Array of alpha values to use when alpha_value_choice is - set_of_values or when alpha_value_choice is set_of_alpha_wrappings. - - - - - - - - Array of offset values to use when alpha_value_choice is set_of_alpha_wrappings. - The array of alpha_values and offset_values define a sequence of (alpha and offset value). - - - - - - - - Specifies if the tool should compute the set of exterior triangle facets - for each alpha complex (for convex hull, alpha shapes, and wrappings). - - - - - Specifies if the tool should check if the alpha complex of - exterior triangular facets is a closed polyhedron. - - - - - Specifies if the tool should compute all interior tetrahedra - of the alpha complex (currently only for alpha shapes). - - - - - - - - - - - - - - - - diff --git a/contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml b/contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml deleted file mode 100644 index 499628aa3..000000000 --- a/contributed_definitions/NXapm_paraprobe_surfacer_results.nxdl.xml +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - The total number of ions in the reconstruction. - - - - - The number of vertices of the alpha complex. - - - - - The number of faces of the alpha complex. - - - - - The total number of XDMF values to represent all faces of triangles via XDMF. - - - - - The total number of XDMF values to represent all faces of tetrahedra via XDMF. - - - - - Application definition for results files of the paraprobe-surfacer tool. - - This tool is part of the paraprobe-toolbox. Inspect the base class :ref:`NXapm_paraprobe_tool_results`. - The purpose and need of the paraprobe-surfacer tool is the generation of meshed - representation of the surface of the the reconstructed volume (or a portion) of it - using different algorithms from the computational geometry community. - - - - - - - - - - - - Paraprobe-surfacer can be used to load a ROI that is the entire or a - sub-set of the ion point cloud. In the point_cloud_wrapping process - the tool computes a triangulated surface mesh which encloses the - ROI/point cloud. This mesh can be seen as a model for the edge of - the dataset. - - Different algorithms can be used with paraprobe-surfacer to create - this mesh such as convex hulls, alpha-shapes as their generalization, - or alpha wrappings. - - Ideally, the resulting mesh should be a watertight polyhedron. - This polyhedron is not necessarily convex. For some algorithms there - is no guarantee that the resulting mesh yields a watertight mesh. - - - - - - - - - - - - - - - - - - - - A bitmask which identifies exactly all those ions whose positions - were considered when defining the filtered point set from which - that alpha_complex instance was computed. - - This window can be different to the window of the *point_set_wrapping* - parent group because irrelevant ions might have been filtered out in addition - to the window defined in *point_set_wrapping* to reduce e.g. computational - costs of the alpha complex computation. - - - - - Number of ions covered by the mask. - - - - - Number of bits assumed matching on a default datatype. - - - - - The bitfield of the mask. See :ref:`NXcs_filter_boolean_mask` for - how this bitfield is to be interpreted. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The set of triangles in the coordinate system paraprobe - which discretizes the exterior surface of the alpha complex. - - - - - - - - - - - - - - - - - - - - - - - A list of as many tuples of XDMF topology key, XDMF number - of vertices and a triple of vertex indices specifying each - triangle. The total number of entries is n_f_tri * (1+1+3). - - - - - - - - Do the triangles define a triangulated surface mesh that is watertight? - - - - - The volume which the triangulated surface mesh - encloses if that mesh is watertight. - - - - - - - The set of tetrahedra which represent the interior volume - of the complex if that is a closed two-manifold. - - - - - The accumulated volume of all interior tetrahedra. - - - - - - - - - - - - - - - - A list of as many tuples of XDMF topology key, XDMF number - of vertices and a triple of vertex indices specifying each - triangle. The total number of entries is n_f_tet * (1+1+4). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml b/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml deleted file mode 100644 index b72b66e52..000000000 --- a/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_config.yaml +++ /dev/null @@ -1,167 +0,0 @@ -category: application -doc: | - Application definition for a configuration file of the paraprobe-surfacer tool. - - This tool is part of the paraprobe-toolbox. Inspect :ref:`NXapm_paraprobe_tool_config` for details. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. - n_alpha_values: | - Number of alpha values (and offset values) to probe. - n_values: | - How many different match values does the filter specify. -type: group -NXapm_paraprobe_surfacer_config(NXobject): - (NXentry): - exists: [min, 1, max, 1] - definition(NX_CHAR): - \@version(NX_CHAR): - enumeration: [NXapm_paraprobe_surfacer_config] - surface_meshing(NXapm_paraprobe_tool_config): - exists: [min, 1, max, 1] - (NXidentifier): - exists: optional - analysis_identifier(NX_UINT): - exists: recommended - reconstruction(NXserialized): - type(NX_CHAR): - path(NX_CHAR): - checksum(NX_CHAR): - algorithm(NX_CHAR): - position(NX_CHAR): - mass_to_charge(NX_CHAR): - ranging(NXserialized): - type(NX_CHAR): - path(NX_CHAR): - checksum(NX_CHAR): - algorithm(NX_CHAR): - ranging_definitions(NX_CHAR): - # filter that are here tool-specific parameter - spatial_filter(NXspatial_filter): - windowing_method(NX_CHAR): - hexahedron_set(NXcg_hexahedron_set): - exists: optional - dimensionality(NX_POSINT): - cardinality(NX_POSINT): - identifier_offset(NX_INT): - hexahedra(NXcg_face_list_data_structure): - vertices(NX_UINT): - cylinder_set(NXcg_cylinder_set): - exists: optional - dimensionality(NX_POSINT): - cardinality(NX_POSINT): - identifier_offset(NX_INT): - center(NX_NUMBER): - height(NX_NUMBER): - radii(NX_NUMBER): - ellipsoid_set(NXcg_ellipsoid_set): - exists: optional - dimensionality(NX_POSINT): - cardinality(NX_POSINT): - identifier_offset(NX_INT): - center(NX_NUMBER): - half_axes_radii(NX_NUMBER): - orientation(NX_NUMBER): - polyhedron_set(NXcg_polyhedron_set): - exists: optional - # TODO - bitmask(NXcs_filter_boolean_mask): - exists: optional - number_of_objects(NX_UINT): - bitdepth(NX_UINT): - mask(NX_UINT): - # leave open if scalar or matrix - # dim: (i,) - identifier(NX_UINT): - evaporation_id_filter(NXsubsampling_filter): - exists: optional - min_incr_max(NX_INT): - iontype_filter(NXmatch_filter): - exists: optional - method(NX_CHAR): - match(NX_NUMBER): - hit_multiplicity_filter(NXmatch_filter): - # config - preprocessing(NXprocess): - method(NX_CHAR): - doc: | - Specifies the method that is used to preprocess the point cloud - prior to the alpha-shape computation. - - The option *default* specifies that no such filtering is applied. - The option *kuehbach* specifies that a Hoshen-Kopelman - percolation analysis is used to identify points that lie closer - to the edge of the dataset. Details about the methods are reported - in `M. Kühbach et al. `_. - enumeration: [default, kuehbach] - kernel_width(NX_UINT): - doc: | - When using the kuehbach preprocessing, this is the width of the - kernel for identifying which ions are in voxels close to the - edge of the point cloud. - unit: NX_UNITLESS - alpha_value_choice(NX_CHAR): - doc: | - Specifies which method to use to define the alpha value. - - The value *convex_hull_naive* is the default. The setting instructs - the tool to use a fast specialized algorithm for computing only - the convex hull. The resulting triangles can be skinny. - - The value *convex_hull_refine* instructs to tool to refine the - quality of the mesh resulting from *convex_hull_naive* - via triangle flipping and splitting. - - The value *smallest_solid* instructs the CGAL library to choose a - value which realizes an alpha-shape that is the smallest solid. - - The value *cgal_optimal* instructs the CGAL library to choose a - value which the library considers as to be an optimal value. - Details are defined in the respective section of the CGAL library - on 3D alpha shapes. - - The value *set_of_values* instructs the tool to compute a list - collection of alpha-shapes for the specified alpha-values. - - The value *set_of_alpha_wrappings* instructs the tool to generate - a set of so-called alpha wrappings. These are similar to alpha-shapes - but provide additional guarantees (such as watertightness and - proximity constraints) on the resulting wrapping. - enumeration: [convex_hull_naive, convex_hull_refine, smallest_solid, cgal_optimal, set_of_values, set_of_alpha_wrappings] - alpha_values(NX_FLOAT): - doc: | - Array of alpha values to use when alpha_value_choice is - set_of_values or when alpha_value_choice is set_of_alpha_wrappings. - unit: NX_ANY - # \@units: nm^2 - dim: (n_alpha_values,) - offset_values(NX_FLOAT): - doc: | - Array of offset values to use when alpha_value_choice is set_of_alpha_wrappings. - The array of alpha_values and offset_values define a sequence of (alpha and offset value). - unit: NX_LENGTH - # \@units: nm - dim: (n_alpha_values,) - has_exterior_facets(NX_BOOLEAN): - doc: | - Specifies if the tool should compute the set of exterior triangle facets - for each alpha complex (for convex hull, alpha shapes, and wrappings). - has_closure(NX_BOOLEAN): - doc: | - Specifies if the tool should check if the alpha complex of - exterior triangular facets is a closed polyhedron. - has_interior_tetrahedra(NX_BOOLEAN): - doc: | - Specifies if the tool should compute all interior tetrahedra - of the alpha complex (currently only for alpha shapes). - # NEW ISSUE: has_facet_appearance(NX_BOOLEAN): - # profiling - (NXprogram): - exists: [min, 1, max, infty] - program(NX_CHAR): - \@version(NX_CHAR): - profiling(NXcs_profiling): - exists: recommended - start_time(NX_DATE_TIME): - end_time(NX_DATE_TIME): - current_working_directory(NX_CHAR): \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml b/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml deleted file mode 100644 index cc4e0c98a..000000000 --- a/contributed_definitions/nyaml/NXapm_paraprobe_surfacer_results.yaml +++ /dev/null @@ -1,180 +0,0 @@ -category: application -doc: | - Application definition for results files of the paraprobe-surfacer tool. - - This tool is part of the paraprobe-toolbox. Inspect the base class :ref:`NXapm_paraprobe_tool_results`. - The purpose and need of the paraprobe-surfacer tool is the generation of meshed - representation of the surface of the the reconstructed volume (or a portion) of it - using different algorithms from the computational geometry community. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. - n_ions: | - The total number of ions in the reconstruction. - n_v_tri: | - The number of vertices of the alpha complex. - n_f_tri: | - The number of faces of the alpha complex. - n_f_tri_xdmf: | - The total number of XDMF values to represent all faces of triangles via XDMF. - n_f_tet_xdmf: | - The total number of XDMF values to represent all faces of tetrahedra via XDMF. -type: group -NXapm_paraprobe_surfacer_results(NXobject): - (NXentry): - exists: [min, 1, max, 1] - definition(NX_CHAR): - \@version(NX_CHAR): - enumeration: [NXapm_paraprobe_surfacer_results] - # tasks - point_set_wrapping(NXapm_paraprobe_tool_results): - doc: | - Paraprobe-surfacer can be used to load a ROI that is the entire or a - sub-set of the ion point cloud. In the point_cloud_wrapping process - the tool computes a triangulated surface mesh which encloses the - ROI/point cloud. This mesh can be seen as a model for the edge of - the dataset. - - Different algorithms can be used with paraprobe-surfacer to create - this mesh such as convex hulls, alpha-shapes as their generalization, - or alpha wrappings. - - Ideally, the resulting mesh should be a watertight polyhedron. - This polyhedron is not necessarily convex. For some algorithms there - is no guarantee that the resulting mesh yields a watertight mesh. - # config - analysis_identifier(NX_UINT): - config(NXserialized): - type(NX_CHAR): - path(NX_CHAR): - checksum(NX_CHAR): - algorithm(NX_CHAR): - window(NXcs_filter_boolean_mask): - number_of_ions(NX_UINT): - bitdepth(NX_UINT): - mask(NX_UINT): - # results - alpha_complexID(NXcg_alpha_complex): - exists: [min, 0, max, infty] - # (NXcg_grid): currently we do not store the underlying grid - # for eventually performed preprocessing - window(NXcs_filter_boolean_mask): - doc: | - A bitmask which identifies exactly all those ions whose positions - were considered when defining the filtered point set from which - that alpha_complex instance was computed. - - This window can be different to the window of the *point_set_wrapping* - parent group because irrelevant ions might have been filtered out in addition - to the window defined in *point_set_wrapping* to reduce e.g. computational - costs of the alpha complex computation. - # filtered in addition to the ROI or again the entire dataset - number_of_ions(NX_UINT): - doc: | - Number of ions covered by the mask. - unit: NX_UNITLESS - bitdepth(NX_UINT): - doc: | - Number of bits assumed matching on a default datatype. - unit: NX_UNITLESS - mask(NX_UINT): - doc: | - The bitfield of the mask. See :ref:`NXcs_filter_boolean_mask` for - how this bitfield is to be interpreted. - unit: NX_UNITLESS - dim: (n_ions,) - dimensionality(NX_UINT): - enumeration: [2, 3] - unit: NX_UNITLESS - type(NX_CHAR): - enumeration: [convex_hull, alpha_shape, alpha_wrapping, other, undefined] - mode(NX_CHAR): - enumeration: [general, regularized] - alpha(NX_NUMBER): - unit: NX_ANY - offset(NX_NUMBER): - exists: optional - unit: NX_LENGTH - triangle_set(NXcg_triangle_set): - exists: optional - doc: | - The set of triangles in the coordinate system paraprobe - which discretizes the exterior surface of the alpha complex. - identifier_offset(NX_INT): - triangles(NXcg_face_list_data_structure): - dimensionality(NX_POSINT): - number_of_vertices(NX_POSINT): - number_of_faces(NX_POSINT): - vertex_identifier_offset(NX_INT): - face_identifier_offset(NX_INT): - vertices(NX_FLOAT): - unit: NX_LENGTH - dim: (n_v_tri, 3) - faces(NX_UINT): - unit: NX_UNITLESS - dim: (n_f_tri, 3) - xdmf_topology(NX_UINT): - doc: | - A list of as many tuples of XDMF topology key, XDMF number - of vertices and a triple of vertex indices specifying each - triangle. The total number of entries is n_f_tri * (1+1+3). - unit: NX_UNITLESS - dim: (n_f_tri_xdmf,) - is_watertight(NX_BOOLEAN): - exists: optional - doc: | - Do the triangles define a triangulated surface mesh that is watertight? - volume(NX_FLOAT): - exists: optional - doc: | - The volume which the triangulated surface mesh - encloses if that mesh is watertight. - unit: NX_VOLUME - - interior_tetrahedra(NXcg_tetrahedron_set): - exists: optional - doc: | - The set of tetrahedra which represent the interior volume - of the complex if that is a closed two-manifold. - identifier_offset(NX_INT): - unit: NX_UNITLESS - volume(NX_FLOAT): - exists: optional - doc: | - The accumulated volume of all interior tetrahedra. - unit: NX_VOLUME - tetrahedra(NXcg_face_list_data_structure): - exists: optional - number_of_vertices(NX_POSINT): - number_of_faces(NX_POSINT): - vertex_identifier_offset(NX_INT): - face_identifier_offset(NX_INT): - vertices(NX_FLOAT): - unit: NX_LENGTH - dim: (n_v_tet, 3) - xdmf_topology(NX_UINT): - doc: | - A list of as many tuples of XDMF topology key, XDMF number - of vertices and a triple of vertex indices specifying each - triangle. The total number of entries is n_f_tet * (1+1+4). - unit: NX_UNITLESS - dim: (n_f_tet_xdmf,) - # TRIANGLE_SET_WRAPPING(NXprocess): - # For the future as we may wish to wrap primitives other like triangles or polylines. - # global - (NXuser): - exists: [min, 0, max, infty] - name(NX_CHAR): - (NXcoordinate_system_set): - paraprobe(NXcoordinate_system): - type(NX_CHAR): - handedness(NX_CHAR): - x(NX_NUMBER): - unit: NX_LENGTH - dim: (3,) - y(NX_NUMBER): - unit: NX_LENGTH - dim: (3,) - z(NX_NUMBER): - unit: NX_LENGTH - dim: (3,) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index a36a94ad7..a9671b654 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -208,8 +208,8 @@ Base classes have been defined to group common pieces of information for each to toolbox. For each tool we define a pair of base classes. One for the configuration (input) side and one for the results (output) side: - :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`: - Common parts of configuration settings and results respectively useful for several tools of the paraprobe-toolbox. + :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`, :ref:`NXapm_paraprobe_tool_common`: + Configuration, results, and common parts respectively useful for the application definitions for tools of the paraprobe-toolbox. .. _ApmParaprobeAppDef: From bc2e8de4c688564c1c843fbeb00a9ec6015332ed Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 29 Feb 2024 22:24:08 +0100 Subject: [PATCH 034/136] Cleanly removed NXem_base class # Conflicts: # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_base.nxdl.xml # contributed_definitions/NXevent_data_em.nxdl.xml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_base.yaml # contributed_definitions/nyaml/NXevent_data_em.yaml # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXem_base.nxdl.xml | 390 ------------------ .../NXimage_r_set_diff.nxdl.xml | 2 +- contributed_definitions/nyaml/NXem_base.yaml | 300 -------------- .../nyaml/NXimage_r_set_diff.yaml | 2 +- 4 files changed, 2 insertions(+), 692 deletions(-) delete mode 100644 contributed_definitions/NXem_base.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXem_base.yaml diff --git a/contributed_definitions/NXem_base.nxdl.xml b/contributed_definitions/NXem_base.nxdl.xml deleted file mode 100644 index e1add30bd..000000000 --- a/contributed_definitions/NXem_base.nxdl.xml +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - - Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. - - This base class combines a method-specific and technical-design-level base class - instance to provide a template for storing parameterized descriptions of - pieces of information collected when performing electron microscopy research. - - The base class here shows all possible branches without making any statements - as to which of these have to be used in an instance. Thereby, the base class - provides a template how to name and structure concepts in a hierarchy - to support finding information and reducing the need for renaming and - restructuring information for a research field where many scientists perform - very specific research but who all also share commonalities like usage of - controlled electron beams, a focus on studies of electron beam matter interaction - to explore physical mechanisms and phenomena, or the desire to characterize materials - using electron microscopy. - - - - - - An at least as strong as SHA256 hashvalue of the file - which specifies the application definition. - - - - - NeXus NXDL schema to which this file conforms. - - - - - - - - The configuration of the I/O writer software (e.g. `pynxtools <https://github.com/FAIRmat-NFDI/pynxtools>`_) - which was used to generate this NeXus file instance. - - - - A collection of all programs and libraries which are considered relevant - to understand with which software tools this NeXus file instance was - generated. Ideally, to enable a binary recreation from the input data. - - Examples include the name and version of the libraries used to write the - instance. Ideally, the software which writes these NXprogram instances - also includes the version of the set of NeXus classes i.e. the specific - set of base classes, application definitions, and contributed definitions - with which the here described concepts can be resolved. - - For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ - which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ - research data management system, it makes sense to store e.g. the GitHub - repository commit and respective submodule references used. - - - - - - Ideally, a (globally) unique persistent identifier - for referring to this experiment. - - An experiment should be understood in that this can be an experiment - in reality or a computer simulation because also the latter is an - experiment (see the Cambridge Dictionary experiment: - *a test done in order to find out something, eg if an idea is correct*). - - The identifier is usually issued by the facility, laboratory, - or the principle investigator. The identifier enables to link - experiments/simulations to e.g. proposals. - - - - - Free-text description about the experiment. - - Users are strongly advised to parameterize their description of the - experiment by using the respective base classes instead of writing prose - into this field. - - The reason is that such free-text field is difficult to machine-interpret. - The motivation behind keeping this field for now is to learn through - the information entered in this field in how far the current base - classes are incomplete. - - - - - ISO 8601 time code with local time zone offset to UTC information included - when the microscope session started. If the application demands that time - codes in this section of the application definition should only be used - for specifying when the experiment was performed - and the exact - duration is not relevant - this start_time field should be used. - - Often though it is useful to specify a time interval via setting both - a start_time and an end_time because this enables software tools and - users to collect a more detailed bookkeeping of the experiment. - - The user should be aware that even with having both time instances specified, - it may not be possible to infer how long the experiment took or for how - long data were acquired. - - More detailed timing data over the course of the experiment have - to be collected to compute this. These computations can take - advantage of individual time stamps start_time and end_time - in :ref:`NXevent_data_em` instances. - - - - - ISO 8601 time code with local time zone offset to UTC included when - the microscope session ended. See docstring of the start_time field - to see how the start_time and end_time should be used together. - - - - - - Possibility to store a collection of serialized resources - that are associated with the experiment. - - An example how to use this set could be to document - from which files generated by software of technology partners - the information in an instance of NXem was filled. - - If resources from technology partners would also be documented - semantically annotated there would not even be a necessity to - copy over specific information in NeXus files as one could write - a inference and information/fact/knowledge retrieval algorithm whereby - a specific piece of information that is related to an experiment or simulation - is just read directly from the respective file of the technology partner. - - The reason why currently this works convincingly in hardly any research - data management system is the strong heterogeneity of the information contained - in such files and the fact that often context and documentation specifically - rich semantic documentation and contextualization is missing. - - - - - - Contact information and eventually details of at least one person - who performed or was involved in the session. This can be the - principle investigator who performed this experiment or the student - who performed the simulation. - Adding multiple users if relevant is recommended. - - - - Given (first) name and surname of the user. - - - - - Name of the affiliation of the user at the point in time - when the experiment was performed. - - - - - Postal address of the affiliation. - - - - - Email address of the user at the point in time when the experiment - was performed. Writing the most permanently used email is recommended. - - - - - Service as another mean of identification of a user than by the name. - Examples could be details about an ORCID or social media account of - the user. - - - - - (Business) (tele)phone number of the user at the point - in time when the experiment was performed. - - - - - Which role does the user have in the place and at the point - in time when the experiment was performed? Technician operating - the microscope, student, postdoc, principle investigator, or guest - are common examples. - - - - - - - A description of the material characterized in the experiment. - Sample and specimen are threaded as de facto synonyms. - Samples can be real specimens or virtual (see method). - - - - A qualifier whether the sample is a real one or a - virtual one (in a computer simulation) - - - - - - - - - - Ideally, (globally) unique persistent identifier which distinguishes - the specimen from all others and especially the predecessor/origin - from where the specimen was cut. - - This field must not be used for an alias! Instead, use name. - - In cases where multiple specimens were loaded into the microscope, - the identifier has to resolve the specific sample, whose results are - stored by this :ref:`NXentry` instance, because a single NXentry should be - used only for the characterization of a single specimen. - - Details about the specimen preparation should be - stored in resources referring to parent_identifier. - - - - - Identifier of the sample from which the sample was cut or the string - *None*. The purpose of this field is to support functionalities - for tracking sample provenance via a research data management system. - - - - - ISO 8601 time code with local time zone offset to UTC information - when the specimen was prepared. - - Ideally, report the end of the preparation, i.e. the last known time - the measured specimen surface was actively prepared. Ideally, this - matches the last timestamp that is mentioned in the digital resource - pointed to by parent_identifier. - - Knowing when the specimen was exposed to e.g. specific atmosphere is - especially required for environmentally sensitive material such as - hydrogen charged specimens or experiments including tracers with a - short half time. Additional time stamps prior to preparation_date - should better be placed in resources which describe but which do not pollute - the description here with prose. Resolving these connected pieces of information - is considered within the responsibility of the research data management - system. - - - - - An alias used to refer to the specimen to please readability for humans. - - - - - List of comma-separated elements from the periodic table that are - contained in the sample. If the sample substance has multiple - components, all elements from each component must be included in - `atom_types`. - - The purpose of the field is to offer research data management systems an - opportunity to parse the relevant elements without having to interpret - these from the resources pointed to by parent_identifier or walk through - eventually deeply nested groups in data instances. - - - - - - (Measured) sample thickness. - - The information is recorded to qualify if the beam used was likely - able to shine through the specimen. For scanning electron microscopy, - in many cases the specimen is typically thicker than what is - illuminatable by the electron beam. - - In this case the value should be set to the actual thickness of - the specimen viewed for an illumination situation where the nominal - surface normal of the specimen is parallel to the optical axis. - - - - - - - (Measured) density of the specimen. - - For multi-layered specimens this field should only be used to describe - the density of the excited volume. For scanning electron microscopy - the usage of this field is discouraged and instead an instance of an - :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` - instances can provide a cleaner description of the relevant details - why one may wish to store the density of the specimen. - - - - - Discouraged free-text field to provide further detail although adding - parent_identifier and having a working research data management system - should provide this contextualization. - - - - - - - - - - - - A region-of-interest analyzed either during or after the session - for which specific processed data generated from the measured or the - simulated data are available. - - - - - - - - - - - - diff --git a/contributed_definitions/NXimage_r_set_diff.nxdl.xml b/contributed_definitions/NXimage_r_set_diff.nxdl.xml index c9ff02c0d..33a4eeb65 100644 --- a/contributed_definitions/NXimage_r_set_diff.nxdl.xml +++ b/contributed_definitions/NXimage_r_set_diff.nxdl.xml @@ -59,7 +59,7 @@ on Kikuchi diffraction pattern here specifically the research community of Electron Backscatter Diffraction (EBSD). - For this reason, this base class and related :ref:`NXem_base` classes extend the + For this reason, this base class and the :ref:`NXem_ebsd` base class extend the work of `M. A. Jackson et al. <https://doi.org/10.1186/2193-9772-3-4>`_ (one of the developers of DREAM.3D) and the H5OINA public file format developed by `P. Pinard et al. <https://doi.org/10.1017/S1431927621006103>`_ with Oxford Instruments. diff --git a/contributed_definitions/nyaml/NXem_base.yaml b/contributed_definitions/nyaml/NXem_base.yaml deleted file mode 100644 index 90461471f..000000000 --- a/contributed_definitions/nyaml/NXem_base.yaml +++ /dev/null @@ -1,300 +0,0 @@ -category: base -# template to be used for an application definition -doc: | - Blue-print of a generic appdef for electron microscopy research formulated as a deep base class. - - This base class combines a method-specific and technical-design-level base class - instance to provide a template for storing parameterized descriptions of - pieces of information collected when performing electron microscopy research. - - The base class here shows all possible branches without making any statements - as to which of these have to be used in an instance. Thereby, the base class - provides a template how to name and structure concepts in a hierarchy - to support finding information and reducing the need for renaming and - restructuring information for a research field where many scientists perform - very specific research but who all also share commonalities like usage of - controlled electron beams, a focus on studies of electron beam matter interaction - to explore physical mechanisms and phenomena, or the desire to characterize materials - using electron microscopy. -# flesh out the description of that to read the docs, because currently the -# description on the NeXus front-page is overwhelming -# considering what we learned from the diataxis workshop we write here a -# specification neither a how to nor a tutorial which explains all the context -# because we address here developers of software -type: group -NXem_base(NXobject): # but should inherit from NXroot - # each NeXus file instance should have a default plot - # however as there are cases when this cannot be assured we cannot - # make the default required, one example is e.g. a NeXus instance - # where scientists just store conventions without a default plot - (NXentry): # means ENTRY(NXentry) - \@version(NX_CHAR): - doc: | - An at least as strong as SHA256 hashvalue of the file - which specifies the application definition. - definition(NX_CHAR): - doc: | - NeXus NXDL schema to which this file conforms. - enumeration: [NXem] - cs_profiling(NXcs_profiling): - doc: | - The configuration of the I/O writer software (e.g. `pynxtools `_) - which was used to generate this NeXus file instance. - (NXprogram): # understood by default as PROGRAM(NXprogram), i.e. program1, program2, ... - doc: | - A collection of all programs and libraries which are considered relevant - to understand with which software tools this NeXus file instance was - generated. Ideally, to enable a binary recreation from the input data. - - Examples include the name and version of the libraries used to write the - instance. Ideally, the software which writes these NXprogram instances - also includes the version of the set of NeXus classes i.e. the specific - set of base classes, application definitions, and contributed definitions - with which the here described concepts can be resolved. - - For the `pynxtools library `_ - which is used by the `NOMAD `_ - research data management system, it makes sense to store e.g. the GitHub - repository commit and respective submodule references used. - experiment_identifier(NXidentifier): - doc: | - Ideally, a (globally) unique persistent identifier - for referring to this experiment. - - An experiment should be understood in that this can be an experiment - in reality or a computer simulation because also the latter is an - experiment (see the Cambridge Dictionary experiment: - *a test done in order to find out something, eg if an idea is correct*). - - The identifier is usually issued by the facility, laboratory, - or the principle investigator. The identifier enables to link - experiments/simulations to e.g. proposals. - experiment_description(NX_CHAR): - doc: | - Free-text description about the experiment. - - Users are strongly advised to parameterize their description of the - experiment by using the respective base classes instead of writing prose - into this field. - - The reason is that such free-text field is difficult to machine-interpret. - The motivation behind keeping this field for now is to learn through - the information entered in this field in how far the current base - classes are incomplete. - start_time(NX_DATE_TIME): - doc: | - ISO 8601 time code with local time zone offset to UTC information included - when the microscope session started. If the application demands that time - codes in this section of the application definition should only be used - for specifying when the experiment was performed - and the exact - duration is not relevant - this start_time field should be used. - - Often though it is useful to specify a time interval via setting both - a start_time and an end_time because this enables software tools and - users to collect a more detailed bookkeeping of the experiment. - - The user should be aware that even with having both time instances specified, - it may not be possible to infer how long the experiment took or for how - long data were acquired. - - More detailed timing data over the course of the experiment have - to be collected to compute this. These computations can take - advantage of individual time stamps start_time and end_time - in :ref:`NXevent_data_em` instances. - end_time(NX_DATE_TIME): - doc: | - ISO 8601 time code with local time zone offset to UTC included when - the microscope session ended. See docstring of the start_time field - to see how the start_time and end_time should be used together. - (NXcite): - (NXserialized): - doc: | - Possibility to store a collection of serialized resources - that are associated with the experiment. - - An example how to use this set could be to document - from which files generated by software of technology partners - the information in an instance of NXem was filled. - - If resources from technology partners would also be documented - semantically annotated there would not even be a necessity to - copy over specific information in NeXus files as one could write - a inference and information/fact/knowledge retrieval algorithm whereby - a specific piece of information that is related to an experiment or simulation - is just read directly from the respective file of the technology partner. - - The reason why currently this works convincingly in hardly any research - data management system is the strong heterogeneity of the information contained - in such files and the fact that often context and documentation specifically - rich semantic documentation and contextualization is missing. - # using NXserialized here instead of NXnote as the former is more specific - (NXuser): - doc: | - Contact information and eventually details of at least one person - who performed or was involved in the session. This can be the - principle investigator who performed this experiment or the student - who performed the simulation. - Adding multiple users if relevant is recommended. - name(NX_CHAR): - doc: | - Given (first) name and surname of the user. - affiliation(NX_CHAR): - doc: | - Name of the affiliation of the user at the point in time - when the experiment was performed. - address(NX_CHAR): - doc: | - Postal address of the affiliation. - email(NX_CHAR): - doc: | - Email address of the user at the point in time when the experiment - was performed. Writing the most permanently used email is recommended. - identifier(NXidentifier): - doc: | - Service as another mean of identification of a user than by the name. - Examples could be details about an ORCID or social media account of - the user. - telephone_number(NX_CHAR): - doc: | - (Business) (tele)phone number of the user at the point - in time when the experiment was performed. - role(NX_CHAR): - doc: | - Which role does the user have in the place and at the point - in time when the experiment was performed? Technician operating - the microscope, student, postdoc, principle investigator, or guest - are common examples. - sample(NXsample): - # NEW ISSUE: inject the conclusion from the discussion with Andrea - # according to SAMPLE.yaml 0f8df14 2022/06/15 - # ID: -> maps to name - # name: -> short_title - # user: -> not matched right now - # citation: doi ->why relevant, should be solved by RDMS - doc: | - A description of the material characterized in the experiment. - Sample and specimen are threaded as de facto synonyms. - Samples can be real specimens or virtual (see method). - method(NX_CHAR): - doc: | - A qualifier whether the sample is a real one or a - virtual one (in a computer simulation) - enumeration: [experiment, simulation] - # MK:: declared_by_vendor I would rather expect this for a substance - # COMPONENT.yaml - # SUBSTANCE: - # QUANTIFY - identifier(NXidentifier): - doc: | - Ideally, (globally) unique persistent identifier which distinguishes - the specimen from all others and especially the predecessor/origin - from where the specimen was cut. - - This field must not be used for an alias! Instead, use name. - - In cases where multiple specimens were loaded into the microscope, - the identifier has to resolve the specific sample, whose results are - stored by this :ref:`NXentry` instance, because a single NXentry should be - used only for the characterization of a single specimen. - - Details about the specimen preparation should be - stored in resources referring to parent_identifier. - parent_identifier(NXidentifier): - doc: | - Identifier of the sample from which the sample was cut or the string - *None*. The purpose of this field is to support functionalities - for tracking sample provenance via a research data management system. - preparation_date(NX_DATE_TIME): - doc: | - ISO 8601 time code with local time zone offset to UTC information - when the specimen was prepared. - - Ideally, report the end of the preparation, i.e. the last known time - the measured specimen surface was actively prepared. Ideally, this - matches the last timestamp that is mentioned in the digital resource - pointed to by parent_identifier. - - Knowing when the specimen was exposed to e.g. specific atmosphere is - especially required for environmentally sensitive material such as - hydrogen charged specimens or experiments including tracers with a - short half time. Additional time stamps prior to preparation_date - should better be placed in resources which describe but which do not pollute - the description here with prose. Resolving these connected pieces of information - is considered within the responsibility of the research data management - system. - name(NX_CHAR): - doc: | - An alias used to refer to the specimen to please readability for humans. - atom_types(NX_CHAR): - doc: | - List of comma-separated elements from the periodic table that are - contained in the sample. If the sample substance has multiple - components, all elements from each component must be included in - `atom_types`. - - The purpose of the field is to offer research data management systems an - opportunity to parse the relevant elements without having to interpret - these from the resources pointed to by parent_identifier or walk through - eventually deeply nested groups in data instances. - # NEW ISSUE: use Andrea and MarkusK groups for describing the geometry of the sample - thickness(NX_NUMBER): - doc: | - (Measured) sample thickness. - - The information is recorded to qualify if the beam used was likely - able to shine through the specimen. For scanning electron microscopy, - in many cases the specimen is typically thicker than what is - illuminatable by the electron beam. - - In this case the value should be set to the actual thickness of - the specimen viewed for an illumination situation where the nominal - surface normal of the specimen is parallel to the optical axis. - unit: NX_LENGTH - # \@units: nm - # NEW ISSUE: error estimates of the thickness and origin, i.e. how the value was obtained would be useful - # NEW ISSUE: error model - # NEW ISSUE: the KIT/SCC SEM, TEM schemata further qualify samples whether they are conductive e/ibeam sensitive - # etc. The problem with this is that beam sensitivity is too vague but spatiotemporal electron dose integral dependent - # KIT/SCC distinguish further conductivity and magnetic properties. While the motivation is clear, making - # it thus simple is likely problematic when the data entered in such fields remaining qualitative. - # what are good or bad properties, it would make sense though to quantify these values - # this includes the description of eventual plasma cleaning steps, - # just knowing that a sample was plasma cleaned is insufficient, maybe it was not cleaned long enough - # if plasma cleaning is done outside the EM than its certainly history, if it happens inside the EM - # are the ibeam description capabilities not sufficient enough? - density(NX_NUMBER): - # NX_MASS_PER_VOLUME - doc: | - (Measured) density of the specimen. - - For multi-layered specimens this field should only be used to describe - the density of the excited volume. For scanning electron microscopy - the usage of this field is discouraged and instead an instance of an - :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` - instances can provide a cleaner description of the relevant details - why one may wish to store the density of the specimen. - unit: NX_ANY - description: - doc: | - Discouraged free-text field to provide further detail although adding - parent_identifier and having a working research data management system - should provide this contextualization. - # (NXmonitor): - (NXdata): - (NXcoordinate_system_set): - # link to an instance of an NXinstrument but that is anyway specialized for EM - measurement(NXem_msr): - simulation(NXem_sim): - (NXroi): - doc: | - A region-of-interest analyzed either during or after the session - for which specific processed data generated from the measured or the - simulated data are available. - se(NXem_img): - bse(NXem_img): - ebsd(NXem_ebsd): - eds(NXem_eds): - adf(NXem_adf): - eels(NXem_eels): - correlation(NXem_correlation): - # cl(NXem_cl): diff --git a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml index 79ca31b16..5a0e27e28 100644 --- a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml +++ b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml @@ -14,7 +14,7 @@ doc: | on Kikuchi diffraction pattern here specifically the research community of Electron Backscatter Diffraction (EBSD). - For this reason, this base class and related :ref:`NXem_base` classes extend the + For this reason, this base class and the :ref:`NXem_ebsd` base class extend the work of `M. A. Jackson et al. `_ (one of the developers of DREAM.3D) and the H5OINA public file format developed by `P. Pinard et al. `_ with Oxford Instruments. From 7e22bc360ad698f84db0639cffc44885c4d1ef04 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 11 Apr 2024 13:22:56 +0200 Subject: [PATCH 035/136] Updated version of NXapm_compositionspace_* appdefs and documentation of the context that is to this work between NFDI-MatWerk and FAIRmat # Conflicts: # contributed_definitions/NXapm_compositionspace_config.nxdl.xml # contributed_definitions/NXapm_compositionspace_results.nxdl.xml # contributed_definitions/nyaml/NXapm_compositionspace_config.yaml # contributed_definitions/nyaml/NXapm_compositionspace_results.yaml --- .../contributed_definitions/apm-structure.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index a9671b654..ba275045c 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -10,6 +10,7 @@ Atom-probe tomography ApmBC StatusQuoApm ApmParaprobeAppDef + ApmGermanNfdi .. _IntroductionApm: @@ -265,3 +266,19 @@ tool one such pair is proposed: Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, spatial arrangement, and colocation of 3D objects via graph-based techniques. + +.. _ApmGermanNfdi: + +Joint work German NFDI consortia NFDI-MatWerk and FAIRmat +####################################################################### + +Members of the NFDI-MatWerk and the FAIRmat consortium of the German National Research Data Infrastructure +are working together within the Infrastructure Use Case IUC09 of the NFDI-MatWerk project to work on examples +how software tools in both consortia become better documented and interoperable to use. Within this project, +we have also added the `CompositionSpace tool that has been developed at the Max-Planck-Institut für Eisenforschung +GmbH in Düsseldorf `_ by A. Saxena et al. + +Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: + + :ref:`NXapm_compositionspace_config`, :ref:`NXapm_compositionspace_results`: + Configuration and the results respectively of the CompositionSpace tool. From 37ae8644e77c6e6ba458c8e5ff2a63a698ec6faf Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Tue, 18 Jun 2024 10:19:22 +0200 Subject: [PATCH 036/136] fixed make local errors after renaming NXopt # Conflicts: # manual/source/classes/contributed_definitions/ellipsometry-structure.rst --- .../{NXopt.nxdl.xml => NXoptical_spectroscopy.nxdl.xml} | 0 .../contributed_definitions/ellipsometry-structure.rst | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename contributed_definitions/{NXopt.nxdl.xml => NXoptical_spectroscopy.nxdl.xml} (100%) diff --git a/contributed_definitions/NXopt.nxdl.xml b/contributed_definitions/NXoptical_spectroscopy.nxdl.xml similarity index 100% rename from contributed_definitions/NXopt.nxdl.xml rename to contributed_definitions/NXoptical_spectroscopy.nxdl.xml diff --git a/manual/source/classes/contributed_definitions/ellipsometry-structure.rst b/manual/source/classes/contributed_definitions/ellipsometry-structure.rst index 32259ecd5..1f3ddbfaf 100644 --- a/manual/source/classes/contributed_definitions/ellipsometry-structure.rst +++ b/manual/source/classes/contributed_definitions/ellipsometry-structure.rst @@ -1,8 +1,8 @@ .. _Ellipsometry-Structure: -==================== +======================== Optical Spectroscopy -==================== +======================== .. index:: Ellipsometry @@ -12,7 +12,7 @@ Optical Spectroscopy .. _Ellipsometry: Ellipsometry -############ +############## Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. The measurements are based on determining how the polarization state of light changes upon transmission and reflection. From 8b613da0231879c90e85e9e5fb3e9967225224b9 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 26 Jun 2024 15:49:22 +0200 Subject: [PATCH 037/136] Hooked in description of new base classes in manual, NXammeter new base class # Conflicts: # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXammeter.nxdl.xml | 35 ++++++++++++++++++++ contributed_definitions/nyaml/NXammeter.yaml | 11 ++++++ 2 files changed, 46 insertions(+) create mode 100644 contributed_definitions/NXammeter.nxdl.xml create mode 100644 contributed_definitions/nyaml/NXammeter.yaml diff --git a/contributed_definitions/NXammeter.nxdl.xml b/contributed_definitions/NXammeter.nxdl.xml new file mode 100644 index 000000000..1adee6e06 --- /dev/null +++ b/contributed_definitions/NXammeter.nxdl.xml @@ -0,0 +1,35 @@ + + + + + + Base class for an ampere meter. + + + + + Current measured. + + + + diff --git a/contributed_definitions/nyaml/NXammeter.yaml b/contributed_definitions/nyaml/NXammeter.yaml new file mode 100644 index 000000000..21353cf77 --- /dev/null +++ b/contributed_definitions/nyaml/NXammeter.yaml @@ -0,0 +1,11 @@ +category: base +doc: | + Base class for an ampere meter. +type: group +NXammeter(NXobject): + # user perspective + current(NX_NUMBER): + doc: | + Current measured. + unit: NX_CURRENT + (NXfabrication): \ No newline at end of file From 9a5bca329ccc6f1b0f9ff6767d927e03767f4ad5 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 27 Jun 2024 12:15:43 +0200 Subject: [PATCH 038/136] Implemented suggestions from @lukaspie related to points mentioned in #243 # Conflicts: # contributed_definitions/NXcomponent_em.nxdl.xml # contributed_definitions/NXcorrector_cs.nxdl.xml # contributed_definitions/NXebeam_column.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXibeam_column.nxdl.xml # contributed_definitions/nyaml/NXcomponent_em.yaml # contributed_definitions/nyaml/NXcorrector_cs.yaml # contributed_definitions/nyaml/NXebeam_column.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXibeam_column.yaml # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXammeter.nxdl.xml | 35 ---------- .../NXcomponent_em.nxdl.xml | 69 ------------------- contributed_definitions/nyaml/NXammeter.yaml | 11 --- .../nyaml/NXcomponent_em.yaml | 39 ----------- 4 files changed, 154 deletions(-) delete mode 100644 contributed_definitions/NXammeter.nxdl.xml delete mode 100644 contributed_definitions/NXcomponent_em.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXammeter.yaml delete mode 100644 contributed_definitions/nyaml/NXcomponent_em.yaml diff --git a/contributed_definitions/NXammeter.nxdl.xml b/contributed_definitions/NXammeter.nxdl.xml deleted file mode 100644 index 1adee6e06..000000000 --- a/contributed_definitions/NXammeter.nxdl.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - Base class for an ampere meter. - - - - - Current measured. - - - - diff --git a/contributed_definitions/NXcomponent_em.nxdl.xml b/contributed_definitions/NXcomponent_em.nxdl.xml deleted file mode 100644 index bedba8b6f..000000000 --- a/contributed_definitions/NXcomponent_em.nxdl.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - Base class for components used in an electron microscope. - - The electron microscope can be a real one or a simulated microscope. - The key motivation behind this generalization is the observation that in all - cases a controlled electron beam is generated in reality or that beam is simulated - and this beam is then used or modified in a controlled manner for the purpose - of studying physical interaction mechanisms of the beam with matter. - Here it does not matter whether one considers a real specimen or a simulated one. - - Using a common description for the real experiment in the lab and - what is - typically a simplification of it - via a computer simulation, has the benefit - that many pieces of information can be stored in the same way. In effect, - users are guided with finding information and unnecessary descriptive - variety for what are exactly the same concept is avoided to work towards - more interoperability. - - Another motivation to make no fundamental distinction between a scanning and - a transmission electron microscope is that both are electron microscopes whose - components are often very similar. - - - - Given name to the component e.g stage, lens C1, etc. - - - - - Ideally, a (globally) unique persistent identifier, link, or text to a - resource which gives further details to this component. - If such resource does not exist, a free-text field to report - further details about the component is possible. - - - - - - - Collection of axis-based translations and rotations to describe the - location and geometry of the component in the instrument. - - - diff --git a/contributed_definitions/nyaml/NXammeter.yaml b/contributed_definitions/nyaml/NXammeter.yaml deleted file mode 100644 index 21353cf77..000000000 --- a/contributed_definitions/nyaml/NXammeter.yaml +++ /dev/null @@ -1,11 +0,0 @@ -category: base -doc: | - Base class for an ampere meter. -type: group -NXammeter(NXobject): - # user perspective - current(NX_NUMBER): - doc: | - Current measured. - unit: NX_CURRENT - (NXfabrication): \ No newline at end of file diff --git a/contributed_definitions/nyaml/NXcomponent_em.yaml b/contributed_definitions/nyaml/NXcomponent_em.yaml deleted file mode 100644 index 78870cc26..000000000 --- a/contributed_definitions/nyaml/NXcomponent_em.yaml +++ /dev/null @@ -1,39 +0,0 @@ -category: base -doc: | - Base class for components used in an electron microscope. - - The electron microscope can be a real one or a simulated microscope. - The key motivation behind this generalization is the observation that in all - cases a controlled electron beam is generated in reality or that beam is simulated - and this beam is then used or modified in a controlled manner for the purpose - of studying physical interaction mechanisms of the beam with matter. - Here it does not matter whether one considers a real specimen or a simulated one. - - Using a common description for the real experiment in the lab and - what is - typically a simplification of it - via a computer simulation, has the benefit - that many pieces of information can be stored in the same way. In effect, - users are guided with finding information and unnecessary descriptive - variety for what are exactly the same concept is avoided to work towards - more interoperability. - - Another motivation to make no fundamental distinction between a scanning and - a transmission electron microscope is that both are electron microscopes whose - components are often very similar. -# `point Electronic GmbH `_ -type: group -NXcomponent_em(NXobject): - name(NX_CHAR): - doc: | - Given name to the component e.g stage, lens C1, etc. - description(NX_CHAR): # NXidentifier - doc: | - Ideally, a (globally) unique persistent identifier, link, or text to a - resource which gives further details to this component. - If such resource does not exist, a free-text field to report - further details about the component is possible. - (NXfabrication): - (NXprogram): - (NXtransformations): - doc: | - Collection of axis-based translations and rotations to describe the - location and geometry of the component in the instrument. From 66b661d629243dcdcc498dfc5daf300f43a027dc Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 27 Jun 2024 13:57:34 +0200 Subject: [PATCH 039/136] Simplified base class design for documenting aberrations # Conflicts: # contributed_definitions/NXaberration_model.nxdl.xml # contributed_definitions/NXaberration_model_ceos.nxdl.xml # contributed_definitions/NXaberration_model_nion.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/nyaml/NXaberration_model.yaml # contributed_definitions/nyaml/NXcorrector_cs.yaml # contributed_definitions/nyaml/NXem.yaml # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXcorrector_cs.nxdl.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contributed_definitions/NXcorrector_cs.nxdl.xml b/contributed_definitions/NXcorrector_cs.nxdl.xml index fcca05d7a..131e2dc53 100644 --- a/contributed_definitions/NXcorrector_cs.nxdl.xml +++ b/contributed_definitions/NXcorrector_cs.nxdl.xml @@ -83,8 +83,7 @@ NEW ISSUE: following parameters of the these constants and how they are useful-- Place for storing measured or estimated aberrations (for each image or final). - - + From 0e1cbf140341a1fab23fc13daa284f07d80822c1 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 27 Jun 2024 16:56:06 +0200 Subject: [PATCH 040/136] Replaced all locations where NXcomponent_em was used for NXcomponent, replaced all locations where NXaperture_em was used for NXaperture # Conflicts: # contributed_definitions/NXaperture_em.nxdl.xml # contributed_definitions/NXcorrector_cs.nxdl.xml # contributed_definitions/NXebeam_column.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXibeam_column.nxdl.xml # contributed_definitions/NXlens_em.nxdl.xml # contributed_definitions/NXscanbox_em.nxdl.xml # contributed_definitions/NXstage_lab.nxdl.xml # contributed_definitions/nyaml/NXcorrector_cs.yaml # contributed_definitions/nyaml/NXebeam_column.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXibeam_column.yaml # contributed_definitions/nyaml/NXlens_em.yaml # contributed_definitions/nyaml/NXscanbox_em.yaml # contributed_definitions/nyaml/NXstage_lab.yaml # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXcorrector_cs.nxdl.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contributed_definitions/NXcorrector_cs.nxdl.xml b/contributed_definitions/NXcorrector_cs.nxdl.xml index 131e2dc53..fcca05d7a 100644 --- a/contributed_definitions/NXcorrector_cs.nxdl.xml +++ b/contributed_definitions/NXcorrector_cs.nxdl.xml @@ -83,7 +83,8 @@ NEW ISSUE: following parameters of the these constants and how they are useful-- Place for storing measured or estimated aberrations (for each image or final). - + + From f1ad6bb6697d52240b2642fe8cafdce271d97576 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 27 Jun 2024 18:38:21 +0200 Subject: [PATCH 041/136] Fused NXimage_r_set, NXimage_c_set, NXimage_r_set_diff into a single more meaty base class NXimage_set, the partner in crime for NXspectrum_set # Conflicts: # contributed_definitions/NXapm.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_adf.nxdl.xml # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXem_eds.nxdl.xml # contributed_definitions/NXem_method.nxdl.xml # contributed_definitions/NXimage_c_set.nxdl.xml # contributed_definitions/NXimage_r_set.nxdl.xml # contributed_definitions/NXimage_r_set_diff.nxdl.xml # contributed_definitions/NXimage_set.nxdl.xml # contributed_definitions/NXspectrum_set.nxdl.xml # contributed_definitions/nyaml/NXapm.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_adf.yaml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXem_eds.yaml # contributed_definitions/nyaml/NXem_method.yaml # contributed_definitions/nyaml/NXevent_data_em.yaml # contributed_definitions/nyaml/NXimage_c_set.yaml # contributed_definitions/nyaml/NXimage_r_set.yaml # contributed_definitions/nyaml/NXimage_set.yaml # contributed_definitions/nyaml/NXspectrum_set.yaml # dev_tools/tests/test_nxdl_utils.py # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXem_adf.nxdl.xml | 65 ----- contributed_definitions/NXem_eds.nxdl.xml | 144 ---------- contributed_definitions/NXem_img.nxdl.xml | 1 - contributed_definitions/NXem_method.nxdl.xml | 47 ---- contributed_definitions/NXem_sim.nxdl.xml | 1 - .../NXimage_c_set.nxdl.xml | 247 ------------------ .../NXimage_r_set.nxdl.xml | 100 ------- .../NXimage_r_set_diff.nxdl.xml | 179 ------------- contributed_definitions/nyaml/NXem_adf.yaml | 28 -- contributed_definitions/nyaml/NXem_eds.yaml | 80 ------ contributed_definitions/nyaml/NXem_img.yaml | 1 - .../nyaml/NXem_method.yaml | 21 -- contributed_definitions/nyaml/NXem_sim.yaml | 1 - .../nyaml/NXimage_c_set.yaml | 140 ---------- .../nyaml/NXimage_r_set.yaml | 45 ---- .../nyaml/NXimage_r_set_diff.yaml | 123 --------- 16 files changed, 1223 deletions(-) delete mode 100644 contributed_definitions/NXem_adf.nxdl.xml delete mode 100644 contributed_definitions/NXem_eds.nxdl.xml delete mode 100644 contributed_definitions/NXem_method.nxdl.xml delete mode 100644 contributed_definitions/NXimage_c_set.nxdl.xml delete mode 100644 contributed_definitions/NXimage_r_set.nxdl.xml delete mode 100644 contributed_definitions/NXimage_r_set_diff.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXem_adf.yaml delete mode 100644 contributed_definitions/nyaml/NXem_eds.yaml delete mode 100644 contributed_definitions/nyaml/NXem_method.yaml delete mode 100644 contributed_definitions/nyaml/NXimage_c_set.yaml delete mode 100644 contributed_definitions/nyaml/NXimage_r_set.yaml delete mode 100644 contributed_definitions/nyaml/NXimage_r_set_diff.yaml diff --git a/contributed_definitions/NXem_adf.nxdl.xml b/contributed_definitions/NXem_adf.nxdl.xml deleted file mode 100644 index 64534699c..000000000 --- a/contributed_definitions/NXem_adf.nxdl.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - Number of images in the stack. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - - - Base class method-specific for annular dark field imaging. - - In the majority of cases simple d-dimensional regular scan patterns are used - to probe a region-of-interest (ROI). Examples can be single point aka spot - measurements, line profiles, or (rectangular) surface mappings. - The latter pattern is the most frequently used. - - For now the base class provides for scans for which the settings, - binning, and energy resolution is the same for each scan point. - - - - - Annulus inner (first value) and outer (second value) half angle. - - - - - - - - diff --git a/contributed_definitions/NXem_eds.nxdl.xml b/contributed_definitions/NXem_eds.nxdl.xml deleted file mode 100644 index 735bfe897..000000000 --- a/contributed_definitions/NXem_eds.nxdl.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - Number of pixel along the y direction, the slow direction - - - - - Number of pixel along the x direction, the fast direction - - - - - Number of X-ray photon energy (bins), the fastest direction. - - - - - Number of identified elements - - - - - Number of peaks detected - - - - - Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). - - `IUPAC instead of Siegbahn notation <https://doi.org/10.1002/xrs.1300200308>`_ should be used. - - - - - Details about computational steps how peaks were indexed as elements. - - - - The program with which the indexing was performed. - - - - - Name and location of each X-ray line which was indexed as a known ion. - For each ion, an NXion instance should be created which specifies - the origin of the signal. For each ion also the relevant IUPAC notation - X-ray lines should be specified. - - - - - Associated lower :math:`[e_{min}, e_{max}]` bounds of the - energy which is assumed associated with this peak. - - - - - - - - Theoretical energy of the line according to IUPAC. - - - - - IUPAC notation identifier of the line which the peak represents. - - This can be a list of IUPAC notations for (the seldom) case that - multiple lines are grouped with the same peak. - - - - - - - - - - List of the names of identified elements. - - - - - - - - Individual element-specific EDS/EDX/EDXS/SXES mapping - - A composition map is an image whose intensities for each pixel are the - accumulated X-ray quanta *under the curve(s)* of a set of peaks. - - These element-specific EDS maps are NXimage_r_set instances - and need to be named with the name of the element from the - element_names field. - - - - - A list of NXpeak instance names whose X-ray quanta - where accumulated for each pixel which yields an element-specific - EDS map. - - - - - - - - - - diff --git a/contributed_definitions/NXem_img.nxdl.xml b/contributed_definitions/NXem_img.nxdl.xml index ebf17380a..1d023c028 100644 --- a/contributed_definitions/NXem_img.nxdl.xml +++ b/contributed_definitions/NXem_img.nxdl.xml @@ -59,5 +59,4 @@ - diff --git a/contributed_definitions/NXem_method.nxdl.xml b/contributed_definitions/NXem_method.nxdl.xml deleted file mode 100644 index 086d4833d..000000000 --- a/contributed_definitions/NXem_method.nxdl.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - Base class to describe specific analysis methods in electron microscopy. - - This base class represent a template how specialized, deep, and method-specific - base classes can be defined with which an (NXem) application - definition gets equipped with specific groups to document method-specific - processing steps and report analyzed quantities. - - The template base class name :ref:`NXem_method` needs to be changed for each - method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. - - - - Details about processing steps. - - - - - - - diff --git a/contributed_definitions/NXem_sim.nxdl.xml b/contributed_definitions/NXem_sim.nxdl.xml index f5f10b1b9..560fee2fd 100644 --- a/contributed_definitions/NXem_sim.nxdl.xml +++ b/contributed_definitions/NXem_sim.nxdl.xml @@ -55,6 +55,5 @@ abTEM and other simulation packages, TEMgym, etc.--> - diff --git a/contributed_definitions/NXimage_c_set.nxdl.xml b/contributed_definitions/NXimage_c_set.nxdl.xml deleted file mode 100644 index 64c945c99..000000000 --- a/contributed_definitions/NXimage_c_set.nxdl.xml +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - - - Number of images in the (hyper)stack. - - - - - Number of pixel per image in the slowest direction. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - - - Specialized base class container for reporting a set of images in reciprocal space. - - In practice, complex numbers are encoded via some formatted pair of real values. - Typically, fast Algorithms for computing Fourier Transformations (FFT) are - used to encode images in reciprocal (frequency) space. FFT libraries are used - for implementing the key functionalities of these mathematical operations. - - Different libraries use different representations and encoding of the - image computed. Details can be found in the respective sections of the - typical FFT libraries: - - * `FFTW by M. Frigo and S. G. Johnson <https://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial>`_ - * `Intel MKL by the Intel Co. <https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2023-0/fourier-transform-functions.html>`_ - * `cuFFT by the NVidia Co. <https://docs.nvidia.com/cuda/cufft/index.html>`_ - - Users are strongly advised to inspect carefully which specific conventions - their library uses to be able to store and modify the implementation of their - code so that the serialized representations as it is detailed - here for NeXus matches with their intention. - - One- and two-dimensional FFTs should use the stack(NXdata) instances. - Three-dimensional FFTs should use the hyperstack(NXdata) instances. - - - - - Image stack. - - - - Image intensity of the real part. - - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - - Pixel coordinate center along j direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - - - Image hyperstack. - - - - Image intensity of the real part. - - - - - - - - - - - Image intensity of the imaginary part. - - - - - - - - - - - Magnitude of the image intensity. - - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along k direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along j direction. - - - - - - - Coordinate along j direction. - - - - - - Pixel coordinate center along i direction. - - - - - - - Coordinate along i direction. - - - - - diff --git a/contributed_definitions/NXimage_r_set.nxdl.xml b/contributed_definitions/NXimage_r_set.nxdl.xml deleted file mode 100644 index 3ef371809..000000000 --- a/contributed_definitions/NXimage_r_set.nxdl.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - Number of images in the stack. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - - - Specialized base class container for reporting a set of images in real space. - - - - - Image (stack). - - - - Image intensity values. - - - - - - - - - - Image identifier - - - - - - - Image identifier. - - - - - - Pixel coordinate center along y direction. - - - - - - - Coordinate along y direction. - - - - - - Pixel coordinate center along x direction. - - - - - - - Coordinate along x direction. - - - - - diff --git a/contributed_definitions/NXimage_r_set_diff.nxdl.xml b/contributed_definitions/NXimage_r_set_diff.nxdl.xml deleted file mode 100644 index 33a4eeb65..000000000 --- a/contributed_definitions/NXimage_r_set_diff.nxdl.xml +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - Number of scanned points. Scan point may have none, one, or more pattern. - - - - - Number of diffraction pattern. - - - - - Number of pixel per pattern in the slow direction. - - - - - Number of pixel per pattern in the fast direction. - - - - - Base class specialized for reporting a cuboidal stack of diffraction pattern. - - Diffraction pattern, whether they were simulated or measured are the raw data - for computational workflows to characterize the phase and orientation - of crystalline regions in matter. - - Steps of post-processing the diffraction patterns should be documented using - method-specific specialized base classes. All eventual post-processing of - resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. - - To implement an example how this base class can be used we focused in FAIRmat - on Kikuchi diffraction pattern here specifically the research community - of Electron Backscatter Diffraction (EBSD). - - For this reason, this base class and the :ref:`NXem_ebsd` base class extend the - work of `M. A. Jackson et al. <https://doi.org/10.1186/2193-9772-3-4>`_ - (one of the developers of DREAM.3D) and the H5OINA public file format developed by - `P. Pinard et al. <https://doi.org/10.1017/S1431927621006103>`_ with Oxford Instruments. - - Kikuchi pattern are typically collected with FIB/SEM microscopes, - for two- and three-dimensional orientation microscopy. - - For a detailed overview of these techniques see e.g. - - * `M. A. Groeber et al. <https://doi.org/10.1186/2193-9772-3-5>`_ - * `A. J. Schwartz et al. <https://doi.org/10.1007/978-1-4757-3205-4>`_ - * `P. A. Rottman et al. <https://doi.org/10.1016/j.mattod.2021.05.003>`_ - - Serial-sectioning demands a recurrent sequence of ion milling and measuring. - This suggests that each serial section is at least an own NXevent_data_em - instance. The three-dimensional characterization as such demands a computational - step where the maps for each serial section get cleaned, aligned, and registered - into an image stack. This image stack represents a digital model of the - inspected microstructural volume. Often this volume is called a (representative) - volume element (RVE). Several software packages exists for performing - these post-processing tasks. - - This example may inspire users of other types of diffraction methods. - - - - Category which type of diffraction pattern is reported. - - - - - - - - Collected diffraction pattern as an image stack. As raw and closest to the - first retrievable measured data as possible, i.e. do not use this - container to store already averaged, filtered or whatever post-processed - pattern unless these are generated unmodifiably in such manner by the - instrument given the way how the instrument and control software - was configured for your microscope session. - - - - Array which resolves the scan point to which each pattern belongs. - - Scan points are evaluated in sequence starting from scan point zero - until scan point n_sc - 1. Evaluating the cumulated of this array - decodes which pattern in intensity belongs to which scan point. - - Take an example with three scan points: The first scan point has one - pattern, the second has three pattern, the last scan point has no - pattern. In this case the scan_point_identifier are 0, 1, 1, 1. - The length of the scan_point_identifier array is four because four - pattern were measured in total. - - In most cases usually one pattern is averaged by the detector for - some amount of time and then reported as one pattern. - - - - - - - - Intensity of the diffraction pattern. - - - - - - - - - - Pattern intensity - - - - - - - Pattern are enumerated starting from 0 to n_p - 1. - - - - - - - Pattern identifier - - - - - - - diff --git a/contributed_definitions/nyaml/NXem_adf.yaml b/contributed_definitions/nyaml/NXem_adf.yaml deleted file mode 100644 index b7011639e..000000000 --- a/contributed_definitions/nyaml/NXem_adf.yaml +++ /dev/null @@ -1,28 +0,0 @@ -category: base -doc: | - Base class method-specific for annular dark field imaging. - - In the majority of cases simple d-dimensional regular scan patterns are used - to probe a region-of-interest (ROI). Examples can be single point aka spot - measurements, line profiles, or (rectangular) surface mappings. - The latter pattern is the most frequently used. - - For now the base class provides for scans for which the settings, - binning, and energy resolution is the same for each scan point. -symbols: - n_images: | - Number of images in the stack. - n_y: | - Number of pixel per image in the slow direction. - n_x: | - Number of pixel per image in the fast direction. -type: group -NXem_adf(NXem_method): - IMAGE_R_SET(NXimage_r_set): - half_angle_interval(NX_NUMBER): - doc: | - Annulus inner (first value) and outer (second value) half angle. - unit: NX_ANGLE - dim: (2,) - # all information about annular dark field images is composed from - # the NXimage_r_set_em base class diff --git a/contributed_definitions/nyaml/NXem_eds.yaml b/contributed_definitions/nyaml/NXem_eds.yaml deleted file mode 100644 index 9a5a97fcd..000000000 --- a/contributed_definitions/nyaml/NXem_eds.yaml +++ /dev/null @@ -1,80 +0,0 @@ -category: base -doc: | - Base class method-specific for energy-dispersive X-ray spectroscopy (EDS/EDX). - - `IUPAC instead of Siegbahn notation `_ should be used. - -# NEW ISSUE: use computational geometry to offer arbitrary scan pattern -# NEW ISSUE: make the binning flexible per scan point -symbols: - # n_p: Number of scan points - n_y: | - Number of pixel along the y direction, the slow direction - n_x: | - Number of pixel along the x direction, the fast direction - n_photon_energy: | - Number of X-ray photon energy (bins), the fastest direction. - n_elements: | - Number of identified elements - n_peaks: | - Number of peaks detected -type: group -NXem_eds(NXem_method): - # NXprocess is composed from NXem_method base class - # SPECTRUM_SET(NXspectrum_set) is composed from NXem_method base class - # for post-processing of/with the above-defined data entries - # including feedback from Christoph Pauly (from MX Uni Saarland, NFDI-MatWerk), - # Sabine Bergmann and Sebastian Brückner (both from FAIRmat, IKZ), - # and Adrien Teutrie, Cecile Hebert (EPFL) - indexing(NXprocess): - doc: | - Details about computational steps how peaks were indexed as elements. - (NXprogram): - doc: | - The program with which the indexing was performed. - PEAK(NXpeak): - doc: | - Name and location of each X-ray line which was indexed as a known ion. - For each ion, an NXion instance should be created which specifies - the origin of the signal. For each ion also the relevant IUPAC notation - X-ray lines should be specified. - (NXion): - energy_range(NX_NUMBER): - doc: | - Associated lower :math:`[e_{min}, e_{max}]` bounds of the - energy which is assumed associated with this peak. - unit: NX_ENERGY - dim: (2,) - energy(NX_NUMBER): - doc: | - Theoretical energy of the line according to IUPAC. - unit: NX_ENERGY - iupac_line_names(NX_CHAR): - doc: | - IUPAC notation identifier of the line which the peak represents. - - This can be a list of IUPAC notations for (the seldom) case that - multiple lines are grouped with the same peak. - dim: (i,) - element_names(NX_CHAR): - doc: | - List of the names of identified elements. - dim: (n_elements,) - IMAGE_R_SET(NXimage_r_set): - doc: | - Individual element-specific EDS/EDX/EDXS/SXES mapping - - A composition map is an image whose intensities for each pixel are the - accumulated X-ray quanta *under the curve(s)* of a set of peaks. - - These element-specific EDS maps are NXimage_r_set instances - and need to be named with the name of the element from the - element_names field. - (NXprocess): - peaks(NX_CHAR): - doc: | - A list of NXpeak instance names whose X-ray quanta - where accumulated for each pixel which yields an element-specific - EDS map. - dim: (n_peaks,) - # everything else is composed from NXimage_r_set diff --git a/contributed_definitions/nyaml/NXem_img.yaml b/contributed_definitions/nyaml/NXem_img.yaml index 8c257d121..57f920244 100644 --- a/contributed_definitions/nyaml/NXem_img.yaml +++ b/contributed_definitions/nyaml/NXem_img.yaml @@ -22,4 +22,3 @@ NXem_img(NXem_method): doc: | Which imaging mode was used? enumeration: [secondary_electron, backscattered_electron] - IMAGE_R_SET(NXimage_r_set): diff --git a/contributed_definitions/nyaml/NXem_method.yaml b/contributed_definitions/nyaml/NXem_method.yaml deleted file mode 100644 index afe91de97..000000000 --- a/contributed_definitions/nyaml/NXem_method.yaml +++ /dev/null @@ -1,21 +0,0 @@ -category: base -doc: | - Base class to describe specific analysis methods in electron microscopy. - - This base class represent a template how specialized, deep, and method-specific - base classes can be defined with which an (NXem) application - definition gets equipped with specific groups to document method-specific - processing steps and report analyzed quantities. - - The template base class name :ref:`NXem_method` needs to be changed for each - method e.g. :ref:`NXem_adf`, :ref:`NXem_ebsd`, :ref:`NXem_eels`, :ref:`NXem_eds`. -# :ref:`NXem_se`, :ref:`NXem_bse`. -type: group -NXem_method(NXobject): - (NXprocess): - doc: | - Details about processing steps. - sequence_index(NX_INT): - IMAGE_R_SET(NXimage_r_set): - IMAGE_C_SET(NXimage_c_set): - SPECTRUM_SET(NXspectrum_set): diff --git a/contributed_definitions/nyaml/NXem_sim.yaml b/contributed_definitions/nyaml/NXem_sim.yaml index 81fe20db1..38492d66e 100644 --- a/contributed_definitions/nyaml/NXem_sim.yaml +++ b/contributed_definitions/nyaml/NXem_sim.yaml @@ -31,4 +31,3 @@ NXem_sim(NXem_method): # sequence_index(N): (NXprogram): (NXcg_geodesic_mesh): - (NXimage_r_set_diff): diff --git a/contributed_definitions/nyaml/NXimage_c_set.yaml b/contributed_definitions/nyaml/NXimage_c_set.yaml deleted file mode 100644 index 8dcd85706..000000000 --- a/contributed_definitions/nyaml/NXimage_c_set.yaml +++ /dev/null @@ -1,140 +0,0 @@ -category: base -doc: | - Specialized base class container for reporting a set of images in reciprocal space. - - In practice, complex numbers are encoded via some formatted pair of real values. - Typically, fast Algorithms for computing Fourier Transformations (FFT) are - used to encode images in reciprocal (frequency) space. FFT libraries are used - for implementing the key functionalities of these mathematical operations. - - Different libraries use different representations and encoding of the - image computed. Details can be found in the respective sections of the - typical FFT libraries: - - * `FFTW by M. Frigo and S. G. Johnson `_ - * `Intel MKL by the Intel Co. `_ - * `cuFFT by the NVidia Co. `_ - - Users are strongly advised to inspect carefully which specific conventions - their library uses to be able to store and modify the implementation of their - code so that the serialized representations as it is detailed - here for NeXus matches with their intention. - - One- and two-dimensional FFTs should use the stack(NXdata) instances. - Three-dimensional FFTs should use the hyperstack(NXdata) instances. -symbols: - n_images: | - Number of images in the (hyper)stack. - n_k: | - Number of pixel per image in the slowest direction. - n_j: | - Number of pixel per image in the slow direction. - n_i: | - Number of pixel per image in the fast direction. -type: group -NXimage_c_set(NXimage_set): - # details about the FFT library used could for instance be stored in the - # NXprocess group which the NXimage_c_set base class can borrow from its - # NXimage_set parent base class - # process information are composable from the NXimage_set base class - stack(NXdata): - doc: | - Image stack. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_images, n_j, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_images, n_j, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_images, n_j, n_i) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - # axis_k(NX_NUMBER): - # doc: | - # Pixel coordinate center along k direction. - # unit: NX_ANY # NX_RECIPROCAL_LENGTH - # dim: (n_k,) - # \@long_name(NX_CHAR): - # doc: | - # Coordinate along j direction. - axis_j(NX_NUMBER): - doc: | - Pixel coordinate center along j direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_j,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. - - hyperstack(NXdata): - doc: | - Image hyperstack. - real(NX_NUMBER): - doc: | - Image intensity of the real part. - unit: NX_UNITLESS - dim: (n_images, n_k, n_j, n_i) - imag(NX_NUMBER): - doc: | - Image intensity of the imaginary part. - unit: NX_UNITLESS - dim: (n_images, n_k, n_j, n_i) - magnitude(NX_NUMBER): - doc: | - Magnitude of the image intensity. - unit: NX_UNITLESS - dim: (n_images, n_k, n_j, n_i) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_k(NX_NUMBER): - doc: | - Pixel coordinate center along k direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_k,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_j(NX_NUMBER): - doc: | - Pixel coordinate center along j direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_j,) - \@long_name(NX_CHAR): - doc: | - Coordinate along j direction. - axis_i(NX_NUMBER): - doc: | - Pixel coordinate center along i direction. - unit: NX_ANY # NX_RECIPROCAL_LENGTH - dim: (n_i,) - \@long_name(NX_CHAR): - doc: | - Coordinate along i direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set.yaml b/contributed_definitions/nyaml/NXimage_r_set.yaml deleted file mode 100644 index f0437e6e6..000000000 --- a/contributed_definitions/nyaml/NXimage_r_set.yaml +++ /dev/null @@ -1,45 +0,0 @@ -category: base -doc: | - Specialized base class container for reporting a set of images in real space. -symbols: - n_images: | - Number of images in the stack. - n_y: | - Number of pixel per image in the slow direction. - n_x: | - Number of pixel per image in the fast direction. -type: group -NXimage_r_set(NXimage_set): - # process information are composable from the NXimage_set base class - stack(NXdata): - doc: | - Image (stack). - intensity(NX_NUMBER): - doc: | - Image intensity values. - unit: NX_UNITLESS - dim: (n_images, n_y, n_x) - axis_image_identifier(NX_INT): - doc: | - Image identifier - unit: NX_UNITLESS - dim: (n_images,) - \@long_name(NX_CHAR): - doc: | - Image identifier. - axis_y(NX_NUMBER): - doc: | - Pixel coordinate center along y direction. - unit: NX_LENGTH - dim: (n_y,) - \@long_name(NX_CHAR): - doc: | - Coordinate along y direction. - axis_x(NX_NUMBER): - doc: | - Pixel coordinate center along x direction. - unit: NX_LENGTH - dim: (n_x,) - \@long_name(NX_CHAR): - doc: | - Coordinate along x direction. diff --git a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml b/contributed_definitions/nyaml/NXimage_r_set_diff.yaml deleted file mode 100644 index 5a0e27e28..000000000 --- a/contributed_definitions/nyaml/NXimage_r_set_diff.yaml +++ /dev/null @@ -1,123 +0,0 @@ -category: base -doc: | - Base class specialized for reporting a cuboidal stack of diffraction pattern. - - Diffraction pattern, whether they were simulated or measured are the raw data - for computational workflows to characterize the phase and orientation - of crystalline regions in matter. - - Steps of post-processing the diffraction patterns should be documented using - method-specific specialized base classes. All eventual post-processing of - resulting orientation maps (2D or 3D) should be documented via :ref:`NXms_recon`. - - To implement an example how this base class can be used we focused in FAIRmat - on Kikuchi diffraction pattern here specifically the research community - of Electron Backscatter Diffraction (EBSD). - - For this reason, this base class and the :ref:`NXem_ebsd` base class extend the - work of `M. A. Jackson et al. `_ - (one of the developers of DREAM.3D) and the H5OINA public file format developed by - `P. Pinard et al. `_ with Oxford Instruments. - - Kikuchi pattern are typically collected with FIB/SEM microscopes, - for two- and three-dimensional orientation microscopy. - - For a detailed overview of these techniques see e.g. - - * `M. A. Groeber et al. `_ - * `A. J. Schwartz et al. `_ - * `P. A. Rottman et al. `_ - - Serial-sectioning demands a recurrent sequence of ion milling and measuring. - This suggests that each serial section is at least an own NXevent_data_em - instance. The three-dimensional characterization as such demands a computational - step where the maps for each serial section get cleaned, aligned, and registered - into an image stack. This image stack represents a digital model of the - inspected microstructural volume. Often this volume is called a (representative) - volume element (RVE). Several software packages exists for performing - these post-processing tasks. - - This example may inspire users of other types of diffraction methods. -symbols: - n_sc: | - Number of scanned points. Scan point may have none, one, or more pattern. - n_p: | - Number of diffraction pattern. - n_y: | - Number of pixel per pattern in the slow direction. - n_x: | - Number of pixel per pattern in the fast direction. -type: group -NXimage_r_set_diff(NXimage_r_set): - pattern_type(NX_CHAR): - doc: | - Category which type of diffraction pattern is reported. - enumeration: [kikuchi] - stack(NXdata): - doc: | - Collected diffraction pattern as an image stack. As raw and closest to the - first retrievable measured data as possible, i.e. do not use this - container to store already averaged, filtered or whatever post-processed - pattern unless these are generated unmodifiably in such manner by the - instrument given the way how the instrument and control software - was configured for your microscope session. - scan_point_identifier(NX_INT): - doc: | - Array which resolves the scan point to which each pattern belongs. - - Scan points are evaluated in sequence starting from scan point zero - until scan point n_sc - 1. Evaluating the cumulated of this array - decodes which pattern in intensity belongs to which scan point. - - Take an example with three scan points: The first scan point has one - pattern, the second has three pattern, the last scan point has no - pattern. In this case the scan_point_identifier are 0, 1, 1, 1. - The length of the scan_point_identifier array is four because four - pattern were measured in total. - - In most cases usually one pattern is averaged by the detector for - some amount of time and then reported as one pattern. - unit: NX_UNITLESS - dim: (n_p,) - intensity(NX_NUMBER): - doc: | - Intensity of the diffraction pattern. - unit: NX_UNITLESS - dim: (n_p, n_y, n_x) - # n_p fast 2, n_y faster 1, n_x fastest 0 - # in axes fast to fastest - # while for _indices fastest to fast - \@long_name(NX_CHAR): - doc: | - Pattern intensity - # \@signal: intensity - # \@axes: [pattern_identifier, ypos, xpos] - # \@xpos_indices: 0 - # \@ypos_indices: 1 - # \@pattern_identifier_indices: 2 - pattern_identifier(NX_INT): - doc: | - Pattern are enumerated starting from 0 to n_p - 1. - unit: NX_UNITLESS - dim: (n_p,) - \@long_name(NX_CHAR): - doc: | - Pattern identifier - # the following fields are taken from the NXimage_r_set base class - # axis_y(R): - # axis_x(R): - -# If we envision a (knowledge) graph for EBSD it consists of individual sub-graphs -# which convey information about the specimen preparation, the measurement of -# the specimen in the electron microscope, the indexing of the collected -# Kikuchi pattern stack, eventual post-processing of the indexed orientation -# images via similarity grouping algorithms to yield (grains, texture). -# Conceptually, these post-processing steps are most frequently serving -# the idea how can one reconstruct so-called microstructural features -# (grains, phases, interfaces) to infer material properties. -# In practice this calls for workflows which quantify correlations between -# the spatial arrangement of the microstructural features, the individual -# (thermodynamic, chemo-mechanical) properties of the features with the -# properties of materials at a coarser scale. -# With NXem and related NXms base classes we propose a covering -# and general solution how to handle such (meta)data with NeXus. From bbcd142bc612d32ceb34ad1d23b930abf5ca8d16 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 2 Jul 2024 20:31:08 +0200 Subject: [PATCH 042/136] Cleaned obsolete and circuit contributed base classes which are not meaty enough # Conflicts: # contributed_definitions/NXadc.nxdl.xml # contributed_definitions/NXcircuit_board.nxdl.xml # contributed_definitions/NXdac.nxdl.xml # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/nyaml/NXcs_gpu_obj.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml index 04468b7b2..0984d318c 100644 --- a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml +++ b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml @@ -5,7 +5,7 @@ symbols: doc: | The symbols used in the schema to specify e.g. dimensions of arrays. type: group -NXcs_gpu_obj(NXobject): # NXcircuit_board ? +NXcs_gpu_obj(NXobject): name(NX_CHAR): doc: | Given name of the GPU. Users should be as specific as possible. From c382db05d29a27af9818134463992c5c40cd244a Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Wed, 3 Jul 2024 10:10:11 +0200 Subject: [PATCH 043/136] added Raman documentation # Conflicts: # contributed_definitions/NXoptical_spectroscopy.nxdl.xml # contributed_definitions/NXwaveplate.nxdl.xml # contributed_definitions/nyaml/NXoptical_spectroscopy.yaml # contributed_definitions/nyaml/NXwaveplate.yaml # manual/source/classes/contributed_definitions/ellipsometry-structure.rst --- .../NXoptical_spectroscopy.nxdl.xml | 868 ------------------ 1 file changed, 868 deletions(-) delete mode 100644 contributed_definitions/NXoptical_spectroscopy.nxdl.xml diff --git a/contributed_definitions/NXoptical_spectroscopy.nxdl.xml b/contributed_definitions/NXoptical_spectroscopy.nxdl.xml deleted file mode 100644 index be636590f..000000000 --- a/contributed_definitions/NXoptical_spectroscopy.nxdl.xml +++ /dev/null @@ -1,868 +0,0 @@ - - - - - - - - - Variables used throughout the document, e.g. dimensions or parameters. - - - - Length of the spectrum array (e.g. wavelength or energy) of the measured - data. - - - - - Number of sensors used to measure parameters that influence the sample, - such as temperature or pressure. - - - - - Number of measurements (1st dimension of measured_data array). This is - equal to the number of parameters scanned. For example, if the experiment - was performed at three different temperatures and two different pressures - N_measurements = 2*3 = 6. - - - - - Number of detection angles of the beam reflected or scattered off the - sample. - - - - - Number of angles of incidence of the incident beam. - - - - - Number of observables that are saved in a measurement. e.g. one for - intensity, reflectivity or transmittance, two for Psi and Delta etc. This - is equal to the second dimension of the data array 'measured_data' and the - number of column names. - - - - - An application definition for optical spectroscopy experiments. - - - - An application definition template for optical spectroscopy experiments. - - A general optical experiment consists of a light or excitation source, a - beam path, a sample + its stage + its environment, and a detection unit. - Examples are reflection or transmission measurements, photoluminescence, - Raman spectroscopy, ellipsometry etc. - - - - An application definition describing a general optical experiment. - - - - Version number to identify which definition of this application - definition was used for this entry/data. - - - - - URL where to find further material (documentation, examples) relevant - to the application definition. - - - - - - - - - A (globally persistent) unique identifier of the experiment. - (i) The identifier is usually defined by the facility or principle - investigator. - (ii) The identifier enables to link experiments to e.g. proposals. - - - - - An optional free-text description of the experiment. - - However, details of the experiment should be defined in the specific - fields of this application definition rather than in this experiment - description. - - - - - Specify the type of the optical experiment. - - - - - Start time of the experiment. UTC offset should be specified. - - - - - Contact information of at least the user of the instrument or the - investigator who performed this experiment. - Adding multiple users, if relevant, is recommended. - - - - Name of the user. - - - - - Name of the affiliation of the user at the point in time when the - experiment was performed. - - - - - Street address of the user's affiliation. - - - - - Email address of the user. - - - - - Author ID defined by https://orcid.org/. - - - - - Telephone number of the user. - - - - - - Properties of the experimental setup. This includes general information - about the instrument (such as model, company etc.), information about - the calibration of the instrument, elements of the beam path including - the excitation or light source and the detector unit, the sample stage - (plus the sample environment, which also includes sensors used to - monitor external conditions) and elements of the beam path. - - Meta data describing the sample should be specified in ENTRY/SAMPLE - outside of ENTRY/INSTRUMENT. - - - - The name of the instrument. - - - - The used version of the hardware if available. If not a commercial - instrument use date of completion of the hardware. - - - - - - Name of the company which build the instrument. - - - - - ISO8601 date when the instrument was constructed. - UTC offset should be specified. - - - - - - Commercial or otherwise defined given name of the program that was - used to measure the data, i.e. the software used to start and - record the measured data and/or metadata. - If home written, one can provide the actual steps in the NOTE - subfield here. - - - - - Either version with build number, commit hash, or description of a - (online) repository where the source code of the program and build - instructions can be found so that the program can be configured in - such a way that result files can be created ideally in a - deterministic manner. - - - - - Website of the software. - - - - - - Commercial or otherwise defined name of the firmware that was used - for the measurement - if available. - - - - Version and build number or commit hash of the software source code. - - - - - Website of the software. - - - - - - Was a calibration performed? If yes, when was it done? If the - calibration time is provided, it should be specified in - ENTRY/INSTRUMENT/calibration/calibration_time. - - - - - - - - - - - - The calibration data and metadata should be described in a separate NeXus file - with the link provided in 'calibration_link'. - - - - If calibtration status is 'calibration time provided', specify the - ISO8601 date when calibration was last performed before this - measurement. UTC offset should be specified. - - - - - Link to the NeXus file containing the calibration data and metadata. - - - - - - Describes an arrangement of optical or other elements, e.g. the beam - path between the light source and the sample, or between the sample - and the detector unit (including the sources and detectors - themselves). - - If a beam splitter (i.e. a device that splits the incoming beam into - two or more beams) is part of the beam path, two or more NXbeam_path - fields may be needed to fully describe the beam paths and the correct - sequence of the beam path elements. - Use as many beam paths as needed to describe the setup. - - - - - Angle(s) of the incident beam vs. the normal of the bottom reflective - (substrate) surface in the sample. - - - - - - - - - Detection angle(s) of the beam reflected or scattered off the sample - vs. the normal of the bottom reflective (substrate) surface in the - sample if not equal to the angle(s) of incidence. - - - - - - - - Sample stage, holding the sample at a specific position in X,Y,Z - (Cartesian) coordinate system and at an orientation defined - by three Euler angles (alpha, beta, gamma). - - - - Specify the type of the sample stage. - - - - - - - - - - - - If there is no motorized stage, we should at least qualify where - the beam hits the sample and in what direction the sample stands - in a free-text description, e.g. 'center of sample, long edge - parallel to the plane of incidence'. - - - - - Specify external parameters that have influenced the sample, such - as the surrounding medium, and varied parameters e.g. temperature, - pressure, pH value, optical excitation etc. - - - - Describe what was the medium above or around the sample. The - common model is built up from the substrate to the medium on the - other side. Both boundaries are assumed infinite in the model. - Here, define the name of the medium (e.g. water, air, UHV, etc.). - - - - - Array of pairs of complex refractive indices n + ik of the medium - for every measured spectral point/wavelength/energy. - Only necessary if the measurement was performed not in air, or - something very well known, e.g. high purity water. - - - - - - - - - A sensor used to monitor an external condition influencing the - sample, such as temperature or pressure. It is suggested to - replace 'PARAMETER' by the type of the varied parameter defined - in 'parameter_type'. - The measured parameter values should be provided in 'values'. - For each parameter, a 'PARAMETER(NXsensor)' field needs to exist. - In other words, there are N_sensors 'PARAMETER(NXsensor)' fields. - - - - Indicates which parameter was changed. Its definition must exist - below. The specified variable has to be N_measurements long, - providing the parameters for each data set. If you vary more than - one parameter simultaneously. - If the measured parameter is not contained in the list `other` - should be specified and the `parameter_type_name` should be provided. - - - - - - - - - - - - - - - - - - - - - - - - - If the parameter_type is `other` a name should be specified here. - - - - - Number of different parameter values at which the measurement - was performed. For example, if the measurement was performed at - temperatures of 4, 77 and 300 K, then number_of_parameters = 3. - - - - - Vector containing the values of the varied parameter. Its - length is equal to N_measurements. The order of the values - should be as follows: - - * Order the sensors according to number_of_parameters starting - with the lowest number. If number_of_parameters is equal for - two sensors order them alphabetically (sensor/parameter name). - * The first sensor's j parameters should be ordered in the - following way. The first N_measurements/number_of_parameters - entries of the vector contain the first parameter (a1), the - second N_measurements/number_of_parameters contain the second - parameter (a2) etc., so the vector looks like: - [ - a1,a1,...,a1, - a2,a2,...,a2, - ... - aj,aj,...aj - ] - * The kth sensor's m parameters should be ordered in the - following way: - [ - p1,...p1,p2,...,p2,...pm,...,pm, - p1,...p1,p2,...,p2,...pm,...,pm, - ... - p1,...p1,p2,...,p2,...pm,...,pm - ] - * The last sensor's n parameters should be ordered in the - following way: - [ - z1,z2,...,zn, - z1,z2,...,zn, - ... - z1,z2,...,zn] - - For example, if the experiment was performed at three different - temperatures (T1, T2, T3), two different pressures (p1, p2) and - two different angles of incidence (a1, a2), then - N_measurements = 12 and the order of the values for the various - parameter vectors is: - - * angle_of_incidence: [a1,a1,a1,a1,a1,a1,a2,a2,a2,a2,a2,a2] - * pressure: [p1,p1,p1,p2,p2,p2,p1,p1,p1,p2,p2,p2] - * temperature: [T1,T2,T3,T1,T2,T3,T1,T2,T3,T1,T2,T3] - - - - - - - - - - For environmental measurements, the environment (liquid, vapor - etc.) is enclosed in a cell, which has windows both in the - direction of the source (entry window) and the detector (exit - window) (looking from the sample). In case that the entry and exit - windows are not the same type and do not have the same properties, - use a second 'WINDOW(MXaperture)' field. - - The windows also add a phase shift to the light altering the - measured signal. This shift has to be corrected based on measuring - a known sample (reference sample) or the actual sample of interest - in the environmental cell. State if a window correction has been - performed in 'window_effects_corrected'. Reference data should be - considered as a separate experiment, and a link to the NeXus file - should be added in reference_data_link in measured_data. - - The window is considered to be a part of the sample stage but also - beam path. Hence, its position within the beam path should be - defined by the 'depends_on' field. - - - - Specify the position of the window in the beam path by pointing - to the preceding element in the sequence of beam path elements. - - - - - Was a window correction performed? If 'True' describe the window - correction procedure in 'window_correction/procedure'. - - - - - Was a window correction performed? If 'True' describe the - window correction procedure in '' - - - - Describe when (before or after the main measurement + time - stamp in 'date') and how the window effects have been - corrected, i.e. either mathematically or by performing a - reference measurement. In the latter case, provide the link to - to the reference data in 'reference_data_link'. - - - - - Link to the NeXus file which describes the reference data if a - reference measurement for window correction was performed. - Ideally, the reference measurement was performed on a reference - sample and on the same sample, and using the same conditions as - for the actual measurement with and without windows. It should - have been conducted as close in time to the actual measurement - as possible. - - - - - - The material of the window. - - - - - - - - - - - - - - - If you specified 'other' as material, decsribe here what it is. - - - - - Thickness of the window. - - - - - Angle of the window normal (outer) vs. the substrate normal - (similar to the angle of incidence). - - - - - - - - Properties of the sample, such as sample type, layer structure, - chemical formula, atom types, its history etc. - Information about the sample stage and sample environment should be - described in ENTRY/INSTRUMENT/sample_stage. - - - - Descriptive name of the sample - - - - - Specify the type of sample, e.g. thin film, single crystal etc. - - - - - - - - - - - - Qualitative description of the layer structure for the sample, - starting with the top layer (i.e. the one on the front surface, on - which the light incident), e.g. native oxide/bulk substrate, or - Si/native oxide/thermal oxide/polymer/peptide. - - - - - Chemical formula of the sample. Use the Hill system (explained here: - https://en.wikipedia.org/wiki/Chemical_formula#Hill_system) to write - the chemical formula. In case the sample consists of several layers, - this should be a list of the chemical formulas of the individual - layers, where the first entry is the chemical formula of the top - layer (the one on the front surface, on which the light incident). - The order must be consistent with layer_structure - - - - - List of comma-separated elements from the periodic table that are - contained in the sample. If the sample substance has multiple - components, all elements from each component must be included in - 'atom_types'. - - - - - Ideally, a reference to the location or a unique (globally - persistent) identifier (e.g.) of e.g. another file which gives - as many as possible details of the material, its microstructure, - and its thermo-chemo-mechanical processing/preparation history. - In the case that such a detailed history of the sample is not - available, use this field as a free-text description to specify - details of the sample and its preparation. - - - - - ISO8601 date with time zone (UTC offset) specified. - - - - - Description of the substrate. - - - - - Specify the sample orientation. - - - - - - Measured data, data errors, and varied parameters. If reference data - were measured they should be considered a separate experiment and a - link to its NeXus file should be added in reference_data_link. - - - - An identifier to correlate data to the experimental conditions, - if several were used in this measurement; typically an index of 0-N. - - - - - Select which type of data was recorded, for example intensity, - reflectivity, transmittance, Psi and Delta etc. - It is possible to have multiple selections. The enumeration list - depends on the type of experiment and may differ for different - application definitions. - - - - - - - - - - - - - - - - - Spectral values (e.g. wavelength or energy) used for the measurement. - An array of 1 or more elements. Length defines N_spectrum. Replace - 'SPECTRUM' by the physical quantity that is used, e.g. wavelength. - - - - - - - If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. - If the unit of the measured data is not covered by NXDL units state - here which unit was used. - - - - - - Resulting data from the measurement, described by 'data_type'. - - The first dimension is defined by the number of measurements taken, - (N_measurements). The instructions on how to order the values - contained in the parameter vectors given in the doc string of - INSTRUMENT/sample_stage/environment_conditions/PARAMETER/values, - define the N_measurements parameter sets. For example, if the - experiment was performed at three different temperatures - (T1, T2, T3), two different pressures (p1, p2) and two different - angles of incidence (a1, a2), the first measurement was taken at the - parameters {a1,p1,T1}, the second measurement at {a1,p1,T2} etc. - - - - - - - - - If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. - If the unit of the measured data is not covered by NXDL units state - here which unit was used. - - - - - - Specified uncertainties (errors) of the data described by 'data_type' - and provided in 'measured_data'. - - - - - - - - - If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. - If the unit of the measured data is not covered by NXDL units state - here which unit was used. - - - - - - List of links to the values of the sensors. Add a link for each - varied parameter (i.e. for each sensor). - - - - - - - - Link to the NeXus file which describes the reference data if a - reference measurement was performed. Ideally, the reference - measurement was performed using the same conditions as the actual - measurement and should be as close in time to the actual measurement - as possible. - - - - - - Commercial or otherwise defined given name of the program that was - used to generate the result file(s) with measured data and/or - metadata (in most cases, this is the same as INSTRUMENT/software). - If home written, one can provide the actual steps in the NOTE - subfield here. - - - - - Either version with build number, commit hash, or description of a - (online) repository where the source code of the program and build - instructions can be found so that the program can be configured in - such a way that result files can be created ideally in a - deterministic manner. - - - - - Website of the software. - - - - - - A plot of the multi-dimensional data array provided in - ENTRY/data/measured_data. - - - - Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) - - - - - - - Parameters that are derived from the measured data. - - - - Light loss due to depolarization as a value in [0-1]. - - - - - - - - - - Jones quality factor. - - - - - - - - - - Reflectivity. - - - - - - - - - - Transmittance. - - - - - - - - - - - Commercial or otherwise defined given name of the program that was - used to generate or calculate the derived parameters. - If home written, one can provide the actual steps in the NOTE - subfield here. - - - - - Either version with build number, commit hash, or description of a - (online) repository where the source code of the program and build - instructions can be found so that the program can be configured in - such a way that result files can be created ideally in a - deterministic manner. - - - - - - - A default view of the data provided in ENTRY/data_collection/measured_data. This - should be the part of the data set which provides the most suitable - representation of the data. - - - - Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) - - - - - From 0e296e7dae11a5cd5d674d7b8ae12a142f72235c Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 4 Jul 2024 16:10:04 +0200 Subject: [PATCH 044/136] Refactoring of base class umbrella for description of a computer based on feedback from @RubelMozumder, @lukaspie, as well as @sanbrock # Conflicts: # contributed_definitions/NXcs_computer.nxdl.xml # contributed_definitions/NXcs_cpu.nxdl.xml # contributed_definitions/NXcs_cpu_obj.nxdl.xml # contributed_definitions/NXcs_cpu_sys.nxdl.xml # contributed_definitions/NXcs_gpu.nxdl.xml # contributed_definitions/NXcs_gpu_obj.nxdl.xml # contributed_definitions/NXcs_gpu_sys.nxdl.xml # contributed_definitions/NXcs_io_obj.nxdl.xml # contributed_definitions/NXcs_io_sys.nxdl.xml # contributed_definitions/NXcs_mm_obj.nxdl.xml # contributed_definitions/NXcs_mm_sys.nxdl.xml # contributed_definitions/nyaml/NXcs_computer.yaml # contributed_definitions/nyaml/NXcs_cpu_obj.yaml # contributed_definitions/nyaml/NXcs_gpu_obj.yaml # contributed_definitions/nyaml/NXcs_mm_obj.yaml # contributed_definitions/nyaml/NXms_score_results.yaml # manual/source/classes/contributed_definitions/cgms-structure.rst --- contributed_definitions/NXcs_cpu_obj.nxdl.xml | 39 -------------- contributed_definitions/NXcs_cpu_sys.nxdl.xml | 48 ----------------- contributed_definitions/NXcs_gpu_obj.nxdl.xml | 39 -------------- contributed_definitions/NXcs_gpu_sys.nxdl.xml | 47 ----------------- contributed_definitions/NXcs_mm_obj.nxdl.xml | 51 ------------------- .../NXms_score_results.nxdl.xml | 33 ------------ .../nyaml/NXcs_cpu_obj.yaml | 12 ----- .../nyaml/NXcs_cpu_sys.yaml | 21 -------- .../nyaml/NXcs_gpu_obj.yaml | 12 ----- .../nyaml/NXcs_gpu_sys.yaml | 20 -------- .../nyaml/NXcs_mm_obj.yaml | 21 -------- 11 files changed, 343 deletions(-) delete mode 100644 contributed_definitions/NXcs_cpu_obj.nxdl.xml delete mode 100644 contributed_definitions/NXcs_cpu_sys.nxdl.xml delete mode 100644 contributed_definitions/NXcs_gpu_obj.nxdl.xml delete mode 100644 contributed_definitions/NXcs_gpu_sys.nxdl.xml delete mode 100644 contributed_definitions/NXcs_mm_obj.nxdl.xml delete mode 100644 contributed_definitions/nyaml/NXcs_cpu_obj.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_cpu_sys.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_gpu_obj.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_gpu_sys.yaml delete mode 100644 contributed_definitions/nyaml/NXcs_mm_obj.yaml diff --git a/contributed_definitions/NXcs_cpu_obj.nxdl.xml b/contributed_definitions/NXcs_cpu_obj.nxdl.xml deleted file mode 100644 index 6ce5370a3..000000000 --- a/contributed_definitions/NXcs_cpu_obj.nxdl.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a (central) processing unit (C)PU of a computer. - - - - Given name of the CPU. Users should be as specific as possible. - - - - diff --git a/contributed_definitions/NXcs_cpu_sys.nxdl.xml b/contributed_definitions/NXcs_cpu_sys.nxdl.xml deleted file mode 100644 index 0de162c66..000000000 --- a/contributed_definitions/NXcs_cpu_sys.nxdl.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a system of classical central processing units. - - For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. - - - - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single CPU one - could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of - :ref:`NXcs_cpu_sys`. - A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` - inside one instance of :ref:`NXcs_cpu_sys`. - A server with two dual-socket server nodes one could describe - with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. - - - diff --git a/contributed_definitions/NXcs_gpu_obj.nxdl.xml b/contributed_definitions/NXcs_gpu_obj.nxdl.xml deleted file mode 100644 index 3c5b6c26a..000000000 --- a/contributed_definitions/NXcs_gpu_obj.nxdl.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a graphic processing unit (GPU) of a computer. - - - - Given name of the GPU. Users should be as specific as possible. - - - - diff --git a/contributed_definitions/NXcs_gpu_sys.nxdl.xml b/contributed_definitions/NXcs_gpu_sys.nxdl.xml deleted file mode 100644 index 217f1adb2..000000000 --- a/contributed_definitions/NXcs_gpu_sys.nxdl.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a system of coprocessor or graphics processors. - - - - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single GPU one - could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of - :ref:`NXcs_gpu_sys`. - A desktop computer with two GPUs one could describe using two instances - of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. - A GPU server like nowadays used for artificial intelligence - one could describe as a system with n instances of :ref:`NXcs_gpu_obj` - in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. - - - diff --git a/contributed_definitions/NXcs_mm_obj.nxdl.xml b/contributed_definitions/NXcs_mm_obj.nxdl.xml deleted file mode 100644 index e2b247079..000000000 --- a/contributed_definitions/NXcs_mm_obj.nxdl.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Computer science description of a memory in a memory system. - - - - Qualifier for the type of random access memory. - - - - - - Total amount of data which the medium can hold. - - - - - - Given name to the I/O unit. - - - - diff --git a/contributed_definitions/NXms_score_results.nxdl.xml b/contributed_definitions/NXms_score_results.nxdl.xml index 0e957612e..d029ddb58 100644 --- a/contributed_definitions/NXms_score_results.nxdl.xml +++ b/contributed_definitions/NXms_score_results.nxdl.xml @@ -652,39 +652,6 @@ electric_field(NXprocess): - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contributed_definitions/nyaml/NXcs_cpu_obj.yaml b/contributed_definitions/nyaml/NXcs_cpu_obj.yaml deleted file mode 100644 index 73097d5ca..000000000 --- a/contributed_definitions/nyaml/NXcs_cpu_obj.yaml +++ /dev/null @@ -1,12 +0,0 @@ -category: base -doc: | - Computer science description of a (central) processing unit (C)PU of a computer. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_cpu_obj(NXobject): - name(NX_CHAR): - doc: | - Given name of the CPU. Users should be as specific as possible. - (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_cpu_sys.yaml b/contributed_definitions/nyaml/NXcs_cpu_sys.yaml deleted file mode 100644 index 5eaf8f0ea..000000000 --- a/contributed_definitions/nyaml/NXcs_cpu_sys.yaml +++ /dev/null @@ -1,21 +0,0 @@ -category: base -doc: | - Computer science description of a system of classical central processing units. - - For coprocessor or graphic cards use :ref:`NXcs_gpu_sys` instead. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_cpu_sys(NXobject): - cpuID(NXcs_cpu_obj): - doc: | - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single CPU one - could describe using one instance of :ref:`NXcs_cpu_obj` inside one instance of - :ref:`NXcs_cpu_sys`. - A dual-socket server one could describe using two instances of :ref:`NXcs_cpu_obj` - inside one instance of :ref:`NXcs_cpu_sys`. - A server with two dual-socket server nodes one could describe - with the above group of one :ref:`NXcs_cpu_sys` into another :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml b/contributed_definitions/nyaml/NXcs_gpu_obj.yaml deleted file mode 100644 index 0984d318c..000000000 --- a/contributed_definitions/nyaml/NXcs_gpu_obj.yaml +++ /dev/null @@ -1,12 +0,0 @@ -category: base -doc: | - Computer science description of a graphic processing unit (GPU) of a computer. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_gpu_obj(NXobject): - name(NX_CHAR): - doc: | - Given name of the GPU. Users should be as specific as possible. - (NXfabrication): diff --git a/contributed_definitions/nyaml/NXcs_gpu_sys.yaml b/contributed_definitions/nyaml/NXcs_gpu_sys.yaml deleted file mode 100644 index dee199330..000000000 --- a/contributed_definitions/nyaml/NXcs_gpu_sys.yaml +++ /dev/null @@ -1,20 +0,0 @@ -category: base -doc: | - Computer science description of a system of coprocessor or graphics processors. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_gpu_sys(NXobject): - gpuID(NXcs_gpu_obj): - doc: | - Granularizing at the socket level. - - Typical examples follow: A desktop computer with a single GPU one - could describe using one instance of :ref:`NXcs_gpu_obj` inside one instance of - :ref:`NXcs_gpu_sys`. - A desktop computer with two GPUs one could describe using two instances - of :ref:`NXcs_gpu_obj` inside one instance of :ref:`NXcs_gpu_sys`. - A GPU server like nowadays used for artificial intelligence - one could describe as a system with n instances of :ref:`NXcs_gpu_obj` - in one :ref:`NXcs_gpu_sys` or :ref:`NXcs_cpu_sys`. diff --git a/contributed_definitions/nyaml/NXcs_mm_obj.yaml b/contributed_definitions/nyaml/NXcs_mm_obj.yaml deleted file mode 100644 index d1fead8c8..000000000 --- a/contributed_definitions/nyaml/NXcs_mm_obj.yaml +++ /dev/null @@ -1,21 +0,0 @@ -category: base -doc: | - Computer science description of a memory in a memory system. -symbols: - doc: | - The symbols used in the schema to specify e.g. dimensions of arrays. -type: group -NXcs_mm_obj(NXobject): - technology(NX_CHAR): - doc: | - Qualifier for the type of random access memory. - # make an enumeration - max_physical_capacity(NX_NUMBER): - doc: | - Total amount of data which the medium can hold. - unit: NX_ANY - # NX_BIT - name(NX_CHAR): - doc: | - Given name to the I/O unit. - (NXfabrication): From b819c6df4e0f442b99338f285671b987c5756490 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 9 Jul 2024 13:18:16 +0200 Subject: [PATCH 045/136] Removed remaining references to NXms and renamed NXslip_system_set # Conflicts: # contributed_definitions/NXmicrostructure_slip_system.nxdl.xml # manual/source/classes/contributed_definitions/cgms-structure.rst --- .../NXmicrostructure_gragles_results.nxdl.xml | 38 +++++++++ .../NXmicrostructure_imm_results.nxdl.xml | 39 +++++++++ .../NXslip_system_set.nxdl.xml | 85 ------------------- .../NXmicrostructure_gragles_results.yaml | 10 +++ .../nyaml/NXmicrostructure_imm_results.yaml | 10 +++ .../nyaml/NXmicrostructure_slip_system.yaml | 46 ++++++++++ .../icme-structure.rst | 18 +++- 7 files changed, 158 insertions(+), 88 deletions(-) create mode 100644 contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml create mode 100644 contributed_definitions/NXmicrostructure_imm_results.nxdl.xml delete mode 100644 contributed_definitions/NXslip_system_set.nxdl.xml create mode 100644 contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml create mode 100644 contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml create mode 100644 contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml diff --git a/contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml b/contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml new file mode 100644 index 000000000..7b6fb5180 --- /dev/null +++ b/contributed_definitions/NXmicrostructure_gragles_results.nxdl.xml @@ -0,0 +1,38 @@ + + + + + + + Application definition for documenting results with GraGLeS. + + + + + + + + + + diff --git a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml new file mode 100644 index 000000000..8d0f83356 --- /dev/null +++ b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml @@ -0,0 +1,39 @@ + + + + + + + Application definition for documenting results obtained with the IMM structure + generator. + + + + + + + + + + diff --git a/contributed_definitions/NXslip_system_set.nxdl.xml b/contributed_definitions/NXslip_system_set.nxdl.xml deleted file mode 100644 index 8fafee2e4..000000000 --- a/contributed_definitions/NXslip_system_set.nxdl.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - The symbols used in the schema to specify e.g. dimensions of arrays. - - - - Number of slip systems. - - - - - Base class for describing a set of crystallographic slip systems. - - - - - - - - - - - - - - - - - - Array of Miller indices which describe the crystallographic plane. - - - - - - - - - - Array of Miller indices which describe the crystallographic direction. - - - - - - - - - For each slip system a marker whether the specified Miller indices - refer to the specific slip system or the set of crystallographic equivalent - slip systems of the respective family of slip systems. - - - - - - diff --git a/contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml b/contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml new file mode 100644 index 000000000..d254cf51b --- /dev/null +++ b/contributed_definitions/nyaml/NXmicrostructure_gragles_results.yaml @@ -0,0 +1,10 @@ +category: application +doc: | + Application definition for documenting results with GraGLeS. +# symbols: +type: group +NXmicrostructure_gragles_results(NXobject): + (NXentry): + definition(NX_CHAR): + enumeration: [NXmicrostructure_gragles_results] + \@version(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml b/contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml new file mode 100644 index 000000000..d35f2fda4 --- /dev/null +++ b/contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml @@ -0,0 +1,10 @@ +category: application +doc: | + Application definition for documenting results obtained with the IMM structure generator. +# symbols: +type: group +NXmicrostructure_imm_results(NXobject): + (NXentry): + definition(NX_CHAR): + enumeration: [NXmicrostructure_imm_results] + \@version(NX_CHAR): diff --git a/contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml b/contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml new file mode 100644 index 000000000..b39f082f9 --- /dev/null +++ b/contributed_definitions/nyaml/NXmicrostructure_slip_system.yaml @@ -0,0 +1,46 @@ +category: base +doc: | + Base class for describing a set of crystallographic slip systems. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. + n: | + Number of slip systems. +type: group +NXmicrostructure_slip_system(NXobject): + # number_of_objects(NX_UINT): + # identifier_offset(NX_UINT): + # identifier(NX_UINT): + lattice_type: + + # doc: Array of lattice types. + enumeration: [triclinic, monoclinic, orthorhombic, tetragonal, trigonal, hexagonal, cubic] + + # dimensions: + # rank: 1 + # dim: [[1, n]] + miller_plane(NX_NUMBER): + unit: NX_UNITLESS + doc: | + Array of Miller indices which describe the crystallographic plane. + dimensions: + rank: 2 + dim: [[1, n], [2, i]] + + # fastest changing dimension needs to be i because for instance for hexagonal hkil is needed + miller_direction(NX_NUMBER): + unit: NX_UNITLESS + doc: | + Array of Miller indices which describe the crystallographic direction. + dimensions: + rank: 2 + dim: [[1, n], [2, i]] + is_specific(NX_BOOLEAN): + unit: NX_UNITLESS + doc: | + For each slip system a marker whether the specified Miller indices + refer to the specific slip system or the set of crystallographic equivalent + slip systems of the respective family of slip systems. + dimensions: + rank: 1 + dim: [[1, n]] diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index 8c067978d..be103b403 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -23,13 +23,25 @@ The following application definitions are proposed to support the discussion on materials-engineering-specific data schemas can connect to or be mapped on concepts which are equally modellable with NeXus: - :ref:`NXms`: + :ref:`NXmicrostructure`: An application definition for arbitrary spatiotemporally resolved simulations. - :ref:`NXms_recon`: + :ref:`NXmicrostructure_recon`: A base class for documenting results of reconstructed microstructures. - :ref:`NXms_score_config`, :ref:`NXms_score_results`: + :ref:`NXmicrostructure_score_config`, :ref:`NXmicrostructure_score_results`: A specific example of an application definition for documenting the configuration and results respectively of a computer simulation with the static recrystallization cellular automata model SCORE. + + :ref:`NXmicrostructure_gragles_config`, :ref:`NXmicrostructure_gragles_results`: + A specific example of an application definition for documenting the + configuration and results respectively of a computer simulation with + the grain growth level-set-based model GraGLeS. + + :ref:`NXmicrostructure_imm_config`, :ref:`NXmicrostructure_imm_results`: + A specific example of an application definition for documenting the + configuration and results respectively of a computer simulation with + the legacy microstructure synthesizer developed at the Institut für + Metallkunde und Metallphysik in Aachen. + From 44b6f7993c898cfe4644f374959356ee1867f9db Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Tue, 9 Jul 2024 16:53:53 +0200 Subject: [PATCH 046/136] Removed NXmicrostructure_recon # Conflicts: # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXmicrostructure.nxdl.xml # contributed_definitions/NXmicrostructure_kanapy_results.nxdl.xml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXmicrostructure.yaml # contributed_definitions/nyaml/NXmicrostructure_kanapy_results.yaml --- .../classes/contributed_definitions/icme-structure.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index be103b403..1946b02c8 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -24,10 +24,7 @@ materials-engineering-specific data schemas can connect to or be mapped on concepts which are equally modellable with NeXus: :ref:`NXmicrostructure`: - An application definition for arbitrary spatiotemporally resolved simulations. - - :ref:`NXmicrostructure_recon`: - A base class for documenting results of reconstructed microstructures. + A base class for documenting a snapshot of a reconstructed microstructures. :ref:`NXmicrostructure_score_config`, :ref:`NXmicrostructure_score_results`: A specific example of an application definition for documenting the From 38c08b1f17a7603ac2958e51e7963b49de05bcb1 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 10 Jul 2024 16:06:24 +0200 Subject: [PATCH 047/136] Finalized data model for NXmicrostructure_imm # Conflicts: # contributed_definitions/NXcg_grid.nxdl.xml # contributed_definitions/NXmicrostructure.nxdl.xml # contributed_definitions/NXmicrostructure_imm_config.nxdl.xml # contributed_definitions/NXrotation_set.nxdl.xml # contributed_definitions/nyaml/NXcg_grid.yaml # contributed_definitions/nyaml/NXmicrostructure.yaml # contributed_definitions/nyaml/NXmicrostructure_imm_config.yaml # contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml --- .../NXmicrostructure_imm_results.nxdl.xml | 129 +++++++++++++++++- .../nyaml/NXmicrostructure_imm_results.yaml | 10 -- .../icme-structure.rst | 13 +- 3 files changed, 131 insertions(+), 21 deletions(-) delete mode 100644 contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml diff --git a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml index 8d0f83356..2b8d678f9 100644 --- a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml +++ b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml @@ -21,12 +21,26 @@ # # For further information, see http://www.nexusformat.org --> - + + + + Number of material points along the edge of the square- or cube-shaped domain. + + + - Application definition for documenting results obtained with the IMM structure - generator. + Application definition for the results of the legacy (micro)structure generator developed + by the Institut für Metallkunde und Metallphysik at RWTH Aachen University. + + * `N. Leuning et al. <https://doi.org/10.3390/ma14216588>`_ + * `C. Mießen <https://doi.org/10.18154/RWTH-2017-10148>`_ + * `M. Kühbach <https://doi.org/10.18154/RWTH-2018-00294>`_ + * `M. Kühbach et al. <https://github.com/mkuehbach/GraGLeS>`_ + + The tool can be used to instantiate specific configurations for two- and three-dimensional discretized microstructures. + Specifically, single-phase material that is composed of crystals, so-called (parent) grains which are tessellated into so-called sub-grains. + Grains are modelled as elongated crystals to mimic fundamental geometrical constraints of the interface network in deformed material. @@ -35,5 +49,112 @@ symbols:--> + + + + + + + Default plot showing the grid. + + + + + + + + Crystal identifier that was assigned to each material point. + + + + + + Material point barycentre coordinate along z direction. + + + + + + + Coordinate along z direction. + + + + + + Material point barycentre coordinate along y direction. + + + + + + + Coordinate along y direction. + + + + + + Material point barycentre coordinate along x direction. + + + + + + + Coordinate along x direction. + + + + + + + + + + + + + + + + + + + + + + + + + + True if the crystal is considered a sub-grain. + False if the crystal is considered a grain. + + + + + + + + Bunge-Euler angle orientation of each crystal. + + + + + + + + + Mean-field dislocation density as a measure of the stored elastic energy + content that is stored in the dislocation network of this grain and related + defects within each crystal. + + + + + + + diff --git a/contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml b/contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml deleted file mode 100644 index d35f2fda4..000000000 --- a/contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml +++ /dev/null @@ -1,10 +0,0 @@ -category: application -doc: | - Application definition for documenting results obtained with the IMM structure generator. -# symbols: -type: group -NXmicrostructure_imm_results(NXobject): - (NXentry): - definition(NX_CHAR): - enumeration: [NXmicrostructure_imm_results] - \@version(NX_CHAR): diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index 1946b02c8..1f408c18b 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -26,6 +26,12 @@ concepts which are equally modellable with NeXus: :ref:`NXmicrostructure`: A base class for documenting a snapshot of a reconstructed microstructures. + :ref:`NXmicrostructure_imm_config`, :ref:`NXmicrostructure_imm_results`: + A specific example of an application definition for documenting the + configuration and results respectively of a computer simulation with + the legacy microstructure synthesizer developed at the Institut für + Metallkunde und Metallphysik in Aachen. + :ref:`NXmicrostructure_score_config`, :ref:`NXmicrostructure_score_results`: A specific example of an application definition for documenting the configuration and results respectively of a computer simulation with @@ -35,10 +41,3 @@ concepts which are equally modellable with NeXus: A specific example of an application definition for documenting the configuration and results respectively of a computer simulation with the grain growth level-set-based model GraGLeS. - - :ref:`NXmicrostructure_imm_config`, :ref:`NXmicrostructure_imm_results`: - A specific example of an application definition for documenting the - configuration and results respectively of a computer simulation with - the legacy microstructure synthesizer developed at the Institut für - Metallkunde und Metallphysik in Aachen. - From 523e9c743c890dc632c1bfbe41287e0c7a126629 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 10 Jul 2024 16:18:19 +0200 Subject: [PATCH 048/136] Finished data model example for NXmicrostructure_kanapy # Conflicts: # contributed_definitions/NXmicrostructure_imm_config.nxdl.xml # contributed_definitions/NXmicrostructure_kanapy_results.nxdl.xml # contributed_definitions/NXrotation_set.nxdl.xml # contributed_definitions/nyaml/NXmicrostructure_imm_results.yaml # contributed_definitions/nyaml/NXmicrostructure_kanapy_results.yaml --- .../NXmicrostructure_imm_results.nxdl.xml | 30 +++++++++++++++++++ .../icme-structure.rst | 5 ++++ 2 files changed, 35 insertions(+) diff --git a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml index 2b8d678f9..90f7c7877 100644 --- a/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml +++ b/contributed_definitions/NXmicrostructure_imm_results.nxdl.xml @@ -28,6 +28,11 @@ Number of material points along the edge of the square- or cube-shaped domain. + + + Number of crystals. + + Application definition for the results of the legacy (micro)structure generator developed @@ -49,6 +54,31 @@ + + + Discouraged free-text field to add further details to the computation. + + + + + + + + + + + + + + + Programs and libraries representing the computational environment + + + + + + + diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index 1f408c18b..eb58606f6 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -32,6 +32,11 @@ concepts which are equally modellable with NeXus: the legacy microstructure synthesizer developed at the Institut für Metallkunde und Metallphysik in Aachen. + :ref:`NXmicrostructure_kanapy_results`: + A specific example of an application definition for documenting the results + of a computer simulation with the kanapy microstructure synthesizer + developed at the ICAMS in Bochum. + :ref:`NXmicrostructure_score_config`, :ref:`NXmicrostructure_score_results`: A specific example of an application definition for documenting the configuration and results respectively of a computer simulation with From 43ff83ddfd6e98f9e8a2ab6bc47cd151b0974ad4 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 11 Jul 2024 10:26:31 +0200 Subject: [PATCH 049/136] Consolidated based classes related to NXem_conventions into NXcoordinate_system_set because that is what these conventions only talk about # Conflicts: # contributed_definitions/NXcoordinate_system_set.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXem_ebsd.nxdl.xml # contributed_definitions/NXms_score_results.nxdl.xml # contributed_definitions/NXrotation_set.nxdl.xml # contributed_definitions/nyaml/NXcoordinate_system_set.yaml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_conventions.yaml # contributed_definitions/nyaml/NXem_ebsd.yaml # contributed_definitions/nyaml/NXmicrostructure_score_results.yaml # contributed_definitions/nyaml/NXrotation_set.yaml # manual/source/classes/contributed_definitions/em-structure.rst --- ...l => NXcoordinate_system_em_ebsd.nxdl.xml} | 17 +- .../NXms_score_results.nxdl.xml | 33 ++ ....yaml => NXcoordinate_system_em_ebsd.yaml} | 15 +- .../nyaml/NXem_conventions.yaml | 296 ------------------ 4 files changed, 44 insertions(+), 317 deletions(-) rename contributed_definitions/{NXem_conventions_ebsd.nxdl.xml => NXcoordinate_system_em_ebsd.nxdl.xml} (94%) rename contributed_definitions/nyaml/{NXem_conventions_ebsd.yaml => NXcoordinate_system_em_ebsd.yaml} (92%) delete mode 100644 contributed_definitions/nyaml/NXem_conventions.yaml diff --git a/contributed_definitions/NXem_conventions_ebsd.nxdl.xml b/contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml similarity index 94% rename from contributed_definitions/NXem_conventions_ebsd.nxdl.xml rename to contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml index 8a19f1e29..8c0c49ace 100644 --- a/contributed_definitions/NXem_conventions_ebsd.nxdl.xml +++ b/contributed_definitions/NXcoordinate_system_em_ebsd.nxdl.xml @@ -21,20 +21,15 @@ # # For further information, see http://www.nexusformat.org --> - - + + Base class for method-specific conventions EBSD. - This base class is expected to be used with :ref:`NXem_conventions`. - - This is the main issue which currently is not in all cases documented - and thus limits the interoperability and value of collected EBSD data. - Not communicating EBSD data with such contextual pieces of information - and the use of file formats which do not store this information is the - key unsolved problem. + Solves the key issue that currently conventions used for collecting and interpreting + EBSD data are not always explicitly communicating which limits interoperability and + reusability of EBSD data. diff --git a/contributed_definitions/NXms_score_results.nxdl.xml b/contributed_definitions/NXms_score_results.nxdl.xml index d029ddb58..0e957612e 100644 --- a/contributed_definitions/NXms_score_results.nxdl.xml +++ b/contributed_definitions/NXms_score_results.nxdl.xml @@ -652,6 +652,39 @@ electric_field(NXprocess): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml b/contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml similarity index 92% rename from contributed_definitions/nyaml/NXem_conventions_ebsd.yaml rename to contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml index 1ec180e23..37826128c 100644 --- a/contributed_definitions/nyaml/NXem_conventions_ebsd.yaml +++ b/contributed_definitions/nyaml/NXcoordinate_system_em_ebsd.yaml @@ -1,17 +1,13 @@ category: base -# symbols: doc: | Base class for method-specific conventions EBSD. - This base class is expected to be used with :ref:`NXem_conventions`. - - This is the main issue which currently is not in all cases documented - and thus limits the interoperability and value of collected EBSD data. - Not communicating EBSD data with such contextual pieces of information - and the use of file formats which do not store this information is the - key unsolved problem. + Solves the key issue that currently conventions used for collecting and interpreting + EBSD data are not always explicitly communicating which limits interoperability and + reusability of EBSD data. +# symbols: type: group -NXem_conventions_ebsd(NXem_conventions): +NXcoordinate_system_em_ebsd(NXobject): # move to the NXem_ebsd part of the NXem application definition gnomonic_projection_reference_frame(NXcoordinate_system): doc: | Details about the gnomonic projection reference frame. @@ -112,7 +108,6 @@ NXem_conventions_ebsd(NXem_conventions): For further details inspect the help button of xaxis_normalization_direction. enumeration: [undefined, north, east, south, west] - # distance_convention: # doc: | # How is the third of the three pattern centre parameter values, diff --git a/contributed_definitions/nyaml/NXem_conventions.yaml b/contributed_definitions/nyaml/NXem_conventions.yaml deleted file mode 100644 index 7835d9a65..000000000 --- a/contributed_definitions/nyaml/NXem_conventions.yaml +++ /dev/null @@ -1,296 +0,0 @@ -category: base -# symbols: -doc: | - Conventions for rotations and coordinate systems to interpret crystal orientation - and other data and results collected with electron microscopy research. - - Documenting explicitly all used conventions and coordinate systems is - the decisive context whereby many results from electron microscopy are - at all interpretable. - -# This base class provides several sets of such assumptions and conventions. -# Further base classes should be defined when specific techniques and methods -# demand further specifications or have specialized demands. NXem_conventions_ebsd -# is an example for such method-specific base class to summarize key conventions -# for Electron Backscatter Diffraction (EBSD). - -# What is could be a best practice for application definition developers -# who would like to describe an electron microscopy case where multiple -# methods and/or detectors are used. In this case one should define a -# method-specific base class like the template NXem_conventions_ebsd. -# Even though this may come at a cost of some duplicated information where -# the same physical detector is used in different ways, i.e. the signal collect -# from the detector is interpreted in a different way. -# As in most cases established types of signal and thus detectors are used -# (secondary electron, backscattered electron, etc.) one could equally use -# just one NXem_conventions base class instance in an application definition -# and use detector_reference_frame as a template. For each method and detector -# one then creates one NXprocess group named detector_reference_frame1, -# detector_reference_frame2, detector_reference_frame3, and so on and so forth -# and adds inside that NXprocess and use the depends_on field. - -# What is considered best practice in an application definition with multiple -# NXentry instances? In this case each NXentry instance should have an own -# NXspecimen instance and thus the NXem_conventions instance should be place -# inside that NXentry. This enables to group multiple experiments on multiple -# samples together without setting a constraint that in all these instances -# the conventions have to be the same. - -# However, best practice is the conventions should be expressed explicitly -# and they should whenever possible be as simple as possible and as few -# as possible to support users with understanding the content of the application -# definition. -type: group -NXem_conventions(NXobject): - # mandatory information about used or - # assumed reference frame and rotation conventions - rotation_conventions(NXobject): - doc: | - Mathematical conventions and materials-science-specific conventions - required for interpreting every collection of orientation data. - rotation_handedness(NX_CHAR): - doc: | - Convention how a positive rotation angle is defined when viewing - from the end of the rotation unit vector towards its origin, - i.e. in accordance with convention 2 of - DOI: 10.1088/0965-0393/23/8/083501. - Counter_clockwise is equivalent to a right-handed choice. - Clockwise is equivalent to a left-handed choice. - enumeration: [undefined, counter_clockwise, clockwise] - rotation_convention(NX_CHAR): - doc: | - How are rotations interpreted into an orientation - according to convention 3 of - DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, passive, active] - euler_angle_convention(NX_CHAR): - doc: | - How are Euler angles interpreted given that there are several - choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of - DOI: 10.1088/0965-0393/23/8/083501. - The most frequently used convention is ZXZ which is based on - the work of H.-J. Bunge but other conventions are possible. - enumeration: [undefined, zxz] - axis_angle_convention(NX_CHAR): - doc: | - To which angular range is the rotation angle argument of an - axis-angle pair parameterization constrained according to - convention 5 of DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, rotation_angle_on_interval_zero_to_pi] - sign_convention(NX_CHAR): - doc: | - Which sign convention is followed when converting orientations - between different parameterizations/representations according - to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, p_plus_one, p_minus_one] - processing_reference_frame(NXcoordinate_system): - doc: | - Details about eventually relevant named directions that may - give reasons for anisotropies. The classical example is cold-rolling - where one has to specify which directions (rolling, transverse, and normal) - align how with the direction of the base vectors of the sample_reference_frame. - type(NX_CHAR): - doc: | - Type of coordinate system and reference frame according to - convention 1 of DOI: 10.1088/0965-0393/23/8/083501. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of coordinate system. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Location of the origin of the processing_reference_frame. - This specifies the location Xp = 0, Yp = 0, Zp = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] - x_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. rolling direction. - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing x-axis base vector of - the processing_reference_frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. - enumeration: [undefined, north, east, south, west, in, out] - y_alias(NX_CHAR): - doc: | - Name or alias assigned to the y-axis base vector, - e.g. transverse direction. - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing y-axis base vector of - the processing_reference_frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_alias(NX_CHAR): - doc: | - Name or alias assigned to the z-axis base vector, - e.g. normal direction. - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing z-axis base vector of - the processing_reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - sample_reference_frame(NXcoordinate_system): - doc: | - Details about the sample/specimen reference frame. - type(NX_CHAR): - doc: | - Type of coordinate system and reference frame according to - convention 1 of DOI: 10.1088/0965-0393/23/8/083501. - The reference frame for the sample surface reference is used for - identifying positions on a (virtual) image which is formed by - information collected from an electron beam scanning the - sample surface. We assume the configuration is inspected by - looking towards the sample surface from a position that is - located behind the detector. - Reference DOI: 10.1016/j.matchar.2016.04.008 - The sample surface reference frame has coordinates Xs, Ys, Zs. - In three dimensions these coordinates are not necessarily - located on the surface of the sample as there are multiple - faces/sides of the sample. Most frequently though the coordinate - system here is used to define the surface which the electron - beam scans. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of the coordinate system if it is a Cartesian. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Location of the origin of the sample surface reference frame. - This specifies the location Xs = 0, Ys = 0, Zs = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] - x_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. longest edge. - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing x-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - enumeration: [undefined, north, east, south, west, in, out] - y_alias(NX_CHAR): - doc: | - Name or alias assigned to the y-axis base vector, - e.g. long edge. - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing y-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_alias(NX_CHAR): - doc: | - Name or alias assigned to the z-axis base vector, - e.g. shortest edge. - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing z-axis base vector of - the sample surface reference frame. We assume the configuration - is inspected by looking towards the sample surface from a position - that is located behind the detector. For further information consult - also the help info for the xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - detector_reference_frameID(NXcoordinate_system): - doc: | - Details about the detector reference frame for a specific detector. - \@depends_on(NX_CHAR): - doc: | - Reference to the specifically named :ref:`NXdetector` instance - for which these conventions in this :ref:`NXprocess` group apply - (e.g. /entry1/instrument/detector1). - type(NX_CHAR): - doc: | - Type of coordinate system/reference frame used for - identifying positions in detector space Xd, Yd, Zd, - according to DOI: 10.1016/j.matchar.2016.04.008. - enumeration: [undefined, cartesian] - handedness(NX_CHAR): - doc: | - Handedness of the coordinate system if it is a Cartesian. - enumeration: [right_handed, left_handed] - origin(NX_CHAR): - doc: | - Where is the origin of the detector space reference - frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. - Assume regions-of-interest in this reference frame form a - rectangle or cuboid. - Edges are interpreted by inspecting the direction of their - outer unit normals (which point either parallel or antiparallel) - along respective base vector direction of the reference frame. - enumeration: [undefined, front_top_left, front_top_right, front_bottom_right, front_bottom_left, back_top_left, back_top_right, back_bottom_right, back_bottom_left] - x_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. longest edge as some landmark on the detector. - x_direction(NX_CHAR): - doc: | - Direction of the positively pointing x-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - Different tools assume that different strategies can be used - and are perceived as differently convenient to enter - details about coordinate system definitions. In this ELN users - have to possibility to fill in what they assume is sufficient to - define the coordinate system directions unambiguously. - Software which works with this user input needs to offer parsing - capabilities which detect conflicting input and warn accordingly. - enumeration: [undefined, north, east, south, west, in, out] - y_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. long edge as some landmark on the detector. - y_direction(NX_CHAR): - doc: | - Direction of the positively pointing y-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - z_alias(NX_CHAR): - doc: | - Name or alias assigned to the x-axis base vector, - e.g. short edge as some landmark on the detector. - z_direction(NX_CHAR): - doc: | - Direction of the positively pointing z-axis base vector of - the detector space reference frame. We assume the configuration - is inspected by looking towards the sample surface from a - position that is located behind the detector. - For further information consult also the help info for the - xaxis_direction field. - enumeration: [undefined, north, east, south, west, in, out] - # conventions specific for EBSD - (NXem_conventions_ebsd): \ No newline at end of file From 9b2ed1b7db8714323e70d1936b1f2c6f7813c993 Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Thu, 11 Jul 2024 15:56:23 +0200 Subject: [PATCH 050/136] Fixed grammar issue --- .../source/classes/contributed_definitions/icme-structure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/source/classes/contributed_definitions/icme-structure.rst b/manual/source/classes/contributed_definitions/icme-structure.rst index eb58606f6..68c6f9859 100644 --- a/manual/source/classes/contributed_definitions/icme-structure.rst +++ b/manual/source/classes/contributed_definitions/icme-structure.rst @@ -24,7 +24,7 @@ materials-engineering-specific data schemas can connect to or be mapped on concepts which are equally modellable with NeXus: :ref:`NXmicrostructure`: - A base class for documenting a snapshot of a reconstructed microstructures. + A base class for documenting a snapshot of a reconstructed microstructure. :ref:`NXmicrostructure_imm_config`, :ref:`NXmicrostructure_imm_results`: A specific example of an application definition for documenting the From 52b314884a4934e762bd41dfa3b7196113a202a1 Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Tue, 13 Aug 2024 16:03:39 +0200 Subject: [PATCH 051/136] Extension of Doc for Optical spectroscopy and Raman --- manual/source/ellipsometry-structure.rst | 50 +++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/manual/source/ellipsometry-structure.rst b/manual/source/ellipsometry-structure.rst index 255c3c582..96d9e1471 100644 --- a/manual/source/ellipsometry-structure.rst +++ b/manual/source/ellipsometry-structure.rst @@ -5,9 +5,36 @@ Optical spectroscopy ==================== .. index:: + OpticalSpec1 Ellipsometry1 + Raman1 DispersiveMaterial1 +.. _OpticalSpec1: + +Optical Spectroscopy +############## + + + + +Application Definitions +----------------------- + +We created one application definition: + + :ref:`NXoptical_spectroscopy`: + A general application definition for optical spectroscopy measurements. This includes specifically: + photoluminescence + transmission spectroscopy + reflection spectroscopy + and general spectroscopy experiments + + General spectroscopy experiments refer to experiments of the type photon-in photon-out. A detector is required to measure the "photon-out"-signal. + For Ellipsomertry and Raman spectroscopy are specific application definitions listed below. + + + .. _Ellipsometry1: @@ -16,7 +43,7 @@ Ellipsometry Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. The measurements are based on determining how the polarization state of light changes upon transmission and reflection. Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. -In the application definition we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. +This application definition is an extension of :ref:`NXoptical_spectroscopy`. It provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. Application Definitions @@ -28,6 +55,27 @@ We created one application definition: A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. +.. _Raman1: + +Raman NXoptical_spectroscopy +############## + +Raman spectroscopy is an optical characterization method by measuring elastic light scattering. In this way phonon characteristics are measured for a extreme broad range of samples: gasses, liquids, solids, glasses, crystals. + +The application definition provides an extension of :ref:`NXoptical_spectroscopy` to cover required or relevant data from Raman scattering experiments. + + +Application Definitions +----------------------- + +We created one application definition: + + :ref:`NXraman`: + A general application definition for Raman measurements. + + + + Dispersive Material ################### From 47b1f36191dd97136beeae041c988f92c75ce0c1 Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Tue, 13 Aug 2024 16:30:18 +0200 Subject: [PATCH 052/136] Update webpage for optical spectroscopy --- dev_tools/docs/nxdl_index.py | 2 +- manual/source/index.rst | 2 +- ...sometry-structure.rst => optical-spectroscopy-structure.rst} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename manual/source/{ellipsometry-structure.rst => optical-spectroscopy-structure.rst} (99%) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index e5840aaeb..3d7139ca0 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -68,7 +68,7 @@ def nxdl_indices() -> Dict[str, dict]: print("---------++++++++-", section) if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}ellipsometry-structure\n") + rst_lines.append(f"{indentation}optical-spectroscopy\n") rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") diff --git a/manual/source/index.rst b/manual/source/index.rst index d2d0ee59b..a91669d02 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -14,7 +14,7 @@ https://www.nexusformat.org/ nexus-index em-structure mpes-structure - ellipsometry-structure + optical-spectroscopy apm-structure transport-structure sts-structure diff --git a/manual/source/ellipsometry-structure.rst b/manual/source/optical-spectroscopy-structure.rst similarity index 99% rename from manual/source/ellipsometry-structure.rst rename to manual/source/optical-spectroscopy-structure.rst index 96d9e1471..954c2a9ce 100644 --- a/manual/source/ellipsometry-structure.rst +++ b/manual/source/optical-spectroscopy-structure.rst @@ -57,7 +57,7 @@ We created one application definition: .. _Raman1: -Raman NXoptical_spectroscopy +Raman spectroscopy ############## Raman spectroscopy is an optical characterization method by measuring elastic light scattering. In this way phonon characteristics are measured for a extreme broad range of samples: gasses, liquids, solids, glasses, crystals. From eedbfcd6945f5aa96fba6123e76f0821d85ef860 Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Wed, 14 Aug 2024 10:26:25 +0200 Subject: [PATCH 053/136] change ellips name to optical spec --- dev_tools/docs/nxdl_index.py | 2 +- ...sometry-structure.rst => optical-spectroscopy-structure.rst} | 2 +- manual/source/index.rst | 2 +- manual/source/optical-spectroscopy-structure.rst | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename manual/source/classes/contributed_definitions/{ellipsometry-structure.rst => optical-spectroscopy-structure.rst} (99%) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index 3d7139ca0..af9997c67 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -68,7 +68,7 @@ def nxdl_indices() -> Dict[str, dict]: print("---------++++++++-", section) if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") - rst_lines.append(f"{indentation}optical-spectroscopy\n") + rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") rst_lines.append(f"{indentation}mpes-structure\n") rst_lines.append(f"{indentation}apm-structure\n") rst_lines.append(f"{indentation}transport-structure\n") diff --git a/manual/source/classes/contributed_definitions/ellipsometry-structure.rst b/manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst similarity index 99% rename from manual/source/classes/contributed_definitions/ellipsometry-structure.rst rename to manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst index 1f3ddbfaf..2944d619c 100644 --- a/manual/source/classes/contributed_definitions/ellipsometry-structure.rst +++ b/manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst @@ -1,4 +1,4 @@ -.. _Ellipsometry-Structure: +.. _Optical-Spectroscopy-Structure: ======================== Optical Spectroscopy diff --git a/manual/source/index.rst b/manual/source/index.rst index a91669d02..962b7f691 100644 --- a/manual/source/index.rst +++ b/manual/source/index.rst @@ -14,7 +14,7 @@ https://www.nexusformat.org/ nexus-index em-structure mpes-structure - optical-spectroscopy + optical-spectroscopy-structure apm-structure transport-structure sts-structure diff --git a/manual/source/optical-spectroscopy-structure.rst b/manual/source/optical-spectroscopy-structure.rst index 954c2a9ce..c5ad40f4a 100644 --- a/manual/source/optical-spectroscopy-structure.rst +++ b/manual/source/optical-spectroscopy-structure.rst @@ -1,4 +1,4 @@ -.. _Ellipsometry-Structure-Fairmat: +.. _Optical-Spectroscopy-Structure-Fairmat: ==================== Optical spectroscopy From 104c8da7e4c4b29a0a8fef18f500a7f9b2475de4 Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Mon, 26 Aug 2024 10:52:55 +0200 Subject: [PATCH 054/136] fix_renaming_of_ellipsometry_to_optical_spec --- dev_tools/docs/nxdl_index.py | 2 +- .../source/optical-spectroscopy-structure.rst | 23 +++---------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index af9997c67..e700c507a 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -163,7 +163,7 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: and acceptance as either a base class or application definition. Some contributions are grouped together: - :ref:`Optical Spectroscopy ` + :ref:`Optical Spectroscopy ` :ref:`Multi-dimensional Photoemission Spectroscopy ` diff --git a/manual/source/optical-spectroscopy-structure.rst b/manual/source/optical-spectroscopy-structure.rst index c5ad40f4a..5549890c4 100644 --- a/manual/source/optical-spectroscopy-structure.rst +++ b/manual/source/optical-spectroscopy-structure.rst @@ -4,18 +4,6 @@ Optical spectroscopy ==================== -.. index:: - OpticalSpec1 - Ellipsometry1 - Raman1 - DispersiveMaterial1 - -.. _OpticalSpec1: - -Optical Spectroscopy -############## - - Application Definitions @@ -35,11 +23,8 @@ We created one application definition: - -.. _Ellipsometry1: - Ellipsometry -############## +############ Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. The measurements are based on determining how the polarization state of light changes upon transmission and reflection. Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. @@ -51,14 +36,12 @@ Application Definitions We created one application definition: - :ref:`NXellipsometry`: - A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. + A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. -.. _Raman1: Raman spectroscopy -############## +################## Raman spectroscopy is an optical characterization method by measuring elastic light scattering. In this way phonon characteristics are measured for a extreme broad range of samples: gasses, liquids, solids, glasses, crystals. From a3c7af65e5c754a5a24b060ad5058fed4a6d62b3 Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Mon, 26 Aug 2024 11:10:13 +0200 Subject: [PATCH 055/136] add missed links --- .../source/optical-spectroscopy-structure.rst | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/manual/source/optical-spectroscopy-structure.rst b/manual/source/optical-spectroscopy-structure.rst index 5549890c4..3551f29bc 100644 --- a/manual/source/optical-spectroscopy-structure.rst +++ b/manual/source/optical-spectroscopy-structure.rst @@ -4,6 +4,18 @@ Optical spectroscopy ==================== +.. index:: + OpticalSpec1 + Ellipsometry1 + Raman1 + DispersiveMaterial1 + +.. _OpticalSpec1: + +Optical Spectroscopy +############## + + Application Definitions @@ -23,6 +35,9 @@ We created one application definition: + +.. _Ellipsometry1: + Ellipsometry ############ @@ -36,10 +51,12 @@ Application Definitions We created one application definition: - + :ref:`NXellipsometry`: A general application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. +.. _Raman1: + Raman spectroscopy ################## From 5500941862a6c46ccee1013300ffa5f41ece42cc Mon Sep 17 00:00:00 2001 From: Ron Hildebrandt Date: Mon, 26 Aug 2024 11:14:07 +0200 Subject: [PATCH 056/136] add missing #### in title... --- manual/source/optical-spectroscopy-structure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/source/optical-spectroscopy-structure.rst b/manual/source/optical-spectroscopy-structure.rst index 3551f29bc..c5d881d99 100644 --- a/manual/source/optical-spectroscopy-structure.rst +++ b/manual/source/optical-spectroscopy-structure.rst @@ -13,7 +13,7 @@ Optical spectroscopy .. _OpticalSpec1: Optical Spectroscopy -############## +#################### From e84302a4922d8390c40d8ca845f341a0ee0ca5cf Mon Sep 17 00:00:00 2001 From: mkuehbach Date: Wed, 4 Sep 2024 16:57:33 +0200 Subject: [PATCH 057/136] Merging NXem_adf into NXem_img, enabling microstructure reconstructions as dependants of specific method results, introduction of NXatom_set to discuss generalization of NXion towards enabling descriptions of groups of atoms, also to lias with FAIRmat Area C # Conflicts: # contributed_definitions/NXcs_io_obj.nxdl.xml # contributed_definitions/NXcs_io_sys.nxdl.xml # contributed_definitions/NXem.nxdl.xml # contributed_definitions/NXmicrostructure.nxdl.xml # contributed_definitions/nyaml/NXem.yaml # contributed_definitions/nyaml/NXem_eds.yaml # contributed_definitions/nyaml/NXem_method.yaml # contributed_definitions/nyaml/NXmicrostructure.yaml # manual/source/classes/contributed_definitions/em-structure.rst --- contributed_definitions/NXatom_set.nxdl.xml | 158 ++++++++++++++++++ contributed_definitions/NXem_img.nxdl.xml | 35 ++-- contributed_definitions/nyaml/NXatom_set.yaml | 104 ++++++++++++ contributed_definitions/nyaml/NXem_img.yaml | 19 ++- .../contributed_definitions/apm-structure.rst | 4 +- 5 files changed, 293 insertions(+), 27 deletions(-) create mode 100644 contributed_definitions/NXatom_set.nxdl.xml create mode 100644 contributed_definitions/nyaml/NXatom_set.yaml diff --git a/contributed_definitions/NXatom_set.nxdl.xml b/contributed_definitions/NXatom_set.nxdl.xml new file mode 100644 index 000000000..0a1e20856 --- /dev/null +++ b/contributed_definitions/NXatom_set.nxdl.xml @@ -0,0 +1,158 @@ + + + + + + + The symbols used in the schema to specify e.g. dimensions of arrays. + + + + Maximum number of atoms/isotopes allowed per (molecular) ion (fragment). + + + + + Number of mass-to-charge-state-ratio range intervals for ion type. + + + + + Base class for documenting a set of atoms. + + + + A unique identifier whereby such an ion can be referred to + via the service offered as described in identifier_type. + + + + + How can the identifier be resolved? + + + + + + + + Ion type (ion species) identifier. + + The identifier zero is reserved for the special unknown ion type. + + + + + Vector of nuclide hash values. + + Individual hash values :math:`H` is :math:`H = Z + N \cdot 256` with :math:`Z` + encode the number of protons :math:`Z` and the number of neutrons :math:`N` + of each nuclide respectively. :math:`Z` and :math:`N` have to be 8-bit unsigned integers. + + The array is sorted in decreasing order. For the rationale behind this see `M. Kühbach et al. (2021) <https://doi.org/10.1017/S1431927621012241>`_ + + + + + + + + Table which decodes the entries in nuclide_hash into a human-readable matrix of instances. + The first column specifies the nuclide mass number, i.e. using the hashvalues + from the isotope_vector this is :math:`Z + N` or 0. The value 0 documents that no + isotope-specific information about the element encoded is relevant. + The second row specifies the number of protons :math:`Z` or 0. + The value 0 in this case documents a placeholder or that no element-specific + information is relevant. + Taking a carbon-14 nuclide as an example the mass number is 14. + That is encoded as a value pair (14, 6) as one row of the table. + + Therefore, this notation is the typical superscribed nuclide mass number + and subscripted number of protons element notation e.g. :math:`^{14}C`. + The array is stored matching the order of nuclide_hash. + + + + + + + + + + Assumed volume of the ion. + + In atom probe microscopy this field can be used to store the reconstructed + volume per ion (average) which is typically stored alongside ranging + definitions. + + + + + Charge of the ion. + + + + + Signed charge state if the atoms form an ion reported in multiples of electron charge. + + In the example of atom probe microscopy, only positive values will be measured + as the ions are accelerated by a negatively signed bias electric field. + In the case that the charge state is not explicitly recoverable, the value should + be set to zero. + + In atom probe microscopy this is for example the case when using + classical ranging definition files in formats like RNG, RRNG. + These file formats do not document the charge state explicitly + but the number of atoms of each element per molecular ion + surplus the mass-to-charge-state-ratio interval. + Details on ranging definition files can be found in the literature: + `M. K. Miller <https://doi.org/10.1002/sia.1719>`_ + + + + + Human-readable name (e.g. Al +++) of the atom set, the atom group, or ion type. + The string should consists of UTF-8 characters, ideally using LaTeX + notation to specify the isotopes, ions, and charge state. + Examples are 12C + or Al +++. + + To ease automated parsing, isotope_vector should be the + preferred machine-readable information used. + + + + + Associated lower (mqmin) and upper (mqmax) bounds of the + mass-to-charge-state ratio interval(s) [mqmin, mqmax] + (boundaries inclusive). This field is primarily of interest + for documenting :ref:`NXprocess` steps of indexing a + ToF/mass-to-charge state histogram. + + + + + + + diff --git a/contributed_definitions/NXem_img.nxdl.xml b/contributed_definitions/NXem_img.nxdl.xml index 1d023c028..cbe26c4b8 100644 --- a/contributed_definitions/NXem_img.nxdl.xml +++ b/contributed_definitions/NXem_img.nxdl.xml @@ -22,23 +22,6 @@ # For further information, see http://www.nexusformat.org --> - - - - Number of images in the stack. - - - - - Number of pixel per image in the slow direction. - - - - - Number of pixel per image in the fast direction. - - - Base class for method-specific generic imaging. @@ -57,6 +40,24 @@ + + + + + + Annulus inner (first value) and outer (second value) half angle. + + + + + + + + A reconstruction of the microstructure or some of its features + based on image information in the parent class. + + + diff --git a/contributed_definitions/nyaml/NXatom_set.yaml b/contributed_definitions/nyaml/NXatom_set.yaml new file mode 100644 index 000000000..3e83a1bef --- /dev/null +++ b/contributed_definitions/nyaml/NXatom_set.yaml @@ -0,0 +1,104 @@ +category: base +doc: | + Base class for documenting a set of atoms. +symbols: + doc: | + The symbols used in the schema to specify e.g. dimensions of arrays. + n_ivec_max: | + Maximum number of atoms/isotopes allowed per (molecular) ion (fragment). + n_ranges: | + Number of mass-to-charge-state-ratio range intervals for ion type. +type: group +NXatom_set(NXobject): + identifier(NX_CHAR): + doc: | + A unique identifier whereby such an ion can be referred to + via the service offered as described in identifier_type. + identifier_type(NX_CHAR): + doc: | + How can the identifier be resolved? + enumeration: [inchi] + ion_type(NX_UINT): + doc: | + Ion type (ion species) identifier. + + The identifier zero is reserved for the special unknown ion type. + unit: NX_UNITLESS + nuclide_hash(NX_UINT): + doc: | + Vector of nuclide hash values. + + Individual hash values :math:`H` is :math:`H = Z + N \cdot 256` with :math:`Z` + encode the number of protons :math:`Z` and the number of neutrons :math:`N` + of each nuclide respectively. :math:`Z` and :math:`N` have to be 8-bit unsigned integers. + + The array is sorted in decreasing order. For the rationale behind this see `M. Kühbach et al. (2021) `_ + unit: NX_UNITLESS + dim: (n_ivec_max,) + nuclide_list(NX_UINT): + doc: | + Table which decodes the entries in nuclide_hash into a human-readable matrix of instances. + The first column specifies the nuclide mass number, i.e. using the hashvalues + from the isotope_vector this is :math:`Z + N` or 0. The value 0 documents that no + isotope-specific information about the element encoded is relevant. + The second row specifies the number of protons :math:`Z` or 0. + The value 0 in this case documents a placeholder or that no element-specific + information is relevant. + Taking a carbon-14 nuclide as an example the mass number is 14. + That is encoded as a value pair (14, 6) as one row of the table. + + Therefore, this notation is the typical superscribed nuclide mass number + and subscripted number of protons element notation e.g. :math:`^{14}C`. + The array is stored matching the order of nuclide_hash. + unit: NX_UNITLESS + dim: (n_ivecmax, 2) + # color(NX_CHAR): + # doc: | + # Color code used for visualizing such ions. + volume(NX_NUMBER): + doc: | + Assumed volume of the ion. + + In atom probe microscopy this field can be used to store the reconstructed + volume per ion (average) which is typically stored alongside ranging + definitions. + unit: NX_VOLUME + charge(NX_NUMBER): + doc: | + Charge of the ion. + unit: NX_CHARGE + charge_state(NX_NUMBER): + doc: | + Signed charge state if the atoms form an ion reported in multiples of electron charge. + + In the example of atom probe microscopy, only positive values will be measured + as the ions are accelerated by a negatively signed bias electric field. + In the case that the charge state is not explicitly recoverable, the value should + be set to zero. + + In atom probe microscopy this is for example the case when using + classical ranging definition files in formats like RNG, RRNG. + These file formats do not document the charge state explicitly + but the number of atoms of each element per molecular ion + surplus the mass-to-charge-state-ratio interval. + Details on ranging definition files can be found in the literature: + `M. K. Miller `_ + unit: NX_UNITLESS + name(NX_CHAR): + doc: | + Human-readable name (e.g. Al +++) of the atom set, the atom group, or ion type. + The string should consists of UTF-8 characters, ideally using LaTeX + notation to specify the isotopes, ions, and charge state. + Examples are 12C + or Al +++. + + To ease automated parsing, isotope_vector should be the + preferred machine-readable information used. + mass_to_charge_range(NX_NUMBER): + doc: | + Associated lower (mqmin) and upper (mqmax) bounds of the + mass-to-charge-state ratio interval(s) [mqmin, mqmax] + (boundaries inclusive). This field is primarily of interest + for documenting :ref:`NXprocess` steps of indexing a + ToF/mass-to-charge state histogram. + unit: NX_ANY # u + dim: (n_ranges, 2) diff --git a/contributed_definitions/nyaml/NXem_img.yaml b/contributed_definitions/nyaml/NXem_img.yaml index 57f920244..015e6fa7d 100644 --- a/contributed_definitions/nyaml/NXem_img.yaml +++ b/contributed_definitions/nyaml/NXem_img.yaml @@ -9,16 +9,19 @@ doc: | For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. -symbols: - n_images: | - Number of images in the stack. - n_y: | - Number of pixel per image in the slow direction. - n_x: | - Number of pixel per image in the fast direction. type: group NXem_img(NXem_method): imaging_mode(NX_CHAR): doc: | Which imaging mode was used? - enumeration: [secondary_electron, backscattered_electron] + enumeration: [secondary_electron, backscattered_electron, annular_dark_field, cathodoluminescence] + (NXimage_set): + half_angle_interval(NX_NUMBER): + doc: | + Annulus inner (first value) and outer (second value) half angle. + unit: NX_ANGLE + dim: (2,) + (NXmicrostructure): + doc: | + A reconstruction of the microstructure or some of its features + based on image information in the parent class. diff --git a/manual/source/classes/contributed_definitions/apm-structure.rst b/manual/source/classes/contributed_definitions/apm-structure.rst index ba275045c..2cbeaae4a 100644 --- a/manual/source/classes/contributed_definitions/apm-structure.rst +++ b/manual/source/classes/contributed_definitions/apm-structure.rst @@ -47,7 +47,7 @@ The following base classes are proposed to support modularizing the storage of p Base classes to describe different coordinate systems used and/or to be harmonized or transformed into one another when interpreting the dataset. - :ref:`NXion`: + :ref:`NXion`: (about to become replaced by :ref:`NXatom_set`) A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. For the usage in atom probe research the maximum number of atoms supported building a molecular ion is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with @@ -57,7 +57,7 @@ The following base classes are proposed to support modularizing the storage of p A base class to bundle manufacturer/technology-partner-specific details about a component or device of an instrument. - :ref:`NXpeak`: + :ref:`NXpeak`: (about to become complemented by NXpeak_fitting) A base class to describe peaks mathematically to detail how peaks in mass-to-charge-state ratio histograms (aka mass spectra) are defined and labelled as iontypes. From 812de23f64f569e0a4ae2336805d27d4509a1f48 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:13:17 +0200 Subject: [PATCH 058/136] various small fixes are merging main and fairmat # Conflicts: # contributed_definitions/nyaml/NXdispersive_material.yaml # dev_tools/tests/test_nxdl_utils.py # manual/source/classes/contributed_definitions/mpes-structure.rst # manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst --- .../NXdispersive_material.nxdl.xml | 11 +- .../contributed_definitions/em-structure.rst | 2 - .../mpes-structure.rst | 4 +- .../optical-spectroscopy-structure.rst | 185 ------------------ 4 files changed, 3 insertions(+), 199 deletions(-) delete mode 100644 manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst diff --git a/contributed_definitions/NXdispersive_material.nxdl.xml b/contributed_definitions/NXdispersive_material.nxdl.xml index e4e4118b6..bc70d81a8 100644 --- a/contributed_definitions/NXdispersive_material.nxdl.xml +++ b/contributed_definitions/NXdispersive_material.nxdl.xml @@ -46,15 +46,6 @@ - - Name of the program used for creating this dispersion - - - Version of the program used - - - Date and time of creating this dispersion. - @@ -231,4 +222,4 @@ - + \ No newline at end of file diff --git a/manual/source/classes/contributed_definitions/em-structure.rst b/manual/source/classes/contributed_definitions/em-structure.rst index 6f011c62f..6b9008ae8 100644 --- a/manual/source/classes/contributed_definitions/em-structure.rst +++ b/manual/source/classes/contributed_definitions/em-structure.rst @@ -112,8 +112,6 @@ The following base classes are proposed to support modularizing the storage of p :ref:`NXstage_lab`: As it was mentioned for atom probe microscopy, this is a base class to describe the stage/specimen holder which offers place for the documentation of the small-scale laboratory functionalities which modern stages of electron microscopes frequently offer. -Method-specific concepts and their usage in application definitions -################################################################### It became clear during the design of the electron-microscopy-specific additions to NeXus that there are sets of pieces of information (data and metadata) which are relevant for a given experiment but have usually only few connections to the detailed description of the workflow of processing these data into knowledge, motivating the granularization of these pieces of information in their own application definition. In fact, one limitation of application definitions in NeXus is that they define a set of constraints on their graph of controlled concepts and terms. If we take for example diffraction experiments with an electron microscope it is usually the case that (diffraction) patterns are collected in the session at the microscope but all scientifically relevant conclusions are drawn later, i.e. through post-processing these data. These numerical and algorithmic steps define computational workflows where data from the application definitions such as NXem are used as input but many additional concepts and constraints may apply without any need for changing constraints on fields or groups of NXem. If we were to modify NXem for these cases, NXem would likely combinatorially diverge as every different combination of required constraints would demand having their own but almost similar application definition. For this reason, we propose to define the following base classes: diff --git a/manual/source/classes/contributed_definitions/mpes-structure.rst b/manual/source/classes/contributed_definitions/mpes-structure.rst index df89809bf..1d37fdba6 100644 --- a/manual/source/classes/contributed_definitions/mpes-structure.rst +++ b/manual/source/classes/contributed_definitions/mpes-structure.rst @@ -1,8 +1,8 @@ .. _Mpes-Structure: -======================================= +============================================== Photoemission & core-level spectroscopy -======================================= +============================================== .. index:: IntroductionMpes diff --git a/manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst b/manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst deleted file mode 100644 index 2944d619c..000000000 --- a/manual/source/classes/contributed_definitions/optical-spectroscopy-structure.rst +++ /dev/null @@ -1,185 +0,0 @@ -.. _Optical-Spectroscopy-Structure: - -======================== -Optical Spectroscopy -======================== - -.. index:: - Ellipsometry - DispersiveMaterial - - -.. _Ellipsometry: - -Ellipsometry -############## - -Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. -The measurements are based on determining how the polarization state of light changes upon transmission and reflection. -Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. - -In the application definition we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. - - -Application Definitions ------------------------ - - :ref:`NXopt`: - A generic application definition for optical spectroscopy measurements, including complex systems up to variable angle spectroscopic ellipsometry. - - :ref:`NXellipsometry`: - An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. - - -Base Classes ------------- - -This is the set of base classes for describing an optical experiment. - - :ref:`NXbeam_path` - A beam path consisting of one or more optical elements. - - NXbeam_path is used in NXopt to describe the beam path, i.e. the arrangement - of optical elements between the excitation source and the sample, or between - the sample and the detector unit. - - :ref:`NXbeam_splitter` - A beam splitter, i.e. a device splitting the light into two or more beams. - - Use two or more NXbeam_paths to describe the beam paths after the beam - splitter. In the dependency chain of the new beam paths, the first elements - each point to this beam splitter, as this is the previous element. - - :ref:`NXfiber` - An optical fiber, e.g. glass fiber. - - :ref:`NXlens_opt` - Description of an optical lens. - - :ref:`NXpolarizer_opt` - An optical polarizer. - - :ref:`NXwaveplate` - A waveplate or retarder. - - :ref:`NXenvironment` - Specify external parameters that have influenced the sample, - such as the surrounding medium, and varied parameters e.g. - temperature, pressure, pH value, optical excitation etc. - - - -.. _DispersiveMaterial: - -Dispersive Material -################### - -A dispersive material is a description for the optical dispersion of materials. -This description may be used to store optical model data from an ellipsometric analysis -(or any other technique) or to build a database of optical constants for optical properties of materials. - -Application Definition ----------------------- - - :ref:`NXdispersive_material`: - An application definition to describe the dispersive properties of a material. - The material may be isotropic, uniaxial or biaxial. Hence, it may contain up - to three dispersive functions or tables. - - - -Base Classes ------------- - -There is a set of base classes for describing a dispersion. - - :ref:`NXdispersion` - This is an umbrella base class for a group of dispersion functions to describe the material. - For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. - If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. - This allows for, e.g. splitting real and imaginary parts and describing them seperately or - adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). - - :ref:`NXdispersion_function` - This dispersion is described by a function and its single and repeated parameter values. - It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` - (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. - - :ref:`NXdispersion_single_parameter` - This denotes a parameter which is used outside the summed part of a dispersion function, - e.g. ``eps_inf`` in the formula example above. - - :ref:`NXdispersion_repeated_parameter` - This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. - ``A`` and ``B`` are repeated parameters in the formula above. - - :ref:`NXdispersion_table` - This describes a tabular dispersion where the permittivity is an array versus wavelength or energy. - -Formula Grammar ---------------- - -Below you find a grammar to which the formula should adhere and which can be used to parse and -evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be -filled with the respective single and repeated params from the stored data. -The grammer is written in the `EBNF `_ dialect -of `Lark `_, which is a parsing toolkit for python. -It is easily translatable to general EBNF and other parser generator dialects. -`Here `_ is a reference implementation in Rust/Python with a -`grammar `_ -written in `lalrpop `_. - -.. code-block:: - - ?assignment: "eps" "=" kkr_expression -> eps - | "n" "=" kkr_expression -> n - - ?kkr_expression: expression - | "" "+" "1j" "*" term -> kkr_term - - ?expression: term - | expression "+" term -> add - | expression "-" term -> sub - - ?term: factor - | term "*" factor -> mul - | term "/" factor -> div - - ?factor: power - | power "**" power -> power - - - ?power: "(" expression ")" - | FUNC "(" expression ")" -> func - | "sum" "[" repeated_expression "]" -> sum_expr - | NAME -> single_param_name - | SIGNED_NUMBER -> number - | BUILTIN -> builtin - - ?repeated_expression: repeated_term - | repeated_expression "+" repeated_term -> add - | repeated_expression "-" repeated_term -> sub - - - ?repeated_term: repeated_factor - | repeated_term "*" repeated_factor -> mul - | repeated_term "/" repeated_factor -> div - - ?repeated_factor: repeated_power - | repeated_power "**" repeated_power -> power - - ?repeated_power: "(" repeated_expression ")" - | FUNC "(" repeated_expression ")" -> func - | SIGNED_NUMBER -> number - | NAME -> param_name - | BUILTIN -> builtin - - FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" - BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" - - %import common.CNAME -> NAME - %import common.SIGNED_NUMBER - %import common.WS_INLINE - - %ignore WS_INLINE - From 7336cc984c7412d8558633dc654d7480ddfeb308 Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:28:46 +0200 Subject: [PATCH 059/136] move doc bundles to applications and base_classes --- dev_tools/docs/nxdl_index.py | 31 ++ .../classes/applications/apm-structure.rst | 284 ++++++++++++++++++ .../container/ComplexContainerBeampath.png | Bin 0 -> 7089 bytes .../container/ComplexExampleContainer.png | Bin 0 -> 25103 bytes .../classes/applications/em-structure.rst | 164 ++++++++++ .../classes/applications/mpes-structure.rst | 42 +++ .../optical-spectroscopy-structure.rst | 199 ++++++++++++ .../classes/base_classes/apm-structure.rst | 284 ++++++++++++++++++ .../container/ComplexContainerBeampath.png | Bin 0 -> 7089 bytes .../container/ComplexExampleContainer.png | Bin 0 -> 25103 bytes .../classes/base_classes/em-structure.rst | 164 ++++++++++ .../classes/base_classes/mpes-structure.rst | 77 +++++ .../optical-spectroscopy-structure.rst | 199 ++++++++++++ 13 files changed, 1444 insertions(+) create mode 100644 manual/source/classes/applications/apm-structure.rst create mode 100644 manual/source/classes/applications/container/ComplexContainerBeampath.png create mode 100644 manual/source/classes/applications/container/ComplexExampleContainer.png create mode 100644 manual/source/classes/applications/em-structure.rst create mode 100644 manual/source/classes/applications/mpes-structure.rst create mode 100644 manual/source/classes/applications/optical-spectroscopy-structure.rst create mode 100644 manual/source/classes/base_classes/apm-structure.rst create mode 100644 manual/source/classes/base_classes/container/ComplexContainerBeampath.png create mode 100644 manual/source/classes/base_classes/container/ComplexExampleContainer.png create mode 100644 manual/source/classes/base_classes/em-structure.rst create mode 100644 manual/source/classes/base_classes/mpes-structure.rst create mode 100644 manual/source/classes/base_classes/optical-spectroscopy-structure.rst diff --git a/dev_tools/docs/nxdl_index.py b/dev_tools/docs/nxdl_index.py index e700c507a..e3f9c9371 100644 --- a/dev_tools/docs/nxdl_index.py +++ b/dev_tools/docs/nxdl_index.py @@ -66,6 +66,12 @@ def nxdl_indices() -> Dict[str, dict]: else: file = "" print("---------++++++++-", section) + if file.endswith(("applications/index.rst", "base_classes/index.rst")): + rst_lines.append(f"{indentation}em-structure\n") + rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") + rst_lines.append(f"{indentation}mpes-structure\n") + rst_lines.append(f"{indentation}apm-structure\n") + if file.endswith("contributed_definitions/index.rst"): rst_lines.append(f"{indentation}em-structure\n") rst_lines.append(f"{indentation}optical-spectroscopy-structure\n") @@ -113,6 +119,18 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: *might* be used in an instance of that class. Consider the base classes as a set of *components* that are used to construct a data file. + +Some contributions are grouped together: + :ref:`Optical Spectroscopy ` + + :ref:`Multi-dimensional Photoemission Spectroscopy ` + + :ref:`Atomprobe Microscopy ` + + :ref:`Electron Microscopy ` + +and others are simply listed here: + """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "applications": """ @@ -141,6 +159,19 @@ def get_nxclass_description(nxdl_file: Path, namespaces) -> str: In application definitions involving raw data, write the raw data in the :ref:`NXinstrument` tree and then link to it from the location(s) defined in the relevant application definition. + +Some contributions are grouped together: + :ref:`Optical Spectroscopy ` + + :ref:`Multi-dimensional Photoemission Spectroscopy ` + + :ref:`Atomprobe Microscopy ` + + :ref:`Electron Microscopy ` + + +and others are simply listed here: + """, # - - - - - - - - - - - - - - - - - - - - - - - - - - - - "contributed_definitions": """ diff --git a/manual/source/classes/applications/apm-structure.rst b/manual/source/classes/applications/apm-structure.rst new file mode 100644 index 000000000..dd6c45662 --- /dev/null +++ b/manual/source/classes/applications/apm-structure.rst @@ -0,0 +1,284 @@ +.. _Apm-Structure-APP: + +===================== +Atom-probe tomography +===================== + +.. index:: + IntroductionApm + ApmAppDef + ApmBC + StatusQuoApm + ApmParaprobeAppDef + ApmGermanNfdi + +.. _IntroductionApm-APP: + +Introduction +############ + +Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, +steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. +The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. + +.. _ApmAppDef-APP: + +Application Definition +###################### + + :ref:`NXapm`: + A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. The structure of the schema has been designed to also document a simulation of an atom probe + experiment. Having a combined schema for the measurement and the simulation is beneficial to document that + there are many similarities between the measurement and a computer simulation of it. + +.. _ApmBC-APP: + +Base Classes +############ + +The following base classes are proposed to support modularizing the storage of pieces of information: + + :ref:`NXchamber`: + A base class to describe a component of the instrument which houses other components. + A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities + for storing and loading specimens. + + :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`: + Base classes to describe different coordinate systems used and/or to be harmonized + or transformed into one another when interpreting the dataset. + + :ref:`NXion`: (about to become replaced by :ref:`NXatom_set`) + A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. + For the usage in atom probe research the maximum number of atoms supported building a molecular ion + is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with + which all possible nuclides (stable, radioactive, or synthetically generated ones) can be described. + + :ref:`NXfabrication`: + A base class to bundle manufacturer/technology-partner-specific details about + a component or device of an instrument. + + :ref:`NXpeak`: (about to become complemented by NXpeak_fitting) + A base class to describe peaks mathematically to detail how peaks in + mass-to-charge-state ratio histograms (aka mass spectra) are defined and + labelled as iontypes. + + :ref:`NXpump`: + A base class to describe details about pump(s) used as components of an instrument. + + :ref:`NXpulser_apm`: + A base class to describe the high-voltage and/or laser pulsing capabilities. + + :ref:`NXreflectron`: + A base class to describe a kinetic-energy-sensitive filtering device + for time-of-flight (ToF) mass spectrometry. + + :ref:`NXstage_lab`: + A base class to describe the specimen fixture including the cryo-head. + Nowadays, stages of microscopes represent small-scale laboratory platforms. + Therefore, there is a need to define the characteristics of such stages in more detail, + especially in light of in-situ experiments. Many similarities exists between a stage + in an electron microscope and one in an atom probe instrument. Both offer fixture + functionalities and additional components for applying e.g. stimuli on the specimen. + +Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of +data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named +instances of the :ref:`NXprocess` base class. + +Several base classes were defined to document processing of atom probe data with established algorithms: + + :ref:`NXapm_hit_finding`: + A base class to describe hit finding algorithm. + + :ref:`NXapm_volt_and_bowl`: + A base class to describe the voltage-and-bowl correction. + + :ref:`NXapm_charge_state_analysis`: + A base class to document the resolving of the charge_state. + + :ref:`NXapm_reconstruction`: + A base class to document the tomographic reconstruction algorithm. + + :ref:`NXapm_ranging`: + A base class to document the ranging process. + + :ref:`NXapm_msr`, :ref:`NXapm_sim`: + Respective base classes that serve as templates to compose the :ref:`NXapm` application definition from. + +These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented +to enable reproducible research, if possible even numerical reproducibility of the results, +and learn how pieces of information are connected. In what follows, an example is presented how an +open-source community software can be modified to use descriptions of these computational steps. + +A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe +data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: + + :ref:`NXspatial_filter`: + A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. + This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, + and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. + The primitives are used for defining the shape and extent of a region of interest (ROI). + + :ref:`NXsubsampling_filter`: + A base class for a filter that can also be used for specifying how entries + like ions can be filtered via sub-sampling. + + :ref:`NXmatch_filter`: + A base class for a filter that can also be used for specifying how entries + like ions can be filtered based on their type or other descriptors like hit multiplicity. + +The respective research software here is the `paraprobe-toolbox `_ +The software is developed by `M. Kühbach et al. `_. +For atom probe research the proposal can also serve as a blue print how computational steps of other software +tool including commercial ones could be developed further to benefit from NeXus. + +.. _IntroductionApmParaprobe-APP: + +apmtools +######## + +The paraprobe-toolbox is an example of an open-source parallelized software for analyzing +point cloud data, for assessing meshes in 3D continuum space, and for studying the effects of +parameterization on descriptors of micro- and nanoscale structural features (crystal defects) +within materials when characterized and studied with atom probe. + +The need for a thorough documentation of the tools in not only the paraprobe-toolbox +was motivated by several needs: + +First, users of software would like to better understand and also be able to study for themselves +which individual parameters and settings for each tool exist and how configuring these +affects analyses quantitatively. This stresses the aspect how to improve documentation. + +Second, scientific software like paraprobe-toolbox implement numerical/algorithmical +(computational) workflows whereby data coming from multiple input sources +(like previous analysis results) are processed and carried through more involved analyses +within several steps inside the tool. The tool then creates output as files. This +provenance and workflow should be documented. + +Individual tools of paraprobe-toolbox are developed in C/C++ and/or Python. +Provenance tracking is useful as it is one component and requirement for making +workflows exactly numerically reproducible and thus to enable reproducibility (the "R" +of the FAIR principles of data stewardship). + +For tools of the paraprobe-toolbox each workflow step is a pair or triple of sub-steps: +1. The creation of a configuration file. +2. The actual analysis using the Python/or C/C++ tools. +3. The optional analyses/visualization of the results based on data in NeXus/HDF5 files generated by each tool. + +.. _StatusQuoApm-APP: + +What has been achieved so far? +############################## + +This proposal summarizes work of members of the FAIRmat project, which is part of the `German +National Research Data Infrastructure `_. The here detailed +proposal documents how all tools of the paraprobe-toolbox were modified to generate +only well-defined configuration files as accepted input and yield specifically formatted output +files according to the following NeXus application definitions. + +Data and metadata between the tools are exchanged with NeXus/HDF5 files. This means that data +inside HDF5 binary containers are named, formatted, and hierarchically structured according +to application definitions. + +For example the application definition NXapm_paraprobe_config_surfacer specifies +how a configuration file for the paraprobe-surfacer tool should be formatted +and which parameters it contains including optionality and cardinality constraints. + +Thereby, each config file uses a controlled vocabulary of terms. Furthermore, +the config files store a SHA256 checksum for each input file. This implements a full +provenance tracking on the input files along the workflow. + +As an example, a user may first range their reconstruction and then compute spatial +correlation functions. The config file for the ranging tool stores the files +which hold the reconstructed ion position and ranging definitions. +The ranging tool generates a results file with the labels of each molecular ion. +This results file is formatted according to the tool-specific `results` +application definition. The generated results file and the reconstruction is +imported by the spatial statistics tool which again keeps track of all files +and reports its results in a spatial statistics tool results file. + +This design makes it possible to rigorously trace which numerical results were achieved +with specific inputs and settings using specifically-versioned tools. Noteworthy +this includes Y-junction on a graph which is where multiple input sources are +combined to generate new results. + +We are convinced that defining, documenting, using, and sharing application definitions +is useful and future-proof strategy for software development and data analyses as it enables +automated provenance tracking which happens silently in the background. + +Base classes have been defined to group common pieces of information for each tool of the +toolbox. For each tool we define a pair of base classes. One for the configuration (input) side +and one for the results (output) side: + + :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`, :ref:`NXapm_paraprobe_tool_common`: + Configuration, results, and common parts respectively useful for the application definitions for tools of the paraprobe-toolbox. + +.. _ApmParaprobeAppDef-APP: + +Application Definitions +####################### + +NXapm_paraprobe application definitions are in fact pairs of application definitions. +One for the configuration (input) side and one for the results (output) side. For each +tool one such pair is proposed: + + :ref:`NXapm_paraprobe_transcoder_config`, :ref:`NXapm_paraprobe_transcoder_results`: + Configuration and the results respectively of the paraprobe-transcoder tool. + Load POS, ePOS, APSuite APT, RRNG, RNG, and NeXus NXapm files. + Store reconstructed positions, ions, and charge states. + + :ref:`NXapm_paraprobe_ranger_config`, :ref:`NXapm_paraprobe_ranger_results`: + Configuration and results respectively of the paraprobe-ranger tool. + Apply ranging definitions and explore possible molecular ions. + Store applied ranging definitions and combinatorial analyses of possible iontypes. + + :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: + Configuration and results respectively of the paraprobe-selector tool. + Defining complex spatial regions-of-interest to filter reconstructed datasets. + Store which points are inside or on the boundary of complex spatial regions-of-interest. + + :ref:`NXapm_paraprobe_surfacer_config`, :ref:`NXapm_paraprobe_surfacer_results`: + Configuration and results respectively of the paraprobe-surfacer tool. + Create a model for the edge of a point cloud via convex hulls, alpha shapes, or alpha-wrappings. + Store triangulated surface meshes of models for the edge of a dataset. + + :ref:`NXapm_paraprobe_distancer_config`, :ref:`NXapm_paraprobe_distancer_results`: + Configuration and results respectively of the paraprobe-distancer tool. + Compute and store analytical distances between ions to a set of triangles. + + :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: + Configuration and results respectively of the paraprobe-tessellator tool. + Compute and store Voronoi cells and properties of these for all ions in a dataset. + + :ref:`NXapm_paraprobe_spatstat_config`, :ref:`NXapm_paraprobe_spatstat_results`: + Configuration and results respectively of the paraprobe-spatstat tool. + Compute spatial statistics on the entire or selected regions of the reconstructed dataset. + + :ref:`NXapm_paraprobe_clusterer_config`, :ref:`NXapm_paraprobe_clusterer_results`: + Configuration and results resepctively of the paraprobe-clusterer tool. + Compute cluster analyses with established machine learning algorithms using CPU or GPUs. + + :ref:`NXapm_paraprobe_nanochem_config`, :ref:`NXapm_paraprobe_nanochem_results`: + Configuration and results resepctively of the paraprobe-nanochem tool. + Compute delocalization, iso-surfaces, analyze 3D objects, composition profiles, and mesh interfaces. + + :ref:`NXapm_paraprobe_intersector_config`, :ref:`NXapm_paraprobe_intersector_results`: + Configuration and results resepctively of the paraprobe-intersector tool. + Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes + in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, + spatial arrangement, and colocation of 3D objects via graph-based techniques. + +.. _ApmGermanNfdi-APP: + +Joint work German NFDI consortia NFDI-MatWerk and FAIRmat +####################################################################### + +Members of the NFDI-MatWerk and the FAIRmat consortium of the German National Research Data Infrastructure +are working together within the Infrastructure Use Case IUC09 of the NFDI-MatWerk project to work on examples +how software tools in both consortia become better documented and interoperable to use. Within this project, +we have also added the `CompositionSpace tool that has been developed at the Max-Planck-Institut für Eisenforschung +GmbH in Düsseldorf `_ by A. Saxena et al. + +Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: + + :ref:`NXapm_compositionspace_config`, :ref:`NXapm_compositionspace_results`: + Configuration and the results respectively of the CompositionSpace tool. diff --git a/manual/source/classes/applications/container/ComplexContainerBeampath.png b/manual/source/classes/applications/container/ComplexContainerBeampath.png new file mode 100644 index 0000000000000000000000000000000000000000..597cee834c0426bd0e60b1afbf6554a5f3b04a99 GIT binary patch literal 7089 zcmbVxgT!j8lW(I7CP9R3l4E<2>J5 z)AI_IpP{<#g$8#av2ACx&qHz?7*6{wc9+~vb1nw=8zsvCGZ@1U!ma35{YCTeb^go#}G;SGXdmMbu z&k(dLz+>M0rk*>Sf)`6r0rqXS-WdWA6B8%4ZJE%EdqQPyjwzkRB;aOHTl>4)o5x|d zk^nCj4;eIl%(n^F+aGp�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®w_`d`gV3yjY{|b6NDG+(F z+Dfp*;kmaQ( zgpwxhnx_R<$?z+(zcBOG)xj(O-onKv&u}*Y!5QxL?cP`t?_fsj3Ui*C1C%hkGmf%^ z$sYlM5zvGrsp|LslzMZq9neG{PhO9SWE6y`=nDqj z1!%~VaeKI+f{24Yh5YfiTrykv1_s2|_N4heH8s^wYtsen8*a~)!^|IO3%vpGm`S1{nVrYa5Y=)!`dfCh0Rn_j zm(8`DmU7cSLw9JQWpjCopTxDauI}8wxVyF3n_>Ml8_BFdMt#r0e~v37)8hNY#B3_$ zfiq(6_mhS~fUxGc4Uesct@)l)-)3G`xg!LX*ly=n;_61Ce%o{7)XTJ^xpdD%0pY88 zN1%RdaOcWZOpDk`_r^Qh929y|N=iX#IE}EoixKkU;>s85%vWuxvKDu*Wq)CRHfT+r zGsd%^_-41J$(cGl94Iq+59(F4XZ=7A0hE}QjKol{eFad^uSSB(p%@Qe|YfeXzUdkFO8W_f}7`qNU|fp^x<*l}Vf9 z+x02ZF!KF&Fc*A>P3K}`N6!dbQY%|?u*bB|Ug&g&f1a-@{yN-FhZW!F`(0)kyOOSB z^qwFm@QUH4{V{Onv#wIpE&b^DdN^PK5W*Kt=Ch=>ysY-QhX2llv}W;fB?rB-yu0EP z!NZ`?HO(u*do2H}?Vn1ryc+5MDIF%=Eqm|wt=`ej?-WTXO#&|2>5S}b*t}wRpL@)j z(>GHG35bU|Ug1ztpIgzuFOQy>l zZ<11~->-5khf1P!O3D!^VSpbBTM(z(Eg3Tut#Kydl|mLJ6|7d}8?C3syj)qg74JK1 zqvgZ=-$6!^ufNp&tRL@uyoS4;YObq7cMxFrU zy=`(ee)9{8O^Y-aD0ZEByyvqX2J_rCP`)Xl7=tPHpceiW#~_Mi2NgY5RGB@$`p=xo z`J@hit(U+6ol>0*-51L12quiX^RW>$^2N>1gd`q?-giNn5G1yO6h63@FIncUZ(wYj z7@}UW8L%>c(y1vk?KRjX-rWT%GF%^oy4kmEFwIY_1A6?<$ONJ!0QNE5Rij{6){+33 zr$QDC2C|Hdoa=`~Pa*)daLWfu1nRPl>NGdOUM;chr({kr0@elnxsL`&wEuEHk*SVl zmI8e>KffhjfzQpagDx~gMc+FXMm{U?)7eU-&m^o){;gTn7ESH5|9%xqNjVOSGU+*JN?!^@FQXL%yo@TU$)hH`Q zs~s^1%AqYXb{luqdc%Pp&49gR9VTAk=PqFSe)*uNT8qN@>`>y z!!$xH_uUC11dA9x~48ZFS z`0DB)!=iXv2~`1*Gp=>N3>n~XA=J4u7)Bd1ePBJn+b-COB zOAF9)ePUf*n*X_O@THk|H`sJ*F7-P*Ee}^Hnt63_l|*j$_C{nwCu@>%^eniSe+YP? zVNv_LWS0!c!9|17zndPaV9~`=(IH4^8iIv7xw*)=cmhh?(Uu*gdWqHR$=mxmU+WEDh<=CA(S=MtUcBI}$q(dspoKg__2F0wzUgL@8?t=7 zV&8x~8uHxV_^-y)iwhKvpify|Ny+w%Wby~mv%DL~#P&*fr2@aa3t5j9>zWKh0(w*M z0cb3<0bS0_{V)9N*Mb%h^RGM~E^=$xfhrUOd#v&yi;Rt5%WElG?5RlVeS(`g5V;s# z9SR=S!_*XYpg@|MN?bo!52-0bx|3fI!KnUDpV-n233?7ayH|(7E6Wmz2iIt$Q`U0` z4Hw^mV?#{$ZL++RN~0F4|17yu^r7t=Vz$d<%~42wBVW^XHWYB%5b*yd7QK&zPet9%Octy%~{j4aaLGWQ&Ab33uzBsp*D@t z;ff|UalgK+w`yM=(cIX8;W9&7n}e{MgeeOocrEV#+^YpCrV8YQVoCY_GEp`1ki--x){S~laCA$%ViX;?S7!J_$ zZDQ9+65(mndK-T12*LRn(zb8GZIUZK4(05V#b)J47ohds?SNMv&TO6y_p>{i@dgBxvwK}DGV3NqJ_`|hzicY*f4-toWyBP=#DhG`^_1(( zqJOUK(_*6yrn4~jA_53Gx4#NZ+#tFbL^T&;YTEW-)E>lh*XZ28fkq_<&+Uc+rxKJ| zau}ud?OPj=B1q9AZJHsfWgl8y?qf8Z$O@Ycqe+1J#kSEInQy^~V03g&S=n%R_t3dE z?B*=3+VQZ7*c|{W{X1i}#`Omz8CfPMe>Y#vg5&nY>nl zTYMj>zosAhn{X0B{%-kVyaGuHB5i zmo!D14NAFtI2+ zxFf<(WH5s2{ny15IOxE`BS8(j5di{x$m#u1@>(O;QR7vxV^C-{?DsU+Th&s15f!xr zhy*{NQ&_CR|dJ2w--ev$C&PANTG!2#n;bM z%myW%Fm)x-gDEk?A)YQVh`NJrOoNE!IBYwj1Me7*-lflkHB1B>e=d? zJOY?+_uk87q6Aq-RU;(ZOe5%VgwPVj!ik3junQg=P5YgMUcM1@ z-6dnUgT%b*f@q&jto)@R?|eX9&FGYg{sCKQ!SiM)L#}tG;==aLuQEbmf+`=M3pUX0 zgL?2NFI{Xl$*lMLqm>oMP%4AOyC|C_)O;NIx5S~M-cYvg`46v6IH55S0b}PoH5DK& zQ=xCQLn$7gC9*LxI@Ybl(l|UETuf=rVj8pXhez3!3JiuXv!@=(d@AJHTWS_VGe@UD zcU=x>8Z;Q`D^T{={n=_ZP0q2K6Klso^TM^%V2bVM1g~IoN}ON)R0-u)BwI%{i{}NF z4(;xvI+S3fZsqV-q7!j4&(^leavS`@NfcpA7-rp?{hD?utMtLZ@Gzc_Pu)iO-sM7A zBvV&sq^UwkNK_Q#*RN`>ySQw6TSLKn^R;;mj)=duhNZrI2`oq@5ibmW_bXtq%*ZZ@ zJxhiq3yP*UlVZF39TUNcixz;wNj&`x&K5G1l#~F=r(QkrO^WV3c)YK;CYuOA@V#y) zH{3WxYrb~V{lSY0u1efIBEDPNHy|ycfrpGnhO<;rRvCQI6JN)QW?(???Pa)kguc^w z_^SM4@aGLYwi0wS$1MkY`dx>2Gp=xuD%)Yu0mHD`MC=@?Dst>+{d>-}y};I>k%#OM zF;Gg=c{A#<4w}N}nm+=8jO8i>7QRLASoigxk-S3;UAu;AeAjSW4X1-_-y+J9iN!F* zibk}xhwAvWFTqFrDCflK?v_gX`a--KGx{%f>}$$hD>4uH;I_7==h?binmVe_Qq!h* z^$Nnu>cBNMBK&_9_MPEyebKu|?>)LO(Sm5vJHsfE5TZtn7NSQ&ln~t@TBIYo45B4O zH%b_Sh~7IfdWjbGzvuow-RHUG>zO(G?0xpyYrU(zhlQiAXw;@SQ+a*?|7~eV{7v}qdubVtvZOoa?Bd{ndDwe!0eQ!ch@8{y2L#knCEQ_T850aAfExCG-WWT~ z+(g!$3XPCeBS^iJcDiLhonQ^wo?s%8%1xPl2yyu~#L46lRtB7{KfM>jT7+J=0H zV7AeTEZZiMQ^fG7qIchpXV6)4)a6t-99VK#xE}9}6yH`fZ}7jFjcnkx^8zC;s&p3emI!it_H1c;GA3Lj=C|9ty1%gP zjBCXEt*&@6{3MkkMNWmG=LfL0NdCK~c6*M~#D+vf!^k8tEua)Y8=<$Kj0!)XLc-Tx z`(EdzRy?d;Vwz?}(jJP}n;26hctgWUE84~lh2W2{^p_KM_sHHq@Yu5eyM}t^HC>zr zx(SZ|OnQln!e}pr$S`c1N!WWxbVitt8-y}<; zqSr=h-B~z!={v2hZ@Ns%Ubp)c5Uxib079D)RV z$s&lUTB|S5iPBf5Qa5w3iE zIjFxzh?mbSsy4q#b$RT6d~wXPp_Qc7@uyc#(Hlk&8a$nhZfh{m0f3i4^}4Can}VY4 zefK-N^%atX1omTjSTnZLhnQqd0)zxAcw9;Lyh(24(eU6oTP!!N>ii&IZL8rsi>n58 zyXhh0_Y$vNV+lBubEKwD=ulePn!fS2kb?Hmp+j7a*08?3yjr_&A|DHM{8#o;nKMPe zV3gmJsme9GeaUH|$#)_6kAa$pyfxT8(wAx0A%EZQiVmoG#!yFm6R>FY+%P}RR3Ivz zXXZY3Oev>EH+&sxm; z0wE+?jpdZrX;(bvI-{5`_bG4A#%lPVtbVr450TM`Zocec9i!y@5|sPBK8Kqx-|#+w z|Ew@1%K8e20x#!{wGb6n&|Yi(Dl?O-)TTbp%qD=SIuAW((xu@~V<(psfeM=!G{mp0 ziDY?>T&Y0NBW-zOcJ~MGE}kT;zn5^*EgtCus`9wKy#*{~x3O-ET;n4pZJ#R5(tEEM z1MW2i<5d1w)zm3mwX@%!$21m{j9 zLtr*bZ6{o4AkWMot2Z3M4L2~L9VxYrk7c<2{r>sVuU{+y8!V+gA0k>ovTf^=vbSyB z5LP$$F~YbTLR> z2JB1S>^JQR54UHNdV20`%rvqG9c{HAMA~{6N@)q_RvOwjH{TF2^qKXujh zoYGEn7ii1`KCM$`(^&p=^2pDQRi(U-u-=4kx|L8v}joqoNh) zL0(k#k|WqAkW5}=YPR+9&nu){&qMj3q4Se#4&6-Y2ZvgK7%W#pq{Kt$4q_Tm5%^jr zCML3|JeRYwvg)yBRO4=Grec5K=2#`;5JH@Mve&(%>_d2nhet_^7?yIt$%+Zc$otyiZk_-)*WoonH$6EB z2-`3y6Fw`R661ix@XjDt<1efi2MJwVGWvL5@fTQSTfSI7~7u`w~-#dQ%Qt5Hd<4~PjH=i9KQCC5XJf+LHr6qyjM;06mHjV6= zV$AxrelTi_Io(EkeP01VHU_{0_M`)JF`d09k9lLQVu2An+hfP0feJF%~7!Fw*k!a&gP6 zfF}<|iXRsj*TcjCH4hFl`1$#5URX6kyB+KYc-%@HoHtCtzWBm{Ua@a!Y0+7QdIyBw zkS}&5XgqydIlcy1YQjn^s}~m9;|&Up!Qi!p;St#&#nXQME;pY9{fEhF9=8>JV$vK@ zqyu;f!*WW;FfC3+V)T0!IpD4IY)<+*z(Dv=hL7)0DJNYO{&$cxC@!X;rLu&n=iM_V z_&wD`wZHLbONhQ-**>0tu8OsSXkqEr($Q)JEA;C6o#q5k@~G+awYFFrafG9HnMeou ztc5>4Ew`a7czAW9FIyrW2hXd6Dd+>TIpjpICbSiF)VjTNOOBA}+WKPBW6$3(+^@Ke zpU40=1Cb<0r(Vw{r+x@F4*@o>)14zcd@g8-^vvD?2&DqqFTh&#?a6yNx+d+!EICo? z!jzQGlVbd(C?dKhoA+7>L+4Hw?8kbBAPK*20L$6SE|gC7^=J zq3*U@KpbYiGBPZ>|T|wp#rD>obwtk6v(N$q76)(%3n5U)9eFa_NmxRV{5^u zuWyZ7ROL+kXUGLBM4SAYaQ))E*NR7iv0ey?>aO5YDnJr|L*r zDrOEHC<~XTesyIGVUr~OM?x*d$_A+c#J^9Y`a|B!Yw5-1`T27)#8oCsAcx&wX(%JN zX;ib8_8*;#zPz3piTU}4ze+97Yb`a+IWho*48ZSEZ5t{K)9u0SX`yl>rcw@ z4Z)`nT+P>zuJl(1MJ88BsE}NZ2pW;&hwCe~w#kJ+2U6!uWBoW}Xl;&MGAaJ?cP5_6 z4nzx+C&pNWK@A^0upa~my=lKqO}Te#SH%BJNGAqmiAGs7B8EJMh)BW0aC#jaX2fU| zuy(}t;yz8s_|p0Lb#9oXn4^vay=Y>{;NW-CDqXle-lGeSv5$6r#2bxkzl>j12+j&aMaf?fBHny;`_#^Z3^0p zOBZz1J82OYQBYhn5r94Oi{3;TVt3!6o9$W&BSuY~oELwc96-%Q1hvI(#h~%D4VUh-X@d;?mq@>W+5+fjwnn?ecxFgklNg$^ z_S=(hN9(|32lixoRo=mEx0rcogBM!*xK`mN9e7PJfJXN%YG}_#OCow&;AJoQWtppI zgPEZRt7~x|2k!AkM!{1v%gjp82KWGKqex=BF<14FN@#Gvd$|H*5O~oLQX9{la(Xb@ zIaAA^LPDc%|ETct-*WfD-wjNn=IXz{H5K01B0sWK+|l%rh|^D3J0am}J|8xluktJD z-;TIx0)mdDRGRbiZNz9*O-$mo&CTkYJF}Nsea@e1S5^$VaYRnTU%6zd!QRHMD1Y+D zuYM~M@jVCs&FX5++#*5Ja(6%INoP7dJUZj>aN-L|lOl6MpA$pLosQm=WMTHrkPaic zab7_V&~GNJtf4U2lSvtHiE^quyDNwZgIOGLD_bpy2SEicNn+q#y-rso0b2~gJT@)H z64;`amb)Jxo%rf_xIb9grumS|6SufvU~NnY8bt%IJd<$`Jsrr`QxS7mH=P!H3J(od zgE+WCSnj#GUBPtZz!ccj^{57B0x5StFNW^Y*}L|=OkP(H#3v)&XZ!boeLuF{7qc2Zsi zXC#Lo=UMEWA3f&b#)k~ve27gGYmCg}yZt~lL@6Ek*$z6S?&oI~m3#9UFV1gMQjOTy zumtQ2d}(ah|LJl=C>bakPxKKd1OpbNUrd5tLR&lH=!;t|w)O$u3Hr3O1~SpRMJC$! zDItg9Is}36oUvRN80dX;+&dz%5GhsOjbvd1en&^Lb^QZLN2E;!P;`ia zSA4WmY`kSwWT(x|Zdd6cuJ;zu78M&l-{XDt z4p1rPYA?S2CMgOE`S)p5)Rr?8duJqp>Dl$iZcQhs6J(uIOs;1<`_bq6v)eG_ps4>; z;Z8b=f`H1jq_Vs^W^~ePl$o9oVEvbNL5Ij}JcyTxiKWuFc` zq@d8r)Vr;c68Dtu+I;W928W1w&8mRy1~etpQ*%$S2Du>20gkaOfc7{h z<(Mtd+Dd0A8K{kT(6ii)Jv~Be{8<{p{#{$JUji69EuMMtWeka^URrcL85!|*ehDfR z_@aTJ?F1ZPn$z9IwCANiTJb^PYau}I{)hg+K(BH9SgRRqaD9L7!NbTJ^obDf*AA** zK==gMC|#t!8@@Nr7N6kmUukDk$x;>f|KE__{5c_3RFJYRlJ_9)e{go!$&)V$evbwA8w- zmG<5Ew}f9T6(GVowBxNA)lC>nRZoS1NHz!j>3O(q8L&dV#m}pj z@tzb|DFO6Tvi9BG-!qLj-qKZ0@RwC@j1OYT-%weyQ2HherA$o7SeikAM@81Mz>d@~ zt)@2s=qp!Of>#Jp%;t;B`f)d4o@`!BA#T%DapDf%DeQ?)_1E^^E$O zrPu01S(mDss;7eK&OI(?x2*yBxO#YaySHuMTJrHPwV{f+ zmAYfOiM;@FA|U^a8u%slwZMQ_QIf&CK1e2P+u7l@gYKTI(&WDeKl1?L1j^fO;M-)X z;GiK99Hn~GZdgxEmKf21$o@^iRp8<}LiWFw#ZBOOxqZ1XvbP*+8V^j!OT4N&?}AgZpye1q&=$Khe-I|zw;0~CUjzpDwdFz&^RwIs~~Tw ziD@!t1bD{?1o0RNA+mQJgf_5DN)m>80kty{T{00Q@fgkPcjGVsHn37r0dWC-EOJF; zTr9VQkyFLJk_b_3I@*_)tg|n3A))mLYmR;x0n2J`_8COKYj`e?Q-R=svTs~ukF*1; z>lo^LdEuQQsjY;Td7<)C%+~Wz0iFxr`|7kH77$e}yP=gpuL|O+SCT~19yRsNR8gq= zR{7fuhK09H7n`+Hl~Hz$eI+uve;BM0j(C!_gQk90vM`igJ}NE z2FL6tu*-L3U&UEM>Fin6OEL;YMJSYCj7Ak$C!p&oMJ4h~iVb~Eq(aCj5hpQRaoa(q zR)wH{ z^n3uin$*Mu1lEZ-MwpGTi>Q$7STl6{Fz;ksr-nXgL@e1QN>a?~JcU;l8x){uaN|=aZsOKA!Xr=&M_~-3G|(=@>c$fuUlB0Nx#_L)dBV2K(LV8W_blN@@fVJ_p&b)x3flVFDI~)w`FB1 z$7>nP{`7mA$@uC<&uGJ-w&lji+FnSF(r3LgSdqoD=#%w(LUi-1&ZtpGAn ztD`_Kup2SDYuiG9eOVs;g833>)skAV!tA)$k z6K()EIg{BY)Tzt{f<{#@?^n;iMuZpj+}RDL$iK&7Rp|bk$Q~K|AgiY4RYiu<8;zK_ zqu1=LVlbmZ@uk$e-a*p}IP*3@!JGvw8ow_KInV)G!m$uMjq}tCN@{^Z7NrGdbn2S4L7i+}z$vohe#9SBJ;J zrw3ec-w4=ttFk~1yE-~K*&VD6Bi+mYqU3k3Ta$eAS=N1G7KXgTYg7mpzjdl|@5T+C zk}nq7T7P&_x+j&6b%aF{JiiQ&J2^RB6BO*48g^lFHo`_ are used to map isotope to hash values with which all possible isotopes can be described. + + :ref:`NXoptical_system_em`: + A base class to store for now qualitative and quantitative values of frequent interest + which are affected by the interplay of the components and state of an electron microscope. + Examples are the semiconvergence angle or the depth of field and depth of focus, the magnification, or the camera length. + + :ref:`NXpeak`: + A base class to describe peaks mathematically. + + :ref:`NXcircuit`: + A base class to describe a logical unit of at least one integrated circuit. + + +.. _EmAnalysisClasses-APP: + +We provide specific base classes which granularize frequently collected or analyzed quantities in specific application fields of electron microscopy to deal +with the situation that there are cases were logical connections between generated data artifacts mainly exist for the fact that the data artifacts were +collected during a workflow of electron microscopy research (e.g. taking measurements and then performing method-specific analyses generating new data and conclusions). +We see a value in granularizing out these pieces of information into own classes. In fact, one limitation of application definitions in NeXus, exactly as it applies for serialization +of information also more generally, is currently that they define a set of constraints on their graph of controlled concepts and terms. + +If we take for example diffraction experiments performed with an electron microscope, it is usually the case that (diffraction) patterns are collected in the session at the microscope. +However, all scientifically relevant conclusions are typically drawn later, i.e. through post-processing the collected diffraction (raw) data. These numerical and algorithmic steps +define computational workflows were data from an instance of an application definition such as NXem are used as input but many additional concepts, constraints, and assumptions +are applied without that these demand necessarily changes in the constraints on fields or groups of NXem. If we were to modify NXem for these cases, +NXem would combinatorially diverge as every different combination of required constraints demands having an own but almost similar application definition. +For this reason, method-specific base classes are used which granularize out how specific pieces of information are processed further to eventually enable their +storage (i.e. serialization) using NeXus. + +More consolidation through the use of NXsubentry classes should be considered in the future. For now we use an approach whereby base classes are combined to reuse vocabulary and a hierarchical organization of pieces of information with specific constraints which are relevant only for specific usage of such data by specific tools used by an eventually smaller circle of users. + + :ref:`NXem_method`, :ref:`NXem_ebsd`, :ref:`NXem_eds`, :ref:`NXem_eels`, :ref:`NXem_img`, :ref:`NXem_correlation`: + Base classes with method-specific details especially when it comes to reporting post-processed data within electron microscopy. + + :ref:`NXcrystal_structure`: + A base class to store crystalline phase/structure used for a simulation of diffraction pattern and comparison of these pattern against patterns to support indexing. + + :ref:`NXroi`: + A base class to granularize information collected and relevant for the characterization of a region-of-interest. diff --git a/manual/source/classes/applications/mpes-structure.rst b/manual/source/classes/applications/mpes-structure.rst new file mode 100644 index 000000000..9bc056b1f --- /dev/null +++ b/manual/source/classes/applications/mpes-structure.rst @@ -0,0 +1,42 @@ +.. _Mpes-Structure-APP: + +======================================= +Photoemission & core-level spectroscopy +======================================= + +.. index:: + IntroductionMpes + MpesAppDef + MpesBC + MpesCommonBC + MpesExtendedBC + + +.. _IntroductionMpes-APP: + +Introduction +############ + +Set of data storage objects to describe multidimensional photoemission (MPES) experiments including x-ray photoelectron spectroscopy (XPS), ultraviolet photoelectron spectroscopy (UPS), +hard x-ray photoelectron spectroscopy (HAXPES), angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) +and photoemission electron microscopy (PEEM). Also includes descriptors for advanced specializations, such as spin-resolution, time resolution, +near-ambient pressure conditions, dichroism etc. + +.. _MpesAppDef-APP: + +Application Definitions +####################### + +:ref:`NXmpes`: + A general application definition with minimalistic metadata requirements, apt to describe all photoemission experiments. + +:ref:`NXmpes_arpes`: + An application definition for angle-resolved photoemission spectroscopy (ARPES) experiments. + +:ref:`NXxps`: + An application definition for X-ray/ultraviolet photoelectron spectroscopy (XPS/UPS) measurements. + +:ref:`NXarpes`: + An application definition for angle-resolved photoemission spectroscopy (ARPES) experiments. This definition is a legacy + support for older NXarpes experiments. For newer experiments, the user is advised to use :ref:`NXmpes_arpes`:.” + diff --git a/manual/source/classes/applications/optical-spectroscopy-structure.rst b/manual/source/classes/applications/optical-spectroscopy-structure.rst new file mode 100644 index 000000000..b9f5e11c1 --- /dev/null +++ b/manual/source/classes/applications/optical-spectroscopy-structure.rst @@ -0,0 +1,199 @@ +.. _Optical-Spectroscopy-Structure-APP: + +==================== +Optical Spectroscopy +==================== + +.. index:: + Ellipsometry + Raman + DispersiveMaterial + + +.. _Ellipsometry-APP: + +Ellipsometry +############ + +Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. +The measurements are based on determining how the polarization state of light changes upon transmission and reflection. +Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. + +In the application definition, we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. + +.. _Raman-APP: + +Raman +############ + +Raman spectroscopy is a characterization method to analyze vibrational properties for liquids, gases, or solids. +The measurements is based on the inelastic light scattering due to the material's vibrations. +Interpretation can be done based on peaks, which represent the phonon properties (intensity, center, width). + +The application definition contains a minimum of descriptive elements required to understand Raman spectroscopy measurements. + + +Application Definitions +----------------------- + + :ref:`NXoptical_spectroscopy`: + A generic application definition for spectroscopy measurements. This includes in particular ellipsometry and Raman spectroscopy measurements, but also other techniques such as photoluminescence, transmission, and reflection measurements. The requirements are: (i) an incident photon beam, (ii) a detector to measure scattered/emitted photons, and (iii) a sample. + + :ref:`NXellipsometry`: + An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. + + :ref:`NXraman`: + An application definition for Raman spectroscopy measurements. + + +Base Classes +------------ + +This is the set of base classes for describing an optical experiment. + + :ref:`NXbeam_device` + Beam devices are used to relate a beam, which has always at least one origin + and at least one destination. + + By referencing the beam devices with each other, a beam path can be + constructed. This can be used for vizualization or beam propery modeling + along the beam path. + + :ref:`NXbeam` + Beam properties such as intensity, polarization, wavelength or direction. + + :ref:`NXdetector` + A detector for signal detection. + + :ref:`NXsource` + A light source such as laser, lamp or LED. + + :ref:`NXmonochromator` + A monochromator is often used to energetically disperse the scattered or emitted light. + + :ref:`NXlens_opt` + Description of an optical lens. + + :ref:`NXwaveplate` + A waveplate or retarder. + + :ref:`NXsensor` + Specify external parameters that have influenced the sample such as + varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. + + + +.. _DispersiveMaterial-APP: + +Dispersive Material +################### + +A dispersive material is a description for the optical dispersion of materials. +This description may be used to store optical model data from an ellipsometric analysis +(or any other technique) or to build a database of optical constants for optical properties of materials. + +Application Definition +---------------------- + + :ref:`NXdispersive_material`: + An application definition to describe the dispersive properties of a material. + The material may be isotropic, uniaxial or biaxial. Hence, it may contain up + to three dispersive functions or tables. + + + +Base Classes +------------ + +There is a set of base classes for describing a dispersion. + + :ref:`NXdispersion` + This is an umbrella base class for a group of dispersion functions to describe the material. + For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. + If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. + This allows for, e.g. splitting real and imaginary parts and describing them seperately or + adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). + + :ref:`NXdispersion_function` + This dispersion is described by a function and its single and repeated parameter values. + It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` + (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. + + :ref:`NXdispersion_single_parameter` + This denotes a parameter which is used outside the summed part of a dispersion function, + e.g. ``eps_inf`` in the formula example above. + + :ref:`NXdispersion_repeated_parameter` + This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. + ``A`` and ``B`` are repeated parameters in the formula above. + + :ref:`NXdispersion_table` + This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. + +Formula Grammar +--------------- + +Below you find a grammar to which the formula should adhere and which can be used to parse and +evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be +filled with the respective single and repeated params from the stored data. +The grammer is written in the `EBNF `_ dialect +of `Lark `_, which is a parsing toolkit for python. +It is easily translatable to general EBNF and other parser generator dialects. +`Here `_ is a reference implementation in Rust/Python with a +`grammar `_ +written in `lalrpop `_. + +.. code-block:: + + ?assignment: "eps" "=" kkr_expression -> eps + | "n" "=" kkr_expression -> n + + ?kkr_expression: expression + | "" "+" "1j" "*" term -> kkr_term + + ?expression: term + | expression "+" term -> add + | expression "-" term -> sub + + ?term: factor + | term "*" factor -> mul + | term "/" factor -> div + + ?factor: power + | power "**" power -> power + + + ?power: "(" expression ")" + | FUNC "(" expression ")" -> func + | "sum" "[" repeated_expression "]" -> sum_expr + | NAME -> single_param_name + | SIGNED_NUMBER -> number + | BUILTIN -> builtin + + ?repeated_expression: repeated_term + | repeated_expression "+" repeated_term -> add + | repeated_expression "-" repeated_term -> sub + + + ?repeated_term: repeated_factor + | repeated_term "*" repeated_factor -> mul + | repeated_term "/" repeated_factor -> div + + ?repeated_factor: repeated_power + | repeated_power "**" repeated_power -> power + + ?repeated_power: "(" repeated_expression ")" + | FUNC "(" repeated_expression ")" -> func + | SIGNED_NUMBER -> number + | NAME -> param_name + | BUILTIN -> builtin + + FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" + BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" + + %import common.CNAME -> NAME + %import common.SIGNED_NUMBER + %import common.WS_INLINE + + %ignore WS_INLINE + diff --git a/manual/source/classes/base_classes/apm-structure.rst b/manual/source/classes/base_classes/apm-structure.rst new file mode 100644 index 000000000..79f90e42b --- /dev/null +++ b/manual/source/classes/base_classes/apm-structure.rst @@ -0,0 +1,284 @@ +.. _Apm-Structure-BC: + +===================== +Atom-probe tomography +===================== + +.. index:: + IntroductionApm + ApmAppDef + ApmBC + StatusQuoApm + ApmParaprobeAppDef + ApmGermanNfdi + +.. _IntroductionApm-BC: + +Introduction +############ + +Set of data schemas to describe the acquisition, i.e. measurement side, the extraction of hits from detector raw data, +steps to compute mass-to-charge state ratios from uncorrected time of flight data, the reconstruction, and the ranging, i.e. identification of peaks in the mass-to-charge-state ratio histogram to detect (molecular) ions. +The data schemas can be useful to generate data artifacts also for field-ion microscopy experiments. + +.. _ApmAppDef-BC: + +Application Definition +###################### + + :ref:`NXapm`: + A general application definition with many detailed places for leaving metadata and computational steps described which are commonly used when reporting the measurement of atom probe data including also detector hit data, as well as how to proceed with reconstructing atom positions from these data, and how to store details about definitions made, which describe how mass-to-charge-state ratio values are mapped to iontypes in a process called ranging. The structure of the schema has been designed to also document a simulation of an atom probe + experiment. Having a combined schema for the measurement and the simulation is beneficial to document that + there are many similarities between the measurement and a computer simulation of it. + +.. _ApmBC-BC: + +Base Classes +############ + +The following base classes are proposed to support modularizing the storage of pieces of information: + + :ref:`NXchamber`: + A base class to describe a component of the instrument which houses other components. + A chamber may offer a controlled atmosphere to execute an experiment and/or offer functionalities + for storing and loading specimens. + + :ref:`NXcoordinate_system_set`, :ref:`NXcoordinate_system`: + Base classes to describe different coordinate systems used and/or to be harmonized + or transformed into one another when interpreting the dataset. + + :ref:`NXion`: (about to become replaced by :ref:`NXatom_set`) + A base class to describe molecular ions with an adjustable number of atoms/isotopes building each ion. + For the usage in atom probe research the maximum number of atoms supported building a molecular ion + is currently set to a maximum of 32. Suggestions made in reference `DOI: 10.1017/S1431927621012241 `_ are used to map isotope to hash values with + which all possible nuclides (stable, radioactive, or synthetically generated ones) can be described. + + :ref:`NXfabrication`: + A base class to bundle manufacturer/technology-partner-specific details about + a component or device of an instrument. + + :ref:`NXpeak`: (about to become complemented by NXpeak_fitting) + A base class to describe peaks mathematically to detail how peaks in + mass-to-charge-state ratio histograms (aka mass spectra) are defined and + labelled as iontypes. + + :ref:`NXpump`: + A base class to describe details about pump(s) used as components of an instrument. + + :ref:`NXpulser_apm`: + A base class to describe the high-voltage and/or laser pulsing capabilities. + + :ref:`NXreflectron`: + A base class to describe a kinetic-energy-sensitive filtering device + for time-of-flight (ToF) mass spectrometry. + + :ref:`NXstage_lab`: + A base class to describe the specimen fixture including the cryo-head. + Nowadays, stages of microscopes represent small-scale laboratory platforms. + Therefore, there is a need to define the characteristics of such stages in more detail, + especially in light of in-situ experiments. Many similarities exists between a stage + in an electron microscope and one in an atom probe instrument. Both offer fixture + functionalities and additional components for applying e.g. stimuli on the specimen. + +Microscopy experiments, not only taking into account those performed on commercial instruments, offer users to apply a set of +data processing steps. Some of them are frequently applied on-the-fly. For now we represent these steps with specifically named +instances of the :ref:`NXprocess` base class. + +Several base classes were defined to document processing of atom probe data with established algorithms: + + :ref:`NXapm_hit_finding`: + A base class to describe hit finding algorithm. + + :ref:`NXapm_volt_and_bowl`: + A base class to describe the voltage-and-bowl correction. + + :ref:`NXapm_charge_state_analysis`: + A base class to document the resolving of the charge_state. + + :ref:`NXapm_reconstruction`: + A base class to document the tomographic reconstruction algorithm. + + :ref:`NXapm_ranging`: + A base class to document the ranging process. + + :ref:`NXapm_msr`, :ref:`NXapm_sim`: + Respective base classes that serve as templates to compose the :ref:`NXapm` application definition from. + +These base classes are examples that substantiate that data processing steps are essential to transform atom probe measurements or simulations into knowledge. Therefore, these steps should be documented +to enable reproducible research, if possible even numerical reproducibility of the results, +and learn how pieces of information are connected. In what follows, an example is presented how an +open-source community software can be modified to use descriptions of these computational steps. + +A detailed inspection of spatial and other type of filters frequently used in analysis of atom probe +data revealed that it is better to define atom-probe-agnostic reusable concepts for filters: + + :ref:`NXspatial_filter`: + A base class proposing how a point cloud can be spatially filtered in a specific yet general manner. + This base class takes advantage of :ref:`NXcg_ellipsoid_set`, :ref:`NXcg_cylinder_set`, + and :ref:`NXcg_hexahedron_set` to cater for commonly used geometric primitives in atom probe. + The primitives are used for defining the shape and extent of a region of interest (ROI). + + :ref:`NXsubsampling_filter`: + A base class for a filter that can also be used for specifying how entries + like ions can be filtered via sub-sampling. + + :ref:`NXmatch_filter`: + A base class for a filter that can also be used for specifying how entries + like ions can be filtered based on their type or other descriptors like hit multiplicity. + +The respective research software here is the `paraprobe-toolbox `_ +The software is developed by `M. Kühbach et al. `_. +For atom probe research the proposal can also serve as a blue print how computational steps of other software +tool including commercial ones could be developed further to benefit from NeXus. + +.. _IntroductionApmParaprobe-BC: + +apmtools +######## + +The paraprobe-toolbox is an example of an open-source parallelized software for analyzing +point cloud data, for assessing meshes in 3D continuum space, and for studying the effects of +parameterization on descriptors of micro- and nanoscale structural features (crystal defects) +within materials when characterized and studied with atom probe. + +The need for a thorough documentation of the tools in not only the paraprobe-toolbox +was motivated by several needs: + +First, users of software would like to better understand and also be able to study for themselves +which individual parameters and settings for each tool exist and how configuring these +affects analyses quantitatively. This stresses the aspect how to improve documentation. + +Second, scientific software like paraprobe-toolbox implement numerical/algorithmical +(computational) workflows whereby data coming from multiple input sources +(like previous analysis results) are processed and carried through more involved analyses +within several steps inside the tool. The tool then creates output as files. This +provenance and workflow should be documented. + +Individual tools of paraprobe-toolbox are developed in C/C++ and/or Python. +Provenance tracking is useful as it is one component and requirement for making +workflows exactly numerically reproducible and thus to enable reproducibility (the "R" +of the FAIR principles of data stewardship). + +For tools of the paraprobe-toolbox each workflow step is a pair or triple of sub-steps: +1. The creation of a configuration file. +2. The actual analysis using the Python/or C/C++ tools. +3. The optional analyses/visualization of the results based on data in NeXus/HDF5 files generated by each tool. + +.. _StatusQuoApm-BC: + +What has been achieved so far? +############################## + +This proposal summarizes work of members of the FAIRmat project, which is part of the `German +National Research Data Infrastructure `_. The here detailed +proposal documents how all tools of the paraprobe-toolbox were modified to generate +only well-defined configuration files as accepted input and yield specifically formatted output +files according to the following NeXus application definitions. + +Data and metadata between the tools are exchanged with NeXus/HDF5 files. This means that data +inside HDF5 binary containers are named, formatted, and hierarchically structured according +to application definitions. + +For example the application definition NXapm_paraprobe_config_surfacer specifies +how a configuration file for the paraprobe-surfacer tool should be formatted +and which parameters it contains including optionality and cardinality constraints. + +Thereby, each config file uses a controlled vocabulary of terms. Furthermore, +the config files store a SHA256 checksum for each input file. This implements a full +provenance tracking on the input files along the workflow. + +As an example, a user may first range their reconstruction and then compute spatial +correlation functions. The config file for the ranging tool stores the files +which hold the reconstructed ion position and ranging definitions. +The ranging tool generates a results file with the labels of each molecular ion. +This results file is formatted according to the tool-specific `results` +application definition. The generated results file and the reconstruction is +imported by the spatial statistics tool which again keeps track of all files +and reports its results in a spatial statistics tool results file. + +This design makes it possible to rigorously trace which numerical results were achieved +with specific inputs and settings using specifically-versioned tools. Noteworthy +this includes Y-junction on a graph which is where multiple input sources are +combined to generate new results. + +We are convinced that defining, documenting, using, and sharing application definitions +is useful and future-proof strategy for software development and data analyses as it enables +automated provenance tracking which happens silently in the background. + +Base classes have been defined to group common pieces of information for each tool of the +toolbox. For each tool we define a pair of base classes. One for the configuration (input) side +and one for the results (output) side: + + :ref:`NXapm_paraprobe_tool_config`, :ref:`NXapm_paraprobe_tool_results`, :ref:`NXapm_paraprobe_tool_common`: + Configuration, results, and common parts respectively useful for the application definitions for tools of the paraprobe-toolbox. + +.. _ApmParaprobeAppDef-BC: + +Application Definitions +####################### + +NXapm_paraprobe application definitions are in fact pairs of application definitions. +One for the configuration (input) side and one for the results (output) side. For each +tool one such pair is proposed: + + :ref:`NXapm_paraprobe_transcoder_config`, :ref:`NXapm_paraprobe_transcoder_results`: + Configuration and the results respectively of the paraprobe-transcoder tool. + Load POS, ePOS, APSuite APT, RRNG, RNG, and NeXus NXapm files. + Store reconstructed positions, ions, and charge states. + + :ref:`NXapm_paraprobe_ranger_config`, :ref:`NXapm_paraprobe_ranger_results`: + Configuration and results respectively of the paraprobe-ranger tool. + Apply ranging definitions and explore possible molecular ions. + Store applied ranging definitions and combinatorial analyses of possible iontypes. + + :ref:`NXapm_paraprobe_selector_config`, :ref:`NXapm_paraprobe_selector_results`: + Configuration and results respectively of the paraprobe-selector tool. + Defining complex spatial regions-of-interest to filter reconstructed datasets. + Store which points are inside or on the boundary of complex spatial regions-of-interest. + + :ref:`NXapm_paraprobe_surfacer_config`, :ref:`NXapm_paraprobe_surfacer_results`: + Configuration and results respectively of the paraprobe-surfacer tool. + Create a model for the edge of a point cloud via convex hulls, alpha shapes, or alpha-wrappings. + Store triangulated surface meshes of models for the edge of a dataset. + + :ref:`NXapm_paraprobe_distancer_config`, :ref:`NXapm_paraprobe_distancer_results`: + Configuration and results respectively of the paraprobe-distancer tool. + Compute and store analytical distances between ions to a set of triangles. + + :ref:`NXapm_paraprobe_tessellator_config`, :ref:`NXapm_paraprobe_tessellator_results`: + Configuration and results respectively of the paraprobe-tessellator tool. + Compute and store Voronoi cells and properties of these for all ions in a dataset. + + :ref:`NXapm_paraprobe_spatstat_config`, :ref:`NXapm_paraprobe_spatstat_results`: + Configuration and results respectively of the paraprobe-spatstat tool. + Compute spatial statistics on the entire or selected regions of the reconstructed dataset. + + :ref:`NXapm_paraprobe_clusterer_config`, :ref:`NXapm_paraprobe_clusterer_results`: + Configuration and results resepctively of the paraprobe-clusterer tool. + Compute cluster analyses with established machine learning algorithms using CPU or GPUs. + + :ref:`NXapm_paraprobe_nanochem_config`, :ref:`NXapm_paraprobe_nanochem_results`: + Configuration and results resepctively of the paraprobe-nanochem tool. + Compute delocalization, iso-surfaces, analyze 3D objects, composition profiles, and mesh interfaces. + + :ref:`NXapm_paraprobe_intersector_config`, :ref:`NXapm_paraprobe_intersector_results`: + Configuration and results resepctively of the paraprobe-intersector tool. + Analyze volumetric intersections and proximity of 3D objects discretized as triangulated surface meshes + in continuum space to study the effect the parameterization of surface extraction algorithms on the resulting shape, + spatial arrangement, and colocation of 3D objects via graph-based techniques. + +.. _ApmGermanNfdi-BC: + +Joint work German NFDI consortia NFDI-MatWerk and FAIRmat +####################################################################### + +Members of the NFDI-MatWerk and the FAIRmat consortium of the German National Research Data Infrastructure +are working together within the Infrastructure Use Case IUC09 of the NFDI-MatWerk project to work on examples +how software tools in both consortia become better documented and interoperable to use. Within this project, +we have also added the `CompositionSpace tool that has been developed at the Max-Planck-Institut für Eisenforschung +GmbH in Düsseldorf `_ by A. Saxena et al. + +Specifically, within the IUC09 we refactored the code base behind the publication `A. Saxena et al. `_ to better document its configuration, here as an example implemented like for the above-mentioned paraprobe-toolbox using NeXus: + + :ref:`NXapm_compositionspace_config`, :ref:`NXapm_compositionspace_results`: + Configuration and the results respectively of the CompositionSpace tool. diff --git a/manual/source/classes/base_classes/container/ComplexContainerBeampath.png b/manual/source/classes/base_classes/container/ComplexContainerBeampath.png new file mode 100644 index 0000000000000000000000000000000000000000..597cee834c0426bd0e60b1afbf6554a5f3b04a99 GIT binary patch literal 7089 zcmbVxgT!j8lW(I7CP9R3l4E<2>J5 z)AI_IpP{<#g$8#av2ACx&qHz?7*6{wc9+~vb1nw=8zsvCGZ@1U!ma35{YCTeb^go#}G;SGXdmMbu z&k(dLz+>M0rk*>Sf)`6r0rqXS-WdWA6B8%4ZJE%EdqQPyjwzkRB;aOHTl>4)o5x|d zk^nCj4;eIl%(n^F+aGp�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®w_`d`gV3yjY{|b6NDG+(F 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 are used to map isotope to hash values with which all possible isotopes can be described. + + :ref:`NXoptical_system_em`: + A base class to store for now qualitative and quantitative values of frequent interest + which are affected by the interplay of the components and state of an electron microscope. + Examples are the semiconvergence angle or the depth of field and depth of focus, the magnification, or the camera length. + + :ref:`NXpeak`: + A base class to describe peaks mathematically. + + :ref:`NXcircuit`: + A base class to describe a logical unit of at least one integrated circuit. + + +.. _EmAnalysisClasses-BC: + +We provide specific base classes which granularize frequently collected or analyzed quantities in specific application fields of electron microscopy to deal +with the situation that there are cases were logical connections between generated data artifacts mainly exist for the fact that the data artifacts were +collected during a workflow of electron microscopy research (e.g. taking measurements and then performing method-specific analyses generating new data and conclusions). +We see a value in granularizing out these pieces of information into own classes. In fact, one limitation of application definitions in NeXus, exactly as it applies for serialization +of information also more generally, is currently that they define a set of constraints on their graph of controlled concepts and terms. + +If we take for example diffraction experiments performed with an electron microscope, it is usually the case that (diffraction) patterns are collected in the session at the microscope. +However, all scientifically relevant conclusions are typically drawn later, i.e. through post-processing the collected diffraction (raw) data. These numerical and algorithmic steps +define computational workflows were data from an instance of an application definition such as NXem are used as input but many additional concepts, constraints, and assumptions +are applied without that these demand necessarily changes in the constraints on fields or groups of NXem. If we were to modify NXem for these cases, +NXem would combinatorially diverge as every different combination of required constraints demands having an own but almost similar application definition. +For this reason, method-specific base classes are used which granularize out how specific pieces of information are processed further to eventually enable their +storage (i.e. serialization) using NeXus. + +More consolidation through the use of NXsubentry classes should be considered in the future. For now we use an approach whereby base classes are combined to reuse vocabulary and a hierarchical organization of pieces of information with specific constraints which are relevant only for specific usage of such data by specific tools used by an eventually smaller circle of users. + + :ref:`NXem_method`, :ref:`NXem_ebsd`, :ref:`NXem_eds`, :ref:`NXem_eels`, :ref:`NXem_img`, :ref:`NXem_correlation`: + Base classes with method-specific details especially when it comes to reporting post-processed data within electron microscopy. + + :ref:`NXcrystal_structure`: + A base class to store crystalline phase/structure used for a simulation of diffraction pattern and comparison of these pattern against patterns to support indexing. + + :ref:`NXroi`: + A base class to granularize information collected and relevant for the characterization of a region-of-interest. diff --git a/manual/source/classes/base_classes/mpes-structure.rst b/manual/source/classes/base_classes/mpes-structure.rst new file mode 100644 index 000000000..80093d7e7 --- /dev/null +++ b/manual/source/classes/base_classes/mpes-structure.rst @@ -0,0 +1,77 @@ +.. _Mpes-Structure-BC: + +======================================= +Photoemission & core-level spectroscopy +======================================= + +.. index:: + IntroductionMpes + MpesAppDef + MpesBC + MpesCommonBC + MpesExtendedBC + + +.. _IntroductionMpes-BC: + +Introduction +############ + +Set of data storage objects to describe multidimensional photoemission (MPES) experiments including x-ray photoelectron spectroscopy (XPS), ultraviolet photoelectron spectroscopy (UPS), +hard x-ray photoelectron spectroscopy (HAXPES), angle-resolved photoemission spectroscopy (ARPES), two-photon photoemission (2PPE) +and photoemission electron microscopy (PEEM). Also includes descriptors for advanced specializations, such as spin-resolution, time resolution, +near-ambient pressure conditions, dichroism etc. + +.. _MpesBC-BC: + +Base Classes +############ + +:ref:`NXelectronanalyser`: + A base class to describe electron kinetic energy analizers. Contains the collective characteristics of the instrument such as energy resolution, and includes the following subclasses: + + :ref:`NXcollectioncolumn`: + Base class to describe the set of electronic lenses in the electron collection column (standard, PEEM, momentum-microscope, etc.). + + :ref:`NXenergydispersion`: + Base class to describe the energy dispersion sytem (hemispherical, time-of-flight, etc.). + + :ref:`NXspindispersion`: + Base class to describe the set of electronic lenses in the electron collection column. + +:ref:`NXmanipulator`: + A base class to describe the complex manipulators used in photoemission experiments, often with > 4 degrees of freedom, + cryogenic cooling and other advanced features. + +Three base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: + + :ref:`NXcalibration`: + A base class to describe the 1D calibration of an axis, with a function mapping a raw data scale to a calibrated scale with the same number of points. + + :ref:`NXdistortion`: + A base class to describe the 2D distortion correction of an axis, with a matrix mapping a raw data image to a undistorted image. + + :ref:`NXregistration`: + A base class to describe the rigid transformations that are applied to an image. May be redundant as they can be described with :ref:`NXtransformations`. + + :ref:`NXprocess_mpes`: + A base class specializing :ref:`NXprocess`, describing events of data processing, reconstruction, or analysis for photoemission-related data. + +.. _MpesCommonBC-BC: + +Common Base Classes +################### + +There are related base classes that are common to other techniques: + + :ref:`NXlens_em`: + A class to describe all types of lenses. Includes electrostatic lenses for electron energy analysers. + + :ref:`NXdeflector` + A class to describe all kinds of deflectors, including electrostatic and magnetostatic deflectors for electron energy analysers. + + :ref:`NXresolution`: + Describes the resolution of a physical quantity, e.g. the resolution of the MPES spectrometer. + + :ref:`NXfit`, :ref:`NXpeak`, :ref:`NXfit_background`, :ref:`NXfit_function`, :ref:`NXfit_parameter`: + Base classes for describing a fit procedure, e.g. a peak fitting in energy space in XPS. \ No newline at end of file diff --git a/manual/source/classes/base_classes/optical-spectroscopy-structure.rst b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst new file mode 100644 index 000000000..cf610fc21 --- /dev/null +++ b/manual/source/classes/base_classes/optical-spectroscopy-structure.rst @@ -0,0 +1,199 @@ +.. _Optical-Spectroscopy-Structure-BC: + +==================== +Optical Spectroscopy +==================== + +.. index:: + Ellipsometry + Raman + DispersiveMaterial + + +.. _Ellipsometry-BC: + +Ellipsometry +############ + +Ellipsometry is an optical characterization method to describe optical properties of interfaces and thickness of films. +The measurements are based on determining how the polarization state of light changes upon transmission and reflection. +Interpretation is based on Fresnel equations and numerical models of the optical properties of the materials. + +In the application definition, we provide a minimum set of description elements allowing for a reproducible recording of ellipsometry measurements. + +.. _Raman-BC: + +Raman +############ + +Raman spectroscopy is a characterization method to analyze vibrational properties for liquids, gases, or solids. +The measurements is based on the inelastic light scattering due to the material's vibrations. +Interpretation can be done based on peaks, which represent the phonon properties (intensity, center, width). + +The application definition contains a minimum of descriptive elements required to understand Raman spectroscopy measurements. + + +Application Definitions +----------------------- + + :ref:`NXoptical_spectroscopy`: + A generic application definition for spectroscopy measurements. This includes in particular ellipsometry and Raman spectroscopy measurements, but also other techniques such as photoluminescence, transmission, and reflection measurements. The requirements are: (i) an incident photon beam, (ii) a detector to measure scattered/emitted photons, and (iii) a sample. + + :ref:`NXellipsometry`: + An application definition for ellipsometry measurements, including complex systems up to variable angle spectroscopic ellipsometry. + + :ref:`NXraman`: + An application definition for Raman spectroscopy measurements. + + +Base Classes +------------ + +This is the set of base classes for describing an optical experiment. + + :ref:`NXbeam_device` + Beam devices are used to relate a beam, which has always at least one origin + and at least one destination. + + By referencing the beam devices with each other, a beam path can be + constructed. This can be used for vizualization or beam propery modeling + along the beam path. + + :ref:`NXbeam` + Beam properties such as intensity, polarization, wavelength or direction. + + :ref:`NXdetector` + A detector for signal detection. + + :ref:`NXsource` + A light source such as laser, lamp or LED. + + :ref:`NXmonochromator` + A monochromator is often used to energetically disperse the scattered or emitted light. + + :ref:`NXlens_opt` + Description of an optical lens. + + :ref:`NXwaveplate` + A waveplate or retarder. + + :ref:`NXsensor` + Specify external parameters that have influenced the sample such as + varied parameters e.g. temperature, pressure, pH value, beam intensity, etc. + + + +.. _DispersiveMaterial-BC: + +Dispersive Material +################### + +A dispersive material is a description for the optical dispersion of materials. +This description may be used to store optical model data from an ellipsometric analysis +(or any other technique) or to build a database of optical constants for optical properties of materials. + +Application Definition +---------------------- + + :ref:`NXdispersive_material`: + An application definition to describe the dispersive properties of a material. + The material may be isotropic, uniaxial or biaxial. Hence, it may contain up + to three dispersive functions or tables. + + + +Base Classes +------------ + +There is a set of base classes for describing a dispersion. + + :ref:`NXdispersion` + This is an umbrella base class for a group of dispersion functions to describe the material. + For a simple dispersion it may contain only on NXdispersion_function or NXdispersion_table entry. + If it contains multiple entries the actual dispersion is the sum of all dispersion functions and tables. + This allows for, e.g. splitting real and imaginary parts and describing them seperately or + adding a dielectric background (e.g. Sellmeier model) to an oscillator model (e.g. Lorentz). + + :ref:`NXdispersion_function` + This dispersion is described by a function and its single and repeated parameter values. + It follows a formula of the form ``eps = eps_inf + sum[A * lambda ** 2 / (lambda ** 2 - B ** 2)]`` + (Sellmeier formula). See the formula grammar below for an ebnf grammar for this form. + + :ref:`NXdispersion_single_parameter` + This denotes a parameter which is used outside the summed part of a dispersion function, + e.g. ``eps_inf`` in the formula example above. + + :ref:`NXdispersion_repeated_parameter` + This denotes arrays of repeated parameters which are used to build a sum of parameter values, e.g. + ``A`` and ``B`` are repeated parameters in the formula above. + + :ref:`NXdispersion_table` + This describes a tabular dispersion where the dielectric function is an array versus wavelength or energy. + +Formula Grammar +--------------- + +Below you find a grammar to which the formula should adhere and which can be used to parse and +evaluate the dispersion function. The terms ``single_param_name`` and ``param_name`` should be +filled with the respective single and repeated params from the stored data. +The grammer is written in the `EBNF `_ dialect +of `Lark `_, which is a parsing toolkit for python. +It is easily translatable to general EBNF and other parser generator dialects. +`Here `_ is a reference implementation in Rust/Python with a +`grammar `_ +written in `lalrpop `_. + +.. code-block:: + + ?assignment: "eps" "=" kkr_expression -> eps + | "n" "=" kkr_expression -> n + + ?kkr_expression: expression + | "" "+" "1j" "*" term -> kkr_term + + ?expression: term + | expression "+" term -> add + | expression "-" term -> sub + + ?term: factor + | term "*" factor -> mul + | term "/" factor -> div + + ?factor: power + | power "**" power -> power + + + ?power: "(" expression ")" + | FUNC "(" expression ")" -> func + | "sum" "[" repeated_expression "]" -> sum_expr + | NAME -> single_param_name + | SIGNED_NUMBER -> number + | BUILTIN -> builtin + + ?repeated_expression: repeated_term + | repeated_expression "+" repeated_term -> add + | repeated_expression "-" repeated_term -> sub + + + ?repeated_term: repeated_factor + | repeated_term "*" repeated_factor -> mul + | repeated_term "/" repeated_factor -> div + + ?repeated_factor: repeated_power + | repeated_power "**" repeated_power -> power + + ?repeated_power: "(" repeated_expression ")" + | FUNC "(" repeated_expression ")" -> func + | SIGNED_NUMBER -> number + | NAME -> param_name + | BUILTIN -> builtin + + FUNC.1: "sin" | "cos" | "tan" | "sqrt" | "dawsn" | "ln" | "log" | "heaviside" + BUILTIN.1: "1j" | "pi" | "eps_0" | "hbar" | "h" | "c" + + %import common.CNAME -> NAME + %import common.SIGNED_NUMBER + %import common.WS_INLINE + + %ignore WS_INLINE + From 98f2852b2a6b4996e710a104e08d5f8f408a287e Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:49:55 +0200 Subject: [PATCH 060/136] small update to mpes-structure --- manual/source/classes/base_classes/mpes-structure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/source/classes/base_classes/mpes-structure.rst b/manual/source/classes/base_classes/mpes-structure.rst index 80093d7e7..4610b5f90 100644 --- a/manual/source/classes/base_classes/mpes-structure.rst +++ b/manual/source/classes/base_classes/mpes-structure.rst @@ -43,7 +43,7 @@ Base Classes A base class to describe the complex manipulators used in photoemission experiments, often with > 4 degrees of freedom, cryogenic cooling and other advanced features. -Three base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: +Four base classes to describe data processing, which can be used as subclasses of :ref:`NXprocess` if describing post-processing or as subclasses of :ref:`NXdetector` if describing live, electronics level processing: :ref:`NXcalibration`: A base class to describe the 1D calibration of an axis, with a function mapping a raw data scale to a calibrated scale with the same number of points. From 8ab66fdaab941e040e04acd0bc10c5734d01dd5d Mon Sep 17 00:00:00 2001 From: Lukas Pielsticker <50139597+lukaspie@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:28:41 +0200 Subject: [PATCH 061/136] remove fairmat-specific files # Conflicts: # .github/workflows/ci.yaml # .github/workflows/fairmat-build-pages.yaml # .github/workflows/fairmat-clean-pages.yaml --- .github/workflows/ci.yaml | 7 +- .github/workflows/fairmat-build-pages.yaml | 45 ----- .github/workflows/fairmat-clean-pages.yaml | 24 --- dev_tools/globals/urls.py | 2 +- manual/source/_static/blockquote.css.bak | 23 --- manual/source/_static/to_alabaster.css | 73 ------- manual/source/_static/to_rtd.css | 10 - manual/source/apm-structure.rst | 9 - manual/source/cgms-structure.rst | 13 -- manual/source/em-structure.rst | 9 - manual/source/examples/index.rst | 6 +- manual/source/fairmat-cover.rst | 146 -------------- manual/source/icme-structure.rst | 9 - manual/source/img/FAIRmat.png | Bin 114746 -> 0 bytes manual/source/img/FAIRmat_new.png | Bin 10334 -> 0 bytes manual/source/img/FAIRmat_new_with_text.png | Bin 29306 -> 0 bytes manual/source/index.rst | 59 ++---- manual/source/laboratory-structure.rst | 9 - manual/source/nexus-index.rst | 20 -- manual/source/north-structure.rst | 26 --- .../source/optical-spectroscopy-structure.rst | 184 ------------------ manual/source/sed/entry-page.html | 6 - manual/source/sts-structure.rst | 8 - manual/source/transport-structure.rst | 14 -- requirements.txt | 2 +- 25 files changed, 27 insertions(+), 677 deletions(-) delete mode 100644 .github/workflows/fairmat-build-pages.yaml delete mode 100644 .github/workflows/fairmat-clean-pages.yaml delete mode 100644 manual/source/_static/blockquote.css.bak delete mode 100644 manual/source/_static/to_alabaster.css delete mode 100644 manual/source/_static/to_rtd.css delete mode 100644 manual/source/apm-structure.rst delete mode 100644 manual/source/cgms-structure.rst delete mode 100644 manual/source/em-structure.rst delete mode 100644 manual/source/fairmat-cover.rst delete mode 100644 manual/source/icme-structure.rst delete mode 100644 manual/source/img/FAIRmat.png delete mode 100644 manual/source/img/FAIRmat_new.png delete mode 100644 manual/source/img/FAIRmat_new_with_text.png delete mode 100644 manual/source/laboratory-structure.rst delete mode 100644 manual/source/nexus-index.rst delete mode 100644 manual/source/north-structure.rst delete mode 100644 manual/source/optical-spectroscopy-structure.rst delete mode 100644 manual/source/sed/entry-page.html delete mode 100644 manual/source/sts-structure.rst delete mode 100644 manual/source/transport-structure.rst diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 055b7eb75..4da534ddf 100755 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,12 +3,10 @@ name: Documentation build on: push: branches: - - main - - fairmat # push commit to the fairmat branch + - main # push commit to the main branch pull_request: branches: - - main - - fairmat # pull request to the fairmat branch + - main # pull request to the main branch workflow_dispatch: # allow manual triggering inputs: deploy: @@ -76,7 +74,6 @@ jobs: sudo apt-get update -y && \ sudo apt-get install -y \ latexmk \ - texlive-xetex \ texlive-latex-recommended \ texlive-latex-extra \ texlive-fonts-recommended diff --git a/.github/workflows/fairmat-build-pages.yaml b/.github/workflows/fairmat-build-pages.yaml deleted file mode 100644 index d228e735f..000000000 --- a/.github/workflows/fairmat-build-pages.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: GH pages fairmat proposal - -on: - push: - branches: [fairmat] - pull_request: - branches: [fairmat] - -jobs: - pages: - runs-on: ubuntu-20.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: install dependencies - run: pip install -r requirements.txt - - name: Get branch name - id: branch-name - uses: tj-actions/branch-names@v7 - - name: test - run: make test - - name: prepare - run: make prepare - - name: html - run: make html - - name: Deploy - if: steps.branch-name.outputs.is_default == 'true' - uses: JamesIves/github-pages-deploy-action@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - folder: build/manual/build/html - branch: fairmat-docs - target-folder: docs - clean: false - - name: Deploy PR - if: steps.branch-name.outputs.is_default == 'false' - uses: JamesIves/github-pages-deploy-action@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - folder: build/manual/build/html - branch: fairmat-docs - target-folder: docs/${{ steps.branch-name.outputs.current_branch }} - clean: false \ No newline at end of file diff --git a/.github/workflows/fairmat-clean-pages.yaml b/.github/workflows/fairmat-clean-pages.yaml deleted file mode 100644 index b70bd52e1..000000000 --- a/.github/workflows/fairmat-clean-pages.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: GH pages cleanup - -on: - delete: - -jobs: - cleanup: - if: github.event.ref_type == 'branch' - runs-on: ubuntu-latest - steps: - - name: Checkout pages - uses: actions/checkout@v2 - with: - ref: fairmat-docs - persist-credentials: false - fetch-depth: 0 - - name: Remove branch directory - run: rm -rf docs/${{ github.event.ref }} - - name: Commit & Push changes - uses: actions-js/push@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: fairmat-docs - message: Fairmat docs cleanup ${date} \ No newline at end of file diff --git a/dev_tools/globals/urls.py b/dev_tools/globals/urls.py index 2929070cc..729b7d102 100644 --- a/dev_tools/globals/urls.py +++ b/dev_tools/globals/urls.py @@ -1,2 +1,2 @@ -REPO_URL = "https://github.com/FAIRmat-NFDI/nexus_definitions/tree/fairmat" +REPO_URL = "https://github.com/nexusformat/definitions/blob/main" MANUAL_URL = "https://manual.nexusformat.org" diff --git a/manual/source/_static/blockquote.css.bak b/manual/source/_static/blockquote.css.bak deleted file mode 100644 index 4ce6e9b98..000000000 --- a/manual/source/_static/blockquote.css.bak +++ /dev/null @@ -1,23 +0,0 @@ -/* - * blockquote.css - * ~~~~~~~~~~~~~~~ - * - * custom Sphinx stylesheet -- define margins in blockquotes with NXDL documentation - * - * :see: http://stackoverflow.com/questions/23462494/how-to-add-custom-css-file - * - */ - -/* do NOT import, causes sidebar to disappear, see issue 341 -@import url("basic.css"); -*/ - -/* -- page layout ----------------------------------------------------------- */ - -/* github issue 341: nicer to solve this just for NXDL documentation files - * but this works for now - */ - -blockquote { - margin-right: 100px; -} diff --git a/manual/source/_static/to_alabaster.css b/manual/source/_static/to_alabaster.css deleted file mode 100644 index cf2c82d78..000000000 --- a/manual/source/_static/to_alabaster.css +++ /dev/null @@ -1,73 +0,0 @@ -/* Theme override commands to control the html aspect in alabaster sphinx theme */ - -/* Override sidebar background color default (#FFFFFF) */ -.sphinxsidebar { - background: #55af31 !important; - } -/* #005F73 is the original NIAC sidebar colour */ - -div.document { - margin-top: 0 !important; -} - -div.body { - margin-top: 30px !important; -} - - /* Control logo positioning */ -.sphinxsidebarwrapper p.logo { - padding: 15% !important; - text-align: center !important; -} - -/* Control sidebar headers (non clickable)*/ -.sphinxsidebarwrapper h3 { - font-size: 18pt !important; -} - -/* Control logo name string */ -.sphinxsidebarwrapper h1.logo { - margin-top: 0px !important; - font-size: 21pt !important; - margin-bottom: 10px !important; -} - -/* Control TOC tree top level links */ -.sphinxsidebar ul li.toctree-l1 > a { - font-size: 11pt !important; - line-height: 1.8 !important; -} - -/* Control TOC tree second level links */ -.sphinxsidebar ul li.toctree-l2 > a { - font-size: 10pt !important; - line-height: 1.8 !important; -} - -/* Control quick search bar */ -.sphinxsidebar input { - margin-top: 5px !important; - margin-bottom: 12px !important; -} - -/* Control quick search bar wrapper, nasty alignment with the google search bar */ -.sphinxsidebar div.searchformwrapper { - width: 209px !important; - align-self: center !important; - margin-left: 3px !important; -} - -/* Control text blurb explaining the project under the logo name */ -.sphinxsidebarwrapper p.blurb { - margin-top: 10px !important; - margin-bottom: 20px !important; -} - -/* Slightly increase the padding in the body */ -.bodywrapper div.body { - padding: 0 45px 0 45px !important; -} - -.body h1 { - margin-bottom: 50px !important; -} \ No newline at end of file diff --git a/manual/source/_static/to_rtd.css b/manual/source/_static/to_rtd.css deleted file mode 100644 index 0b6947542..000000000 --- a/manual/source/_static/to_rtd.css +++ /dev/null @@ -1,10 +0,0 @@ -/* Theme override commands to control the html aspect in read the docs sphinx theme*/ - -/* Sidebar header (and topbar for mobile) */ -.wy-side-nav-search, .wy-nav-top { - background: #FF331C; - } -/* Sidebar */ -.wy-nav-side { - background: #005F73; - } \ No newline at end of file diff --git a/manual/source/apm-structure.rst b/manual/source/apm-structure.rst deleted file mode 100644 index 581e2ec5b..000000000 --- a/manual/source/apm-structure.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _Apm-Structure-Fairmat: - -===================== -Atom-probe tomography -===================== - -Atom probe tomography and related field-ion microscopy, aka atom probe microscopy (techniques) cover metrology methods with an origin in the materials science and condensed-matter physics communities. With its maturation and commercialization in the last two decades atom probe is increasingly being used for characterization of bio materials and fundamental science of field evaporation physics. - -A status report of the ongoing work on data schemas for atom probe using NeXus is available here: :ref:`Apm-Structure`. diff --git a/manual/source/cgms-structure.rst b/manual/source/cgms-structure.rst deleted file mode 100644 index 563479b17..000000000 --- a/manual/source/cgms-structure.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _Cg-Structure-Fairmat: - -============================ -Geometry and microstructures -============================ - -Computational geometry is a frequently used tool for describing the shape and geometry of structural features in materials and components of instruments used for materials characterization. -NeXus has a long history of base classes which serve specifically the former tasks. Upon closer inspection during the first year of the FAIRmat project we found though that the collection of -base classes could profit from an extension to make working with computational geometry data in NeXus simpler and more fine-grained. - -A status report of this ongoing work is available here: :ref:`CgmsFeatures-Structure`. - -A status report of how these definitions can be of value for the field of Integrated Materials Engineering (ICME) is available here: :ref:`Icme-Structure`. diff --git a/manual/source/em-structure.rst b/manual/source/em-structure.rst deleted file mode 100644 index 148e513aa..000000000 --- a/manual/source/em-structure.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _Em-Structure-Fairmat: - -=================== -Electron microscopy -=================== - -Electron microscopy is a cross-cutting characterization technique of key demand and relevance within materials science, materials engineering, and bio-science/omics research communities. - -A status report of the ongoing work on data schemas for electron microscopy using NeXus is available here: :ref:`Em-Structure`. diff --git a/manual/source/examples/index.rst b/manual/source/examples/index.rst index 52407feb0..dbea811c4 100644 --- a/manual/source/examples/index.rst +++ b/manual/source/examples/index.rst @@ -1,8 +1,8 @@ .. _Examples: -============================== -NeXus: Examples data files I/O -============================== +================================================ +Examples of writing and reading NeXus data files +================================================ .. .. image:: ../img/NeXus.png diff --git a/manual/source/fairmat-cover.rst b/manual/source/fairmat-cover.rst deleted file mode 100644 index 9545073b6..000000000 --- a/manual/source/fairmat-cover.rst +++ /dev/null @@ -1,146 +0,0 @@ -.. _FairmatCover: - -======================= -FAIRmat-NeXus Proposal -======================= - -.. index:: - IntroductionCover - OurScope - Outreach - WhichData - WhatIsNew - -Aim -######################### - -Experiments nowadays create a set of very often voluminous and diverse numerical data and metadata. -These pieces of information represent entities of what is effectively a graph of materials data. -This graph can have a very large number of nodes and edges representing the large variety of -relations which scientists ideally want to identify and master -when transforming experimental research into knowledge. - -Experimentalists face the challenge that these pieces of information come at different levels -of granularity and format, of which many need to be better documented. You have very likely experienced -yourself how file and data formats are routinely encountered tasks to master in your daily -research practice and you might have questioned how these formats are currently handled -when you want to produce FAIR research data and publications. - -The NeXus-FAIRmat proposal is an interdisciplinary data science activity initiated by scientists of the -condensed-matter physics community which strives to develop community-maintained open file and data formats -for describing specific experimental techniques, their numerical data and metadata, -and strategies how to exchange these pieces of information. - -.. _IntroductionCover: - -The FAIRmat proposal to NeXus is an effort by the community of scientists of the `FAIRmat consortium `_ -to refine and expand the structure of NeXus. As a project which aims at creating an infrastructure -for experimental data to be findable, accessible, interoperable, and reusable (FAIR) in the fields of -condensed-matter physics and the chemical physics of solids, FAIRmat has adopted NeXus as the common format. - -`NeXus `_ is a common data exchange format which has its origin in the community of -scientists performing neutron, x-ray, and muon experiments. The development of NeXus is coordinated by the -NeXus International Advisory Committee (NIAC). -NeXus defines a schema of data entries with a controlled vocabulary and defined relations between the entries. -NeXus offers not only tools to document these schema definitions in a version-controlled manner but -also tools to check and verify how and if specific instances of NeXus schemata comply with the intended -schema definition when the data are written to files. Although, the Hierarchical Data Format (HDF5) is the -most commonly used file format to write NeXus file to, NeXus can also be used with other file formats. - -NeXus defines domain-specific rules for organizing data in e.g. HDF5 files (:ref:`application.definitions`) -and defines a dictionary of well-defined domain-specific (a vocabulary) of terms (:ref:`base.class.definitions`). -The meta- and numerical data in a NeXus file represent a hierarchical graph which encodes a specifically -granularized representation of relevant pieces of information and results that should be stored with -an experiment. - -Base classes and application definitions are two key components of the NeXus data model. -A base class represents a set of numerical data and metadata which specify details about -scientists, projects, instruments, and other physical devices, including the numerical data -and metadata which are deemed relevant for their description and the associated -computational analyses. Application definitions are constructed from combining such experiment- -and research-question-specifically customized base classes. - -In this combination, an application definition is a data contract between -a producer and a consumer of these scientific data. - -This design has sufficient flexibility to cover any experimental technique and instrumentation, while -ensuring rigorous, application-specific structures that can be processed in an automated manner. - -In cases where base classes or application definitions have not yet been proposed advantage of NeXus can be taken -if the respective scientific community explicitly designs, implements, uses, and continuously evolves -these classes and definitions. Here the role of the NIAC is to support the community with -data modeling and data science technical expertise, thus taking an important role of -cross-disciplinary review. - -The NeXus-FAIRmat proposal represents the results of this development for experiments and use cases which have not yet used NeXus. -Specifically, the proposal includes cases in the materials-science-branch of electron microscopy (EM), photo-emission spectroscopy, -ellipsometry, and the field of atom probe tomography and related field-ion microscopy, here jointly referred to as atom probe microscopy. - - -The documentation available here includes parts of the contents of the NeXus User Manual (also available `here `_), -reported here for the convenience of the user, but is restricted to the parts most pertinent to the our proposal. - -For more extensive information, please visit the original manual. - -.. _OurScope: - -Our scope and perspective -######################### - -Thanks to a cooperative approach across a wide variety of experimental techniques, -the NeXus-FAIRmat proposal of the FAIRmat project has an opportunity -to expand the set of data/metadata accurately described via NeXus. - -With a closely-connected team of domain experts, we will develop such expansion while at the same time maintaining -a consistent structure across different techniques and methods, striving for the maximum simplicity of use. - -Achieving a standardized and FAIR data structure has a wide spectrum of advantages, ranging from radical -progress in scientific transparency to the development of new, far-reaching tools that can be shared across -the whole scientific community. The convenience of such tools can range from guaranteeing data reusability within -a single lab, to enabling open-source availability of ready-to-use advanced analysis software. - -Perhaps the greatest resource, however, is the inclusion of experimental datasets in the `NOMAD Laboratory `_: -a data infrastructure that already hosts the largest computational material science repository in the world, representing a -homogeneous and machine-readable archive, a human-accessible encyclopedia of materials data -with tools for automated artificial intelligence analyses and data access. - -.. _Outreach: - -Outreach to the community -########################## - -A data infrastructure is not effective if it does not integrate seamlessly in the day-to-day workflow of a laboratory. -For this reason, we approach our newly developed NeXus proposal as a community-driven development. -We have drafted an accurate and consistent expansion of NeXus capabilities for a number of lab-based techniques, -but need extensive testing and tweaking of its characteristics by the community. - -If your data is generated with these techniques and you are interested in producing FAIR data and accessing the FAIRmat tools, we -invite you to try out our proposed structure. If you find any conflicts or inconsistencies, please raise them to us using the -comment section. These comments are implemented with `Hypothesis `_, a modern web annotation -tool from the journalism community. The commenting function for each page of the proposal enable you to contribute to the -creation of a more consistent and practical NeXus structure which, in our firm belief, can serve your community and beyond. - -If you do not find your specific experimental technique but would be interested in participating in the development -of a standard using NeXus, feel also very much invited to contact us directly at the `FAIRmat-Team `_. - -.. _WhichData: - -Which data should I convert? -############################ - -You are free to choose at which point in the workflow you wish to convert the data to NeXus, as its flexibility allows to -describe raw data, pre-processed data and fully processed data. As an entry step, we suggest to use a test dataset -that is fully processed and already published (or, alternatively, of negligible scientific content). These datasets, indeed, require often the most -extensive metadata description, but are most easily converted to NeXus, with minimal to no impact on the data processing pipeline. - -In fact, a low barrier (but high yield!) way to participate to FAIRmat consists in converting only fully processed datasets that -are used for a publication, and publishing them via FAIRmat only when your manuscript is in press. This makes the task of -converting to NeXus much more sporadic than fairifying raw data, to the point that it may be even acceptable not to automate it. At the same time, -it guarantees full control on the data until publication. We are confident that if you take this approach, more appetite will come with eating, -and you will be naturally inclined to gradually integrate FAIRmat structures and tools further in your workflow. - - -.. _WhatIsNew: - -.. What is New? -.. ############## diff --git a/manual/source/icme-structure.rst b/manual/source/icme-structure.rst deleted file mode 100644 index 8ff31eaf7..000000000 --- a/manual/source/icme-structure.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _Icme-Structure-Fairmat: - -============================================== -Integrated Computational Materials Engineering -============================================== - -With a large set of data schemas for computational geometry, and methods from condensed-matter physics as well as materials engineering we are convinced that the NeXus standardization framework can be one component of efforts to harmonize and consolidate the zoo of descriptions and data schemas used within the field of Integrated Computational Materials Engineering (ICME). - -A status report along these lines of thoughts and ongoing efforts is available here: :ref:`Icme-Structure`. diff --git a/manual/source/img/FAIRmat.png b/manual/source/img/FAIRmat.png deleted file mode 100644 index 034aa452deb2c7695940d513cf0efe94291a1d69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114746 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