Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CATKIT-96: Reduce file IO overhead for sending commands to BMC #236

Merged
merged 5 commits into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 21 additions & 30 deletions catkit/hardware/boston/DmCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
m_per_volt_map1 = None # for caching the conversion factor, to avoid reading from disk each time
m_per_volt_map2 = None # for caching the conversion factor, to avoid reading from disk each time

flat_map_dm1 = None # for caching the conversion factor, to avoid reading from disk each time
flat_map_dm2 = None # for caching the conversion factor, to avoid reading from disk each time

class DmCommand(object):
def __init__(self, data, dm_num, flat_map=False, bias=False, as_voltage_percentage=False,
Expand Down Expand Up @@ -107,14 +109,7 @@ def to_dm_command(self):

# OR apply Flat Map (which is itself biased).
elif self.flat_map:
if self.dm_num == 1:
flat_map_file_name = CONFIG_INI.get("boston_kilo952", "flat_map_dm1")
flat_map_volts = fits.open(os.path.join(self.calibration_data_path, flat_map_file_name))
dm_command += flat_map_volts[0].data
else:
flat_map_file_name = CONFIG_INI.get("boston_kilo952", "flat_map_dm2")
flat_map_volts = fits.open(os.path.join(self.calibration_data_path, flat_map_file_name))
dm_command += flat_map_volts[0].data
dm_command += get_flat_map_volts(self.dm_num)

# Convert between 0-1.
dm_command /= self.max_volts
Expand Down Expand Up @@ -191,14 +186,18 @@ def get_flat_map_volts(dm_num):
calibration_data_path = os.path.join(catkit.util.find_package_location(calibration_data_package),
"hardware",
"boston")
if dm_num == 1:
flat_map_file_name = CONFIG_INI.get("boston_kilo952", "flat_map_dm1")
flat_map_volts = fits.open(os.path.join(calibration_data_path, flat_map_file_name))
return flat_map_volts[0].data
else:
flat_map_file_name = CONFIG_INI.get("boston_kilo952", "flat_map_dm2")
flat_map_volts = fits.open(os.path.join(calibration_data_path, flat_map_file_name))
return flat_map_volts[0].data

global flat_map_dm1, flat_map_dm2

if flat_map_dm1 is None:
fname = CONFIG_INI.get("boston_kilo952", "flat_map_dm1")
flat_map_dm1 = fits.getdata(os.path.join(calibration_data_path, fname))

if flat_map_dm2 is None:
fname = CONFIG_INI.get("boston_kilo952", "flat_map_dm2")
flat_map_dm2 = fits.getdata(os.path.join(calibration_data_path, fname))
Copy link
Contributor

Choose a reason for hiding this comment

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

I would still load them conditionally to account for single DM usage. There's no strong reason to do so, only the weak example case of us messing around with a single DM and not even having the second file on disk.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll do the same for the get_m_per_volt_map() function just below this one then.


return flat_map_dm1 if dm_num == 1 else flat_map_dm2


def get_m_per_volt_map(dm_num):
Expand Down Expand Up @@ -262,26 +261,18 @@ def convert_m_to_volts(data, dm_num, meter_to_volt_map=None):


def convert_dm_command_to_image(dm_command):
# Flatten the mask using index952
mask = catkit.util.get_dm_mask()
index952 = np.flatnonzero(mask)
mask = catkit.util.get_dm_mask().astype('bool')
number_of_actuators = np.count_nonzero(mask)

number_of_actuators_per_dimension = CONFIG_INI.getint('boston_kilo952', 'dm_length_actuators')
number_of_actuators = CONFIG_INI.getint("boston_kilo952", "number_of_actuators")
image = np.zeros((number_of_actuators_per_dimension, number_of_actuators_per_dimension))
image[np.unravel_index(index952, image.shape)] = dm_command[:number_of_actuators]
image = np.zeros(mask.shape)
image[mask] = dm_command[:number_of_actuators]
Comment on lines -265 to +287
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Good reduction! It took me way too long to even figure out what the old code was doing.


return image


def convert_dm_image_to_command(dm_image, path_to_save=None):
# Flatten the gain_map using index952
mask = catkit.util.get_dm_mask()
index952 = np.flatnonzero(mask)

# Parse using index952.
image_1d = np.ndarray.flatten(dm_image)
dm_command = image_1d[index952]
# Take actuators corresponding to the DM mask
dm_command = dm_image[catkit.util.get_dm_mask().astype('bool')]

# Write new image as fits file
if path_to_save is not None:
Expand Down
13 changes: 9 additions & 4 deletions catkit/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ def find_package_location(package='catkit'):
return importlib.util.find_spec(package).submodule_search_locations[0]


def find_repo_location(package='cakit'):
def find_repo_location(package='catkit'):
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch, thanks. 👍

return os.path.abspath(os.path.join(find_package_location(package), os.pardir))


def get_dm_mask():
mask_path = os.path.join(find_package_location("catkit"), "hardware", "boston", "kiloCdm_2Dmask.fits")
mask = fits.open(mask_path)[0].data
return mask
if get_dm_mask.mask is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's do the following just to keep code contained to the func def, please.

if getattr(get_dm_mask, "mask", None) is None:
  ...

mask_path = os.path.join(find_package_location("catkit"), "hardware", "boston", "kiloCdm_2Dmask.fits")
get_dm_mask.mask = fits.getdata(mask_path)

return get_dm_mask.mask


get_dm_mask.mask = None
Copy link
Contributor

Choose a reason for hiding this comment

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

See comment above.



# Does numpy gotchu?
Expand Down