Skip to content

Estimate transmission wrapper#365

Open
pjnaughton wants to merge 13 commits into
mainfrom
estimate_transmission_wrapper
Open

Estimate transmission wrapper#365
pjnaughton wants to merge 13 commits into
mainfrom
estimate_transmission_wrapper

Conversation

@pjnaughton
Copy link
Copy Markdown
Collaborator

Wrapper to estimate the max recommended transmission from dials.find_spots.

@pjnaughton pjnaughton self-assigned this May 12, 2026
@pjnaughton pjnaughton requested a review from pblowey May 12, 2026 14:15
Comment on lines +203 to 211
transmission_limits = (get_beamline_param(
beamline_config, ("gda.mx.udc.minTransmission",), 0.0),
min(
get_beamline_param(
beamline_config, ("gda.mx.udc.maxTransmission",), 1.0
),
recommended_max_transmission
),
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed on slack that rather than using the recommended_max transmission to set the transmission limits, the recommended transmission should be used in place of recipe_step.transmission (i.e. instead of the transmission value from the Agamemnon recipe). This means that the recommended transmission will be scaled appropriately for wavelength and resolution.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested with Phasing which has a recommended transmission of .25, and the recommended transmission from our wrapper is .44 and after scaling it returns to use .36 transmission in the dc. You can see it at https://ispyb-test.diamond.ac.uk/dc/visit/mx23694-156/id/21149301 for Phasing wedge 1

for command, script, output_file in commands:
result = subprocess.run(script, cwd=working_directory, check=True)

while not os.path.exists(output_file):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this step necessary? Have you found that the dials.import subprocess returns without the output files existing?


reflection_file = results_directory / "strong.refl"
reflections = flex.reflection_table.from_file(reflection_file)
num_counts, _ = self.build_hist_from_reflections(reflections)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you've gone to the trouble of constructing a histogram, it would be good to plot this and have it as an output file. Additionally, you could output the histogram similarly to how xia2.overload does, so that the data is available as a result file. If this takes a some time to process, you could always run this after the wrapper sends the scaled_transmission off to the next recipe step, so that the pipeline is not slowed down.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The histogram can just be saved using json.dump(...) and does not take much time. Would there be another why using JSONLines is preferable?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason to use JSONLines, you can just create it in the wrapper as you have done

return False

results_directory.mkdir(parents=True, exist_ok=True)
output_files = ["dials.find_spots.log", "strong.refl", "imported.expt"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The strong.refl and imported.expt are probably not too useful to have as results files so I would omit them from here. I think it would be useful to construct a log file for this wrapper, that gives a simple overview of the running of the dials commands as well as the analysis of the spots afterwards.

Comment on lines +2899 to +2907
curr_program = find_process_program.filter(
AutoProcProgram.autoProcProgramId == parameters.program_id
).scalar()
# xia2 dials occassionaly gives optimistic estimate for resolution
if curr_program == "xia2 dials":
self.log.info(
f"Skipping strategy trigger for dcid={parameters.dcid} from program: xia2 dials."
)
return {"success": True}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This query/check isn't needed. We can avoid triggering for xia2-dials by simply not including the call to the trigger service in the xia2-dials recipe(s).

Comment on lines +137 to +172
def draw_plot(self, counts, pixels):
"""Create ASCII art histogram"""

self.log.info("Plotting pixel intensities...")

width, height = 60, 20
title = "'Pixel intensity distribution'"
xlabel = "'Num counts'"
ylabel = "'Counts'"

command = ["gnuplot"]
plot_commands = [
"set term dumb %d %d" % (width, height - 2),
"set logscale y",
"set logscale x",
"set ytics out",
"set title %s" % title,
"set xlabel %s" % xlabel,
"set ylabel %s offset character %d,0" % (ylabel, len(ylabel) // 2),
]

data_string = "\n".join(f"{x} {y}" for x, y in zip(counts[1:], pixels[1:]))

plot_commands.append("plot '-' using 1:2 title '' with lines")
plot_commands.append(data_string)

try:
result = subprocess.run(
command, input="\n".join(plot_commands), text=True, capture_output=True
)
except (OSError, subprocess.TimeoutExpired) as e:
self.log.info("Error plotting counts vs pixels")
self.log.info(e)
return
else:
self.log.info(result.stdout)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid having gnuplot as a dependency. I'd be happy just to have a matplotlib png of the histogram as an output.

return len(num_pixels)

def save_hist_to_json(self, hist, max_trusted_value, results_dir):
results_path = results_dir / "overload.json"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could give this a more informative name and don't need to follow the xia2_overload filename. Something like pixel_count_histogram.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants