diff --git a/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXSDLPCA200.py b/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXSDLPCA200.py index 8796869..68f5414 100644 --- a/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXSDLPCA200.py +++ b/csaxs_bec/bec_ipython_client/plugins/cSAXS/cSAXSDLPCA200.py @@ -6,28 +6,28 @@ connected to Galil RIO digital outputs. DLPCA-200 Remote Control (datasheet page 4) ------------------------------------------- -Sub-D pin → function: - Pin 10 → gain LSB (digital out channel, index 0 in bit-tuple) - Pin 11 → gain MID (digital out channel, index 1 in bit-tuple) - Pin 12 → gain MSB (digital out channel, index 2 in bit-tuple) - Pin 13 → coupling LOW = AC, HIGH = DC - Pin 14 → speed mode HIGH = low noise (Pin14=1), LOW = high speed (Pin14=0) +Sub-D pin -> function: + Pin 10 -> gain LSB (digital out channel, index 0 in bit-tuple) + Pin 11 -> gain MID (digital out channel, index 1 in bit-tuple) + Pin 12 -> gain MSB (digital out channel, index 2 in bit-tuple) + Pin 13 -> coupling LOW = AC, HIGH = DC + Pin 14 -> speed mode HIGH = low noise (Pin14=1), LOW = high speed (Pin14=0) Gain truth table (MSB, MID, LSB): - 0,0,0 → low-noise: 1e3 high-speed: 1e5 - 0,0,1 → low-noise: 1e4 high-speed: 1e6 - 0,1,0 → low-noise: 1e5 high-speed: 1e7 - 0,1,1 → low-noise: 1e6 high-speed: 1e8 - 1,0,0 → low-noise: 1e7 high-speed: 1e9 - 1,0,1 → low-noise: 1e8 high-speed: 1e10 - 1,1,0 → low-noise: 1e9 high-speed: 1e11 + 0,0,0 -> low-noise: 1e3 high-speed: 1e5 + 0,0,1 -> low-noise: 1e4 high-speed: 1e6 + 0,1,0 -> low-noise: 1e5 high-speed: 1e7 + 0,1,1 -> low-noise: 1e6 high-speed: 1e8 + 1,0,0 -> low-noise: 1e7 high-speed: 1e9 + 1,0,1 -> low-noise: 1e8 high-speed: 1e10 + 1,1,0 -> low-noise: 1e9 high-speed: 1e11 -Strategy: prefer low-noise mode (1e3–1e9). For 1e10 and 1e11, +Strategy: prefer low-noise mode (1e3-1e9). For 1e10 and 1e11, automatically fall back to high-speed mode. Device wiring example (galilrioesxbox): - bpm4: Pin10→ch0, Pin11→ch1, Pin12→ch2, Pin13→ch3, Pin14→ch4 - bim: Pin10→ch6, Pin11→ch7, Pin12→ch8, Pin13→ch9, Pin14→ch10 + bpm4: Pin10->ch0, Pin11->ch1, Pin12->ch2, Pin13->ch3, Pin14->ch4 + bim: Pin10->ch6, Pin11->ch7, Pin12->ch8, Pin13->ch9, Pin14->ch10 Usage examples -------------- @@ -57,11 +57,11 @@ dev = builtins.__dict__.get("dev") # Each entry describes one DLPCA-200 amplifier connected to a Galil RIO. # # Keys inside "channels": -# gain_lsb → digital output channel number wired to DLPCA-200 Pin 10 -# gain_mid → digital output channel number wired to DLPCA-200 Pin 11 -# gain_msb → digital output channel number wired to DLPCA-200 Pin 12 -# coupling → digital output channel number wired to DLPCA-200 Pin 13 -# speed_mode → digital output channel number wired to DLPCA-200 Pin 14 +# gain_lsb -> digital output channel number wired to DLPCA-200 Pin 10 +# gain_mid -> digital output channel number wired to DLPCA-200 Pin 11 +# gain_msb -> digital output channel number wired to DLPCA-200 Pin 12 +# coupling -> digital output channel number wired to DLPCA-200 Pin 13 +# speed_mode -> digital output channel number wired to DLPCA-200 Pin 14 # # To add a new amplifier, simply extend this dict. # --------------------------------------------------------------------------- @@ -70,22 +70,22 @@ DLPCA200_AMPLIFIER_CONFIG: dict[str, dict] = { "rio_device": "galilrioesxbox", "description": "Beam Position Monitor 4 current amplifier", "channels": { - "gain_lsb": 0, # Pin 10 → Galil ch0 - "gain_mid": 1, # Pin 11 → Galil ch1 - "gain_msb": 2, # Pin 12 → Galil ch2 - "coupling": 3, # Pin 13 → Galil ch3 - "speed_mode": 4, # Pin 14 → Galil ch4 + "gain_lsb": 0, # Pin 10 -> Galil ch0 + "gain_mid": 1, # Pin 11 -> Galil ch1 + "gain_msb": 2, # Pin 12 -> Galil ch2 + "coupling": 3, # Pin 13 -> Galil ch3 + "speed_mode": 4, # Pin 14 -> Galil ch4 }, }, "bim": { "rio_device": "galilrioesxbox", "description": "Beam Intensity Monitor current amplifier", "channels": { - "gain_lsb": 6, # Pin 10 → Galil ch6 - "gain_mid": 7, # Pin 11 → Galil ch7 - "gain_msb": 8, # Pin 12 → Galil ch8 - "coupling": 9, # Pin 13 → Galil ch9 - "speed_mode": 10, # Pin 14 → Galil ch10 + "gain_lsb": 6, # Pin 10 -> Galil ch6 + "gain_mid": 7, # Pin 11 -> Galil ch7 + "gain_msb": 8, # Pin 12 -> Galil ch8 + "coupling": 9, # Pin 13 -> Galil ch9 + "speed_mode": 10, # Pin 14 -> Galil ch10 }, }, } @@ -93,7 +93,7 @@ DLPCA200_AMPLIFIER_CONFIG: dict[str, dict] = { # --------------------------------------------------------------------------- # DLPCA-200 gain encoding tables # --------------------------------------------------------------------------- -# (msb, mid, lsb) → gain in V/A +# (msb, mid, lsb) -> gain in V/A _GAIN_BITS_LOW_NOISE: dict[tuple, int] = { (0, 0, 0): int(1e3), (0, 0, 1): int(1e4), @@ -114,13 +114,13 @@ _GAIN_BITS_HIGH_SPEED: dict[tuple, int] = { (1, 1, 0): int(1e11), } -# Inverse maps: gain → (msb, mid, lsb, low_noise_flag) +# Inverse maps: gain -> (msb, mid, lsb, low_noise_flag) # low_noise_flag: True = Pin14 HIGH, False = Pin14 LOW _GAIN_TO_BITS: dict[int, tuple] = {} for _bits, _gain in _GAIN_BITS_LOW_NOISE.items(): _GAIN_TO_BITS[_gain] = (*_bits, True) for _bits, _gain in _GAIN_BITS_HIGH_SPEED.items(): - if _gain not in _GAIN_TO_BITS: # low-noise takes priority + if _gain not in _GAIN_TO_BITS: # low-noise takes priority _GAIN_TO_BITS[_gain] = (*_bits, False) VALID_GAINS = sorted(_GAIN_TO_BITS.keys()) @@ -168,9 +168,7 @@ class cSAXSDLPCA200: """Return config dict for a named amplifier, raising on unknown names.""" if amp_name not in self._config: known = ", ".join(sorted(self._config.keys())) - raise cSAXSDLPCA200Error( - f"{self.TAG} Unknown amplifier '{amp_name}'. Known: [{known}]" - ) + raise cSAXSDLPCA200Error(f"{self.TAG} Unknown amplifier '{amp_name}'. Known: [{known}]") return self._config[amp_name] def _get_rio(self, amp_name: str): @@ -181,9 +179,7 @@ class cSAXSDLPCA200: try: rio = getattr(dev, rio_name) except AttributeError: - raise cSAXSDLPCA200Error( - f"{self.TAG} RIO device '{rio_name}' not found in BEC 'dev'." - ) + raise cSAXSDLPCA200Error(f"{self.TAG} RIO device '{rio_name}' not found in BEC 'dev'.") return rio def _dout_get(self, rio, ch: int) -> int: @@ -208,9 +204,9 @@ class cSAXSDLPCA200: """ rio = self._get_rio(amp_name) ch = self._get_cfg(amp_name)["channels"] - msb = self._dout_get(rio, ch["gain_msb"]) - mid = self._dout_get(rio, ch["gain_mid"]) - lsb = self._dout_get(rio, ch["gain_lsb"]) + msb = self._dout_get(rio, ch["gain_msb"]) + mid = self._dout_get(rio, ch["gain_mid"]) + lsb = self._dout_get(rio, ch["gain_lsb"]) speed_mode = self._dout_get(rio, ch["speed_mode"]) return msb, mid, lsb, speed_mode @@ -218,7 +214,7 @@ class cSAXSDLPCA200: """ Decode hardware bit-state into gain value (V/A). - speed_mode=1 → low-noise table, speed_mode=0 → high-speed table. + speed_mode=1 -> low-noise table, speed_mode=0 -> high-speed table. Returns None if the bit combination is not in the table. """ bits = (msb, mid, lsb) @@ -228,7 +224,7 @@ class cSAXSDLPCA200: return _GAIN_BITS_HIGH_SPEED.get(bits) # ------------------------------------------------------------------ - # Public API – control + # Public API - control # ------------------------------------------------------------------ def set_gain(self, amp_name: str, gain: float, force_high_speed: bool = False) -> None: @@ -236,7 +232,7 @@ class cSAXSDLPCA200: Set the transimpedance gain of a DLPCA-200 amplifier. The method automatically selects low-noise mode (Pin14=HIGH) whenever - the requested gain is achievable in low-noise mode (1e3 – 1e9 V/A). + the requested gain is achievable in low-noise mode (1e3 - 1e9 V/A). For gains of 1e10 and 1e11 V/A, high-speed mode is used automatically. Parameters @@ -258,7 +254,9 @@ class cSAXSDLPCA200: """ gain_int = int(gain) if gain_int not in _GAIN_TO_BITS: - valid_str = ", ".join(f"1e{int(round(__import__('math').log10(g)))}" for g in VALID_GAINS) + valid_str = ", ".join( + f"1e{int(round(__import__('math').log10(g)))}" for g in VALID_GAINS + ) raise cSAXSDLPCA200Error( f"{self.TAG} Invalid gain {gain:.2e} V/A for '{amp_name}'. " f"Valid values: {valid_str}" @@ -284,11 +282,11 @@ class cSAXSDLPCA200: try: rio = self._get_rio(amp_name) - ch = self._get_cfg(amp_name)["channels"] + ch = self._get_cfg(amp_name)["channels"] - self._dout_set(rio, ch["gain_msb"], bool(msb)) - self._dout_set(rio, ch["gain_mid"], bool(mid)) - self._dout_set(rio, ch["gain_lsb"], bool(lsb)) + self._dout_set(rio, ch["gain_msb"], bool(msb)) + self._dout_set(rio, ch["gain_mid"], bool(mid)) + self._dout_set(rio, ch["gain_lsb"], bool(lsb)) self._dout_set(rio, ch["speed_mode"], use_low_noise) # True=low-noise mode_str = "low-noise" if use_low_noise else "high-speed" @@ -297,7 +295,7 @@ class cSAXSDLPCA200: f"({mode_str} mode, bits MSB={msb} MID={mid} LSB={lsb})" ) print( - f"{amp_name}: gain → {gain_int:.2e} V/A [{mode_str}] " + f"{amp_name}: gain -> {gain_int:.2e} V/A [{mode_str}] " f"(bits: MSB={msb} MID={mid} LSB={lsb})" ) @@ -318,7 +316,7 @@ class cSAXSDLPCA200: Amplifier name (e.g. "bpm4", "bim"). coupling : str "AC" or "DC" (case-insensitive). - DC → Pin13 HIGH, AC → Pin13 LOW. + DC -> Pin13 HIGH, AC -> Pin13 LOW. Examples -------- @@ -328,19 +326,18 @@ class cSAXSDLPCA200: coupling_upper = coupling.strip().upper() if coupling_upper not in ("AC", "DC"): raise cSAXSDLPCA200Error( - f"{self.TAG} Invalid coupling '{coupling}' for '{amp_name}'. " - f"Use 'AC' or 'DC'." + f"{self.TAG} Invalid coupling '{coupling}' for '{amp_name}'. " f"Use 'AC' or 'DC'." ) pin13_high = coupling_upper == "DC" try: rio = self._get_rio(amp_name) - ch = self._get_cfg(amp_name)["channels"] + ch = self._get_cfg(amp_name)["channels"] self._dout_set(rio, ch["coupling"], pin13_high) logger.info(f"{self.TAG} [{amp_name}] coupling set to {coupling_upper}") - print(f"{amp_name}: coupling → {coupling_upper}") + print(f"{amp_name}: coupling -> {coupling_upper}") except cSAXSDLPCA200Error: raise @@ -350,7 +347,7 @@ class cSAXSDLPCA200: ) from exc # ------------------------------------------------------------------ - # Public API – readback / reporting + # Public API - readback / reporting # ------------------------------------------------------------------ def read_settings(self, amp_name: str) -> dict: @@ -361,17 +358,17 @@ class cSAXSDLPCA200: ------- dict with keys: "amp_name" : str - "gain" : int or None – gain in V/A (None if unknown bit pattern) - "mode" : str – "low-noise" or "high-speed" - "coupling" : str – "AC" or "DC" - "bits" : dict – raw bit values {msb, mid, lsb, speed_mode, coupling} + "gain" : int or None - gain in V/A (None if unknown bit pattern) + "mode" : str - "low-noise" or "high-speed" + "coupling" : str - "AC" or "DC" + "bits" : dict - raw bit values {msb, mid, lsb, speed_mode, coupling} """ rio = self._get_rio(amp_name) - ch = self._get_cfg(amp_name)["channels"] + ch = self._get_cfg(amp_name)["channels"] - msb = self._dout_get(rio, ch["gain_msb"]) - mid = self._dout_get(rio, ch["gain_mid"]) - lsb = self._dout_get(rio, ch["gain_lsb"]) + msb = self._dout_get(rio, ch["gain_msb"]) + mid = self._dout_get(rio, ch["gain_mid"]) + lsb = self._dout_get(rio, ch["gain_lsb"]) speed_mode = self._dout_get(rio, ch["speed_mode"]) coupling_bit = self._dout_get(rio, ch["coupling"]) @@ -381,15 +378,15 @@ class cSAXSDLPCA200: return { "amp_name": amp_name, - "gain": gain, - "mode": mode, + "gain": gain, + "mode": mode, "coupling": coupling, "bits": { - "msb": msb, - "mid": mid, - "lsb": lsb, + "msb": msb, + "mid": mid, + "lsb": lsb, "speed_mode": speed_mode, - "coupling": coupling_bit, + "coupling": coupling_bit, }, } @@ -426,7 +423,9 @@ class cSAXSDLPCA200: print(f" {'Gain':<12}: {gain_str}") print(f" {'Mode':<12}: {s['mode']}") print(f" {'Coupling':<12}: {s['coupling']}") - print(f" {'Raw bits':<12}: MSB={bits['msb']} MID={bits['mid']} LSB={bits['lsb']} speed={bits['speed_mode']} coup={bits['coupling']}") + print( + f" {'Raw bits':<12}: MSB={bits['msb']} MID={bits['mid']} LSB={bits['lsb']} speed={bits['speed_mode']} coup={bits['coupling']}" + ) def info_all(self) -> None: """ @@ -440,4 +439,4 @@ class cSAXSDLPCA200: def list_amplifiers(self) -> list[str]: """Return sorted list of configured amplifier names.""" - return sorted(self._config.keys()) \ No newline at end of file + return sorted(self._config.keys())