COMCIFS / Powder_Dictionary

CIF definitions for powder diffraction
4 stars 4 forks source link

`PD_INSTR` and `PD_INSTR_DETECTOR` extension #157

Open rowlesmr opened 1 year ago

rowlesmr commented 1 year ago

There needs at least parallel and elliptical focussing mirrors, as well as more dataitems to describe the detector

mirrors

PD_INSTR has _pd_instr.2theta_monochr_pre and PD_INSTR_DETECTOR has _pd_instr.2theta_monochr_post which have the value of the mono angle.

There could be _pd_instr.2theta_mirror_pre and _pd_instr.2theta_mirror_post, which takes the value 'parallel' or 'focussing', where it is assumed that the focus is on the detector (or source for a diffracted beam focussing mirror, whatever that means...).

An alternate value is to give the distance of the focal point from the optic; parallel == 0, and focussing == some finite value. This allows for mirrors that don't focus on the detector.

Detectors

There needs to be more dataitems to describe strip detectors. These are small, linear position-sensitive detectors which have ~100-300 channels. The channels are normally opaque to the user, and you just get one, pre-made diffraction pattern, rather than a bunch you need to merge.

Suggestions:

jamesrhester commented 1 year ago

As far as I can tell, multi-pixel detector geometry is completely covered by the imgCIF dictionary, including laying out all of the relevant axes. Once our raw powder data working group starts up as part of an IUCr journals project, we'll have a better idea of what is missing and we can feed back that information here.

Mirrors are an excellent idea. We should be able to recreate a geometrical layout of the instrument suitable for simulation calculations.

rowlesmr commented 1 year ago

Moved from #162

(https://github.com/COMCIFS/Powder_Dictionary/pull/162#issuecomment-1610825834) _pd_instr_mirror can then reference _order_along_beam to locate the mirror it is describing.

That's not going to work, as _pd_instr_mono needs to give a mono angle, as well as reference into the list.

.

First pass at something (all names are probably terrible, and there is at least one thing @jamesrhester doesn't like*):

The inner details could also be hidden, a la how PD_INSTR and PD_INSTR_DETECTOR currently do it with datanames not being \<category>.\<object>.

PD_INSTR_ORDER: Loop category. Indexed on _pd_instr.id, order, optic_type, and optic_value.

Dataitems:

The enumeration values of _pd_instr_order.optic_type would be:

A similar thing would apply for PD_INSTR_ORDER_DETECTOR: Loop category. Indexed on _pd_instr_detector.id, order, optic_type, and optic_value. 0th optic is the specimen. The last optic is the detector. (or should it be the other way around?)

Examples:

data_first
_pd_instr.id UUID
loop_
_pd_instr_order.order
_pd_instr_order.optic_type
_pd_instr_order.optic_value
0   source               .     # X-rays come from here.
1   eq_divg              0.3   # There is a divergence slit set to 0.3°.
2   eq_divg              0.6   # There is an anti-scatter slit set to 0.6°.
3   ax_soller            3.5   # A set of axial Soller slits at 3.5°.
4   ax_slit             10.0   # A mask to cut the beam off at 10.0 mm wide.
5   ax_spec_beam_size   10.7   # The beam width at the specimen is 10.7 mm.
5   spec                 .     # The specimen.

data_second
_pd_instr.id UUID2
loop_
_pd_instr_order.order
_pd_instr_order.optic_type
_pd_instr_order.optic_value
_pd_instr_order.distance_from_virt_source
0   source               .     -40.0      # X-rays come from here.
0   ax_source_size      12.0   -40.0      # LFF tube, so 12 mm is a std size
0   eq_source_size       0.4   -40.0      # at the normal takeoff angle, 0.4 mm is about right
1   ax_soller            5.0   -35.0      # A set of axial Soller slits at 5.0° between the source and mono
2   eq_divg              0.5   -30.5      # There is a divergence slit set to 0.5° between the source and mono
2   ax_slit             12.0   -30.5      # A mask to cut the beam off at 12.0 mm wide between the source and mono
3   mono                26.6   -20.5      # A mono set at 26.6° 2\q
4   eq_slit              0.1     0.0      # 0.1 mm slit which is on the detector circle.
4   virt_source          .       0.0      # This is a "standard" BB instr with a pre-spec mono, so "here" is where the x-rays come from    
5   eq_divg              0.3    15.0      # There is a divergence slit set to 0.3°.
6   ax_soller            3.5    20.0      # A set of axial Soller slits at 3.5°.
7   ax_slit             10.0    25.0      # A mask to cut the beam off at 10.0 mm wide.
8   ax_spec_beam_size   10.7   250.0      # The beam width at the specimen is 10.7 mm.
8   spec                 .     250.0      # The specimen.

data_third
_pd_instr.id UUID3
loop_
_pd_instr_order.order
_pd_instr_order.optic_type
_pd_instr_order.optic_value_mm
_pd_instr_order.optic_value_deg
0   source               .      .
0   ax_source_size      12.0    .
0   eq_source_size       0.4    .
1   ax_soller            .      5.0
2   eq_slit              .      0.5
2   ax_slit             12.0    .
3   mono                 .     26.6
4   eq_slit              0.1    .
4   virt_source          .      .
5   eq_slit              .      0.3
6   eq_slit              .      0.6
7   ax_soller            .      3.5
8   ax_slit             10.0    .
9   ax_spec_beam_size   10.7    .
9   spec                 .      .
jamesrhester commented 1 year ago

OK. So some comments.

  1. It is going in the right direction
  2. I prefer pd_instr_layout as the name, or even pd_instr_component
  3. There should be a separate _pd_instr_component.id as one of the key data names, as order is not unique and the combination of order and optic_type, which could be unique, I guess, means that other categories would also need to use child data names of these two in order to refer to a component (see next point). Also, are we really willing to assert that no two optical elements at the same position will have the same type (because value is not a good idea, see next point)?
  4. As you correctly asterisk, _pd_instr_order.optic_value is a big no-no, with the interpretation of the item depending on the value of some other item. The correct way to do this is for _pd_instr_component.id to be referred to in the relevant other loops describing the mono/mirror/slits/doohickey. That way you're not limited to one value, can describe each component in glorious detail, have a lot more per-component flexibility. In this scheme optic_type is a bit superfluous, but a useful check.
  5. The distances should definitely be along the beam direction, not straight line. If straight line, then you need a direction as well in order to locate it.
  6. Good catch that _pd_instr.id has to be linked and one of the keys.

But actually it's not that far off being pretty fit for purpose. The only danger is that we'll end up defining a whole separate dictionary that is useful for general beamline description that "everyone" will want to use.

rowlesmr commented 1 year ago

the relevant other loops describing the mono/mirror/slits/doohickey

This is the bit I couldn't figure out how to do without having essentially a diagonal loop, and why I went with the evil solution.

Given a component ordering:

data_fourth
_pd_instr.id UUID4
loop_
_pd_instr_component.id
_pd_instr_component.order
a   0   # source               .      .
b   0   # ax_source_size      12.0    .
c   0   # eq_source_size       0.4    .
d   1   # ax_soller            .      5.0
e   2   # eq_slit              .      0.5
f   2   # ax_slit             12.0    .
g   3   # mono                 .     26.6
h   4   # eq_slit              0.1    .
i   4   # virt_source          .      .
j   5   # eq_divg              .      0.3
k   6   # eq_divg              .      0.6
l   7   # ax_soller            .      3.5
m   8   # ax_slit             10.0    .
n   9   # ax_spec_beam_size   10.7    .
o   9   # spec                 .      .

How to assign a value to the component and associate it with its order?

One way is to have one big loop

# single category solution
loop_
_pd_instr_details.component_id
_pd_instr_details.source   
_pd_instr_details.ax_source_size   
_pd_instr_details.eq_source_size   
_pd_instr_details.ax_soller        
_pd_instr_details.eq_slit          
_pd_instr_details.ax_slit          
_pd_instr_details.mono                   
_pd_instr_details.virt_source   
_pd_instr_details.eq_divg
_pd_instr_details.ax_spec_beam_size
_pd_instr_details.spec             
a   Cu .    .   .   .   .    .    . .   .    .
b   .  12.0 .   .   .   .    .    . .   .    . 
c   .  .    0.4 .   .   .    .    . .   .    . 
d   .  .    .   5.0 .   .    .    . .   .    .
e   .  .    .   .   0.5 .    .    . .   .    .
f   .  .    .   .   .   12.0 .    . .   .    .
g   .  .    .   .   .   .    26.6 . .   .    .
h   .  .    .   .   0.1 .    .    . .   .    .
i   .  .    .   .   .   .    .    1 .   .    .
j   .  .    .   .   .   .    .    . 0.3 .    .
k   .  .    .   .   .   .    .    . 0.6 .    .
l   .  .    .   3.5 .   .    .    . .   .    .
m   .  .    .   .   .   10.0 .    . .   .    .
n   .  .    .   .   .   .    .    . .   10.7 .
o   .  .    .   .   .   .    .    . .   .    1

But it is nearly diagonal, wastes a lot of space and is hard to write and read.

The second way is to have many categories:

# many category solution
loop_
_pd_instr_source.component_id
_pd_instr_source.source   
_pd_instr_source.ax_size   
_pd_instr_source.eq_size
a   Cu .    .  
b   .  12.0 .  
c   .  .    0.4

loop_
_pd_instr_soller.component_id
_pd_instr_soller.ax
d   5.0 
l   3.5 

loop_
_pd_instr_slit.component_id
_pd_instr_slit.eq          
_pd_instr_slit.ax          
e   0.5  .
f   .    12.0
h   0.1  .
m   .    10.0

loop_
_pd_instr_mono.component_id
_pd_instr_mono.angle  
g   26.6

loop_
_pd_instr_vsrc.component_id
_pd_instr_vsrc.vsrc  
i   1

loop_
_pd_instr_divg.component_id
_pd_instr_divg.eq  
j   0.3 
k   0.6 

loop_
_pd_instr_spec.component_id
_pd_instr_spec.ax_beam_size
_pd_instr_spec.spec             
n   10.7 .
o   .    1

which has it's own problems in terms of managing the number of loops.

jamesrhester commented 1 year ago

The many categories approach is preferable, because it is robust to extension. Conceivably these categories could expand in the future with geometric descriptions, manufacturing details, whatever. There is no harm in having many categories, and that just reflects the fact that these are all different things with different needs. We could consider placing all slits into a single category, though.

rowlesmr commented 1 year ago

This could very quickly lead down the path of a thing for a separate dictionary!

jamesrhester commented 1 year ago

This could very quickly lead down the path of a thing for a separate dictionary!

Yep. At which point one asks oneself what is most important to get done first.

rowlesmr commented 1 year ago

Yeah, nah.