import freephil

# scope for the geometry input - N.B. having to unroll the input for structured
# axis definitions as PHIL does not work well with complex data structures ->
# have axis names, axis values, ... as separate parameters. Ah, this already
# exists as a goniometer phil scope in dxtbx. Will have to assume that the
# axes are presented in order... ah, no, because we need translation axes in
# the stack as well.

scope = freephil.parse(
    """
output {
  data_file_template = nexus_%06d.h5
    .type = path
    .help = "Filename template for data files"
  master_file_name = nexus_master.h5
    .type = path
    .help = "Filename for master file"
}
input {
  coordinate_frame = mcstas *imgcif
    .type = choice
    .help = "Which coordinate system is being used to provide input vectors"
  n_images = 2
    .type = int
    .help = "Number of blank images to be generated per file"
  n_events = 100000
    .type = int
    .help = "Length of event stream per file"
  detector {
    mode = *images events
      .type = choice
      .help = "Which kind of data is generated by the detector."
    description = Eiger 2XE 16M
      .type = str
      .help = "Detector class to record"
    sensor_material = *Si CdTe
      .type = choice
      .help = "Sensor material (e.g. silicon)"
    sensor_thickness = 0.320
      .type = float
      .help = "Sensor thickness, mm"
    overload = 65535
      .type = int
      .help = "Pixels >= this value are invalid due to overloading"
    underload = -1
      .type = int
      .help = "Pixels <= this value are invalid"
    pixel_size = 0.075 0.075
      .type = floats(size = 2)
      .help = "Pixel size in mm"
    beam_center = 2214.355 2300.496
      .type = floats(size = 2)
      .help = "Beam position on the detector"
    flatfield = None
      .type = path
      .help = "If path is given, add flatfield correction data field"
    pixel_mask = None
      .type = path
      .help = "if path is given, add link to bad pixel mask"
# for the moment only considering single modules but will have to consider
# multiple modules in the not too distant future
    image_size = 4362 4148
      .type = ints(size = 2)
      .help = "Image size, slow, fast"
    exposure_time = 0.004
      .type = float
      .help = "Nominal exposure time, seconds"
# taken as a given that fast axis sits on slow axis which sits on last axis
# named below - should probably sort out the axis offset definition i.e. are
# the offsets applied before or after the axis shift?
    fast_axis = 1 0 0
      .type = floats(size = 3)
      .help = "Fast axis at datum position"
    slow_axis = 0 -1 0
      .type = floats(size = 3)
      .help = "Slow axis at datum position"
    offsets = -166.2 172.1 0 0 0 0
      .type = floats
      .help = "Axis offsets - one after the other - fast then slow"
    module_offset = False
      .type = bool
      .help = "If set to true, calculates offset of the module in regard to detector origin and creates corresponding field"
    axes = two_theta det_z
      .type = strings
      .help = "Axis names for the detector axes"
    depends = . two_theta
      .type = strings
      .help = "Axis names for the axis dependencies"
    vectors = 1 0 0 0 0 -1
      .type = floats
      .help = "Axis vectors - one after the other"
    starts = 0.0 100.0
      .type = floats
      .help = "Starting values for axes"
    ends = 0.0 100.0
      .type = floats
      .help = "Ending values for axes, only different to start for scan axis"
    increments = 0.0 0.0
      .type = floats
      .help = "Increment values for axes, non-zero only for scan axis"
    types = rotation translation
      .type = strings
      .help = "Axis types, rotation or translation"
    units = deg mm
      .type = strings
      .help = "Axis units, from mm or deg"
  }

  goniometer {
# sample is assumed to sit on the last of tehse axes
    axes = omega sam_z sam_y sam_x chi phi
      .type = strings
      .help = "Axis names for the goniometer axes"
    depends = . omega sam_z sam_y sam_x chi
      .type = strings
      .help = "Axis names for the axis dependencies"
    vectors = 1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 1 0 0
      .type = floats
      .help = "Axis vectors - one after the other"
    offsets = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      .type = floats
      .help = "Axis offsets - one after the other"
    starts = 0.0 0.0 0.0 0.0 0.0 0.0
      .type = floats
      .help = "Starting values for axes"
    ends = 90.0 0.0 0.0 0.0 0.0 0.0
      .type = floats
      .help = "Ending values for axes, only different to start for scan axis"
    increments = 0.1 0.0 0.0 0.0 0.0 0.0
      .type = floats
      .help = "Increment values for axes, non-zero only for scan axis"
    types = rotation translation translation translation rotation rotation
      .type = strings
      .help = "Axis types, rotation or translation"
    units = deg mm mm mm deg deg deg
      .type = strings
      .help = "Axis units, from mm or deg"
  }

  beamline {
    source {
      name = Diamond Light Source
        .type = str
        .help = "Facility name"
      short_name = DLS
        .type = str
        .help = "Facility abbreviation"
      type = Synchrotron X-ray Source
        .type = str
        .help = "Facility type"
    }
  }
  beam {
    wavelength = 0.979590
      .type = float
      .help = "Wavelength of incident beam, angstroms"
    flux = 268717230611.358
      .type = float
      .help = "Flux of incident beam, ph / s"
  }
  attenuator {
    transmission = 1
      .type = float
      .help = "Attenuation of beam intensity"
  }

# these are ornamental since there was never an experiment
  start_time = Wed Nov 18 11:08:02 2020
    .type = str
    .help = "Experiment start time"
  end_time = Wed Nov 18 11:08:02 2020
    .type = str
    .help = "Experiment end time"
}
"""
)

if __name__ == "__main__":
    print(scope.as_str())
