コード例 #1
0
    def t1(self):
        try:
            raise Exception
        except Exception as e:
            pass

        cothread.Yield()
コード例 #2
0
    def _handle(self):
        E = None
        try:
            while True:
                E = self._Q.Wait()
                _log.debug("Subscription %s handle %s", self.name, LazyRepr(E))

                S = self._S

                if isinstance(E, Cancelled):
                    return

                elif isinstance(E, Disconnected):
                    _log.debug('Subscription notify for %s with %s', self.name,
                               E)
                    if self._notify_disconnect:
                        self._cb(E)
                    else:
                        _log.info("Subscription disconnect %s", self.name)
                    continue

                elif isinstance(E, RemoteError):
                    _log.debug('Subscription notify for %s with %s', self.name,
                               E)
                    if self._notify_disconnect:
                        self._cb(E)
                    elif isinstance(E, RemoteError):
                        _log.error("Subscription Error %s", E)
                    return

                elif S is None:  # already close()'d
                    return

                i = 0
                while True:
                    E = S.pop()
                    if E is None or self._S is None:
                        break
                    self._cb(E)
                    i = (i + 1) % 4
                    if i == 0:
                        cothread.Yield()

                if S.done:
                    _log.debug('Subscription complete %s', self.name)
                    S.close()
                    self._S = None
                    if self._notify_disconnect:
                        E = Finished()
                        self._cb(E)
                    break
        except:
            _log.exception("Error processing Subscription event: %s",
                           LazyRepr(E))
            self._S.close()
            self._S = None
コード例 #3
0
ファイル: controls.py プロジェクト: dls-controls/i10switching
    def __init__(self):
        """Monitor values of PVs: offsets, scales etc."""
        if self.__guard:
            raise RuntimeError('Do not instantiate. ' +
                               'If you require an instance use get_instance.')

        self.arrays = {
            Arrays.OFFSETS: caget(
                [ctrl + ':OFFSET' for ctrl in PvReferences.CTRLS]),
            Arrays.SCALES: caget(
                [ctrl + ':WFSCA' for ctrl in PvReferences.CTRLS]),
            Arrays.SET_SCALES: caget(
                [name + ':SETWFSCA' for name in PvReferences.NAMES]),
            Arrays.WAVEFORMS: caget(PvReferences.TRACES),
            Arrays.SETI: caget([name + ':SETI' for name in PvReferences.NAMES]),
            Arrays.IMIN: caget([name + ':IMIN' for name in PvReferences.NAMES]),
            Arrays.IMAX: caget([name + ':IMAX' for name in PvReferences.NAMES]),
            Arrays.ERRORS: caget(
                [name + ':ERRGSTR' for name in PvReferences.NAMES])
        }

        self.listeners = {'straight': [], 'trace': []}

        for i in range(len(PvReferences.CTRLS)):
            camonitor(PvReferences.CTRLS[i] + ':OFFSET',
                      lambda x, i=i: self.update_values(
                    x, Arrays.OFFSETS, i, 'straight'))
            camonitor(PvReferences.CTRLS[i] + ':WFSCA',
                      lambda x, i=i: self.update_values(
                    x, Arrays.SCALES, i, 'straight'))

        for idx, ioc in enumerate(PvReferences.NAMES):
            camonitor(ioc + ':SETWFSCA',
                      lambda x, i=idx: self.update_values(
                    x, Arrays.SET_SCALES, i, 'straight'))
            camonitor(ioc + ':SETI',
                      lambda x, i=idx: self.update_values(
                    x, Arrays.SETI, i, 'straight'))
            camonitor(ioc + ':IMIN',
                      lambda x, i=idx: self.update_values(
                    x, Arrays.IMIN, i, 'straight'))
            camonitor(ioc + ':IMAX',
                      lambda x, i=idx: self.update_values(
                    x, Arrays.IMAX, i, 'straight'))
            camonitor(ioc + ':ERRGSTR',
                      lambda x, i=idx: self.update_values(
                    x, Arrays.ERRORS, i, 'straight'), format=FORMAT_TIME)

        camonitor(PvReferences.TRACES[0],
                  lambda x: self.update_values(x, Arrays.WAVEFORMS, 0, 'trace'))
        camonitor(PvReferences.TRACES[1],
                  lambda x: self.update_values(x, Arrays.WAVEFORMS, 1, 'trace'))

        cothread.Yield()  # Ensure monitored values are connected
コード例 #4
0
def await_ioc_start(stats, prefix):
    cothread.Yield()
    pid_rbv = catools.caget(f"{prefix}:PID", timeout=5)
    if int(pid_rbv) != os.getpid():
        raise BadValueError("Got back different PID: " +
                            "is there another system instance on the machine?")
    catools.caput(f"{prefix}:YAML:PATH",
                  stats["yaml_path"],
                  datatype=catools.DBR_CHAR_STR)
    catools.caput(
        f"{prefix}:PYMALCOLM:PATH",
        stats["pymalcolm_path"],
        datatype=catools.DBR_CHAR_STR,
    )
コード例 #5
0
ファイル: idlocalbump.py プロジェクト: yuketian/sofb
def run_single_bumps(pvmaps):
    for pvm in pvmaps:
        if ap.caget(pvm["cmd"]) == 0: continue
        ap.caput(pvm["cmddone"], 0)
        ename = pvm["idname"]
        if not ename: continue
        if ap.caget(pvm["op"]) == 0: continue
        xc, xangle = ap.caget([pvm["offset"], pvm["angle"]])
        plane = pvm["XY"].lower()
        print ename, xc, xangle, plane
        norm0, norm1, norm2, corvals = ap.setIdBump(
            ename, xc, xangle, plane=plane, check=False, ncor=6, dImax=0.5)
        print "Norm:", norm0, norm1, norm2
        print corvals
        ap.caput(pvm["cmddone"], 1)
        ap.caput(pvm["cmd"], 0)
        cothread.Yield(0.1)
コード例 #6
0
ファイル: plots.py プロジェクト: dls-controls/i10switching
    def get_windowed_data(self, trigger, trace):
        """Overlay the two peaks."""
        try:
            diff = np.diff(trigger)

            length = len(trace)
            # TODO: this parameter probably shouldn't be hard coded
            stepvalue = 0.5

            if min(diff) > -1 * stepvalue or max(diff) < stepvalue:
                raise RangeError

            maxtrig = next(x for x in diff if x > stepvalue)
            mintrig = next(x for x in diff if x < -1 * stepvalue)
            edges = [
                np.where(diff == maxtrig)[0][0],
                np.where(diff == mintrig)[0][0]
            ]

            cothread.Yield()
            trigger_length = (edges[1] - edges[0]) * 2

            if length < trigger_length:
                raise RangeError
            if edges[1] > edges[0]:  # So that colours don't swap around
                first_peak = np.roll(trace[:trigger_length], -edges[0] -
                                     trigger_length / 4)[:trigger_length / 2]
                second_peak = np.roll(trace[:trigger_length], -edges[1] -
                                      trigger_length / 4)[:trigger_length / 2]
            else:
                first_peak = np.roll(trace[:trigger_length], -edges[1] -
                                     trigger_length / 4)[:trigger_length / 2]
                second_peak = np.roll(trace[:trigger_length], -edges[0] -
                                      trigger_length / 4)[:trigger_length / 2]

            return first_peak, second_peak

        except RangeError:
            print 'Trace is partially cut off'  # status bar? callback?
            first_peak = [float('nan'), float('nan')]
            second_peak = [float('nan'), float('nan')]
            return first_peak, second_peak
コード例 #7
0
    def _co_execute(self):
        """Execute the virtual accelerator. This includes the following:

        1. Creating a temporary working directory for execution of FLAME.
        2. Set up the working directory by symlinking from the data directory.
        3. Writing the EPICS DB to the working directory (va.db).
        4. Starting the softIoc and channel initializing monitors.
        5. Add noise to the settings for all input (CSET) channels.
        6. Create or update the FLAME machine configuration.
        7. Propagate the FLAME simulation and read the results.
        8. Update the READ channels of all devives.
        9. Update the REST channels of input devies.
        10. Repeat from step #5.
        """
        _LOGGER.debug("VA: Execute virtual accelerator")
        _LOGGER.info("VA: Running at " + self._ts_now)

        chanprefix = self._chanprefix
        if self._pv_suffix != '':
            suffix_str = "_" + self._pv_suffix
        else:
            suffix_str = ""

        # Add channel for VA rep-rate
        chanrate = f"{chanprefix}:SVR:RATE{suffix_str}"
        self._epicsdb.append(("ao", chanrate, OrderedDict([
            ("DESC", "Rep-rate of Simulation Engine"),
            ("VAL", self._rate),
            ("PREC", 1),
            ])))
        _LOGGER.info("VA: Reprate PV is " + chanrate)


        # Add channel for sample counting
        chansample_cnt = f"{chanprefix}:SVR:CNT{suffix_str}"
        self._epicsdb.append(("ao", chansample_cnt, OrderedDict([
            ("DESC", "Sample counter for scan client"),
            ("VAL", 0)
            ])))

        # Add channel for VA configuration and control
        channoise = f"{chanprefix}:SVR:NOISE{suffix_str}"
        self._epicsdb.append(("ao", channoise, OrderedDict([
                ("DESC", "Noise level of Virtual Accelerator"),
                ("VAL", self._noise),
                ("PREC", 5)
            ])))
        _LOGGER.info("VA: Noise PV is " + channoise)

        chanstat = f"{chanprefix}:SVR:STATUS{suffix_str}"
        self._epicsdb.append(("bi", chanstat, OrderedDict([
                ("DESC", "Status of Virtual Accelerator"),
                ("VAL", 1),
                ("ZNAM", "ERR"),
                ("ONAM", "OK"),
                ("PINI", "1")
            ])))
        _LOGGER.info("VA: Status PV is " + chanstat)

        # MPS status
        chan_mps_stat = f"{chanprefix}:SVR:MpsStatus"
        self._epicsdb.append(("mbbi", chan_mps_stat, OrderedDict([
                ("DESC", "MPS Status of Virtual Accelerator"),
                ("VAL", 3),
                ("ZRST", "Fault"),
                ("ONST", "Disable"),
                ("TWST", "Monitor"),
                ("THST", "Enable"),
                ("PINI", "1")
            ])))
        _LOGGER.info("VA: MPS PV is " + chan_mps_stat)

        #
        chancharge = f"{chanprefix}:SVR:CHARGE{suffix_str}"
        self._epicsdb.append(("ai", chancharge, OrderedDict([
                ("DESC", "Q/M of Virtual Accelerator"),
                ("VAL", 0.0),
                ("PREC", 5)
            ])))

        # initial beam condition
        chanbsrc = f"{chanprefix}:SVR:BEAM{suffix_str}"
        self._epicsdb.append(("waveform", chanbsrc, OrderedDict([
                ("DESC", "Init beam of Virtual Accelerator"),
                ("NELM", 4096),
                ("FTVL", "UCHAR")
            ])))
        _LOGGER.info("VA: Init beam condition PV is " + chanbsrc)

        #
        if self.work_dir is not None:
            os.makedirs(self.work_dir)
            self._rm_work_dir = False
            latticepath = os.path.join(self.work_dir, "test.lat")
        else:
            self.work_dir = tempfile.mkdtemp(_TEMP_DIRECTORY_SUFFIX)
            self._rm_work_dir = True
            latticepath = None

        _LOGGER.info("VA: Working directory: %s", self._work_dir)

        # input file paths
        epicsdbpath = os.path.join(self.work_dir, "va.db")

        #output file paths
        epicslogpath = os.path.join(self.work_dir, "softioc.log")

        if os.path.isabs(self.data_dir):
            abs_data_dir = self.data_dir
            self._latfactory.dataDir = self.data_dir
        else:
            abs_data_dir = os.path.abspath(self.data_dir)
            self._latfactory.dataDir = os.path.abspath(self.data_dir)

        with open(epicsdbpath, "w") as outfile:
            self._write_epicsdb(outfile)
        _LOGGER.info("VA: Write EPICS database to %s", epicsdbpath)
        #_LOGGER.debug("VA: Write EPICS database to %s", epicsdbpath)

        self._ioc_logfile = open(epicslogpath, "w")
        self._ioc_process = Popen(["softIoc", "-d", "va.db"], cwd=self.work_dir,
                                  stdout=self._ioc_logfile, stderr=subprocess.STDOUT)
        _LOGGER.debug("VA: Start EPICS soft IOC with log %s", epicslogpath)

        _LOGGER.debug("VA: Connecting to channels: {}".format(len(self._csetmap.keys())))

        self._subscriptions = []
        self._subscriptions.append(catools.camonitor(chanrate, self._handle_rate_monitor))
        self._subscriptions.append(catools.camonitor(channoise, self._handle_noise_monitor))
        self._subscriptions.append(catools.camonitor(chanbsrc, self._handle_bsrc_monitor))
        self._subscriptions.extend(catools.camonitor(self._csetmap.keys(), self._handle_cset_monitor))
        _LOGGER.debug("VA: Connecting to channels: Done")

        machine = None

        while self._continue:
            # update the RSET channels with new settings
            batch = catools.CABatch()
            for cset in self._csetmap.items():
                name, field = self._fieldmap[cset[0]]
                batch[cset[1][0]] = self._settings[name][field]
            batch.caput()

            settings = self._copy_settings_with_noise()
            self._latfactory.settings = settings
            lattice = self._latfactory.build()

            start = time.time()

            if machine is None:
                _LOGGER.debug("VA: Create FLAME machine from configuration")
                machine = Machine(lattice.conf())
            else:
                _LOGGER.debug("VA: Reconfigure FLAME machine from configuration")
                for idx, elem in enumerate(lattice.elements):
                    machine.reconfigure(idx, elem[2])

                if self._bsrc is not None:
                    _LOGGER.info("VA: Reconfigure FLAME machine with init beam config")
                    machine.reconfigure(self._bsrc['index'], self._bsrc['properties'])

            if latticepath is not None:
                _LOGGER.debug(f"VA: Write FLAME lattice file to {outfile}")
                generate_latfile(machine, latfile=latticepath)

            _LOGGER.debug("VA: Allocate FLAME state from configuration")
            S = machine.allocState({})

            output_map = []
            for elem in lattice.elements:
                if 'name' in elem[3]:
                    output_map.append(elem[3]['name'])
                else:
                    output_map.append(None)

            batch = catools.CABatch()
            for i in range(0, len(machine)):
                machine.propagate(S, i, 1)

                if output_map[i] in self._elemmap:
                    elem = self._elemmap[output_map[i]]

                    if isinstance(elem, BPMElement):
                        x_centroid = S.moment0_env[0]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.x_phy], x_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.x_phy]] = x_centroid
                        y_centroid = S.moment0_env[2]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.y_phy], y_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.y_phy]] = y_centroid
                         # convert rad to deg and adjust for 161MHz sampling frequency
                        phase = _normalize_phase(2.0 * S.ref_phis * (180.0 / math.pi))
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.phase_phy], phase)
                        batch[self._readfieldmap[elem.name][elem.fields.phase_phy]] = phase
                        energy = S.ref_IonEk/1.0e6 # convert eV to MeV
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.energy_phy], energy)
                        batch[self._readfieldmap[elem.name][elem.fields.energy_phy]] = energy

                    elif isinstance(elem, PMElement):
                        x_centroid = S.moment0_env[0]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.x], x_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.x]] = x_centroid
                        y_centroid = S.moment0_env[2]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.y], y_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.y]] = y_centroid
                        x_rms = S.moment0_rms[0]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.xrms], x_rms)
                        batch[self._readfieldmap[elem.name][elem.fields.xrms]] = x_rms
                        y_rms = S.moment0_rms[2]/1.0e3
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.yrms], y_rms)
                        batch[self._readfieldmap[elem.name][elem.fields.yrms]] = y_rms

                        sign = elem.sign
                        xy_centroid = (sign*x_centroid + y_centroid)/math.sqrt(2.0) # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.xy], xy_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.xy]] = xy_centroid

                        xy_rms = 1.0e-3*math.sqrt(
                                (S.moment1_env[0, 0] + S.moment1_env[2, 2])*0.5
                                + sign*S.moment1_env[0, 2]
                        )
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.xyrms], xy_rms)
                        batch[self._readfieldmap[elem.name][elem.fields.xyrms]] = xy_rms

                        cxy = sign * S.moment1_env[0, 2] * 1e-6 / x_rms / y_rms
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.cxy], cxy)
                        batch[self._readfieldmap[elem.name][elem.fields.cxy]] = cxy

                    elif isinstance(elem, (FCElement, VDElement, TargetElement, DumpElement, WedgeElement)):
                        x_centroid = S.moment0_env[0]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.x], x_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.x]] = x_centroid
                        y_centroid = S.moment0_env[2]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.y], y_centroid)
                        batch[self._readfieldmap[elem.name][elem.fields.y]] = y_centroid
                        x_rms = S.moment0_rms[0]/1.0e3 # convert mm to m
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.xrms], x_rms)
                        batch[self._readfieldmap[elem.name][elem.fields.xrms]] = x_rms
                        y_rms = S.moment0_rms[2]/1.0e3
                        _LOGGER.debug("VA: Update read: %s to %s",
                                      self._readfieldmap[elem.name][elem.fields.yrms], y_rms)
                        batch[self._readfieldmap[elem.name][elem.fields.yrms]] = y_rms

            batch.caput()

            _LOGGER.info("VA: FLAME execution time: %f s", time.time()-start)

            # Allow the BPM, PM, etc. readbacks to update
            # before the device setting readbacks PVs.
            cothread.Yield()

            batch = catools.CABatch()
            for name, value in self._csetmap.items():
                name, field = self._fieldmap[name]
                _LOGGER.debug("VA: Update read: %s to %s", value[1], settings[name][field])
                batch[value[1]] = settings[name][field]
            batch.caput()

            # Sleep for a fraction (10%) of the total execution time
            # when one simulation costs more than 0.50 seconds.
            # Otherwise, sleep for the rest of 1 second.
            # If a scan is being done on this virtual accelerator,
            # then the scan server has a period of time to update
            # setpoints before the next run of IMPACT.
            delt = time.time() - start
            if delt > 0.50:
                cothread.Sleep(delt * 0.1)
            else:
                cothread.Sleep(1.0 / self._rate - delt)
コード例 #8
0
 def put(self, pv, op):
     _log.debug("putting %s <- %s", op.name(), op.value())
     cothread.Yield()  # because we can
     pv.post(op.value() * 2)
     op.done()
コード例 #9
0
ファイル: pmacchildpart.py プロジェクト: thomascobb/pymalcolm
    def create_generator_profile_sparse(self, start_index: int) -> bool:
        # Ensure we have the correct trigger type
        assert (self.output_triggers !=
                scanning.infos.MotionTrigger.EVERY_POINT
                ), f"{self.name}: trigger should not be every point"

        # Keep going until we finish or exceed the maximum length of a profile
        start_batch_index = start_index
        point_index = start_index
        while True:
            # Grab some points
            points, joined, velocities = self.get_some_points(
                start_batch_index)
            if not points:
                return True

            # Number of points and check if the last point is in this batch
            num_points = len(points)
            last_point_in_batch = self.is_last_point_in_current_batch(
                start_batch_index, num_points)

            # Don't do all points in the batch otherwise we can get an index error
            # when adding the turnaround.
            points_to_do = num_points - 1
            for i in range(points_to_do):
                point_added = self.add_sparse_point(points, i, joined[i],
                                                    velocities[i])

                # add in the turnaround between non-contiguous points
                if not (joined[i]):
                    self.insert_gap(points[i], points[i + 1], point_index + 1)

                # Check if we have exceeded the profile points limit. Only check if we
                # have actually added a point, otherwise we waste time.
                if point_added and self.check_profile_length_exceeds_profile_points(
                ):
                    self.end_index = point_index + 1
                    return False

                # Increment point index
                point_index += 1

            # Check for the last point
            if last_point_in_batch:
                point_added = self.add_sparse_point(points, points_to_do,
                                                    False, False)

                # Check if we have exceeded the profile points limit. Only check if we
                # have actually added a point, otherwise we waste time.
                if point_added and self.check_profile_length_exceeds_profile_points(
                ):
                    self.end_index = point_index + 1
                    return False

                # Increment point index
                point_index += 1

            # Increment the index for the next batch
            start_batch_index = point_index

            # Check if we are done
            if start_batch_index == self.steps_up_to:
                # Return True for a tail-off
                return True

            # Yield so that we don't continuously block other threads
            cothread.Yield()
コード例 #10
0
import cothread
import random

def worker(n):
    for i in range(25):
        print(f"{n}", end="")
        cothread.Sleep(random.random() * 0.5) # suspend cothread   
    print()

threads = []
for n in range(1, 5):
    t = cothread.Spawn(worker, n)
    threads.append(t)

cothread.Yield()    # wait for other cothreads

# the cothread will terminate when we reach the end of the program
# therefore we must wait for the cothreads to complete
for t in threads:
    t.Wait()
コード例 #11
0
ファイル: recursion-test.py プロジェクト: huyong1979/cothread
#!/usr/bin/env python3

# Simple recursion overflow test, checks that guard pages do indeed guard
# against stack overflow (by generating a segmentation fault).

import os
os.environ['COTHREAD_CHECK_STACK'] = 'yes'

import require
import cothread
from cothread import _coroutine


def recurse(n):
    print('recursing', n)
    stack = _coroutine.stack_use(_coroutine.get_current())
    print('stack', stack)
    assert stack[0] <= stack[2]
    recurse(n + 1)


cothread.Spawn(recurse, 0, stack_size=8192)
cothread.Yield()
# We're dead
コード例 #12
0
 def handle_request(self, controller, request):
     controller.handle_request(request)
     # Yield control to allow the request to be handled
     cothread.Yield()
コード例 #13
0
 def test_received_message_subscribe(self):
     self.ps.received_message('{"message":"subscribe","id":0,"channel":"loc/test(43)"}')
     cothread.Yield()
     self.sock.sendall.assert_called_once_with('\x81u{"message": "event", "type": "value", "id": 0, "value": {"type": {"version": "1", "name": "VDouble"}, "value": 43.0}}')
コード例 #14
0
ファイル: idlocalbump.py プロジェクト: yuketian/sofb
        pvmaps.append(pvdict)

    #for b in ap.getElements("UBPM"):
    #    print b.name, b.pv(field="x")
    print "Start checking IDLocalBump command ..."
    while True:
        run_single_bumps(pvmaps)
        if ap.caget(_pvcmd) == 0:
            time.sleep(1)
            continue
        #obt = ap.getOrbit(spos=True)
        #print "BPMS:", len(ap.getElements("BPM")),
        #print np.average(obt[:,0]), np.std(obt[:,0])
        for pvm in pvmaps:
            ap.caput(pvm["cmddone"], 0)
        for pvm in pvmaps:
            ename = pvm["idname"]
            if not ename: continue
            if ap.caget(pvm["op"]) == 0: continue
            xc, xangle = ap.caget([pvm["offset"], pvm["angle"]])
            plane = pvm["XY"].lower()
            print ename, xc, xangle, plane
            norm0, norm1, norm2, corvals = ap.setIdBump(
                ename, xc, xangle, plane=plane, check=False, ncor=6, dImax=0.5)
            print "Norm:", norm0, norm1, norm2
            print corvals
            ap.caput(pvm["cmddone"], 1)
            cothread.Yield(0.1)
        time.sleep(1)
        ap.caput(_pvcmd, 0) 
コード例 #15
0
ファイル: impact.py プロジェクト: phantasy-project/phantasy
    def _execute(self):
        """Execute the virtual accelerator. This includes the following:
            1. Creating a temporary working directory for execution of IMPACT.
            2. Setup the working directory by symlinking from the data directory.
            3. Writing the EPICS DB to the working directory (va.db).
            4. Starting the softIoc and channel initializing monitors.
            5. Add noise to the settings for all input (CSET) channels.
            6. Generate the IMPACT lattice file in working directory (test.in).
            7. Execute IMPACT simulation and read the output files (fort.??).
            8. Update the READ channels of all devives.
            9. Update the REST channels of input devies.
            10. Repeat from step #5.
        """
        _LOGGER.debug("VirtualAccelerator: Execute virtual accelerator")

        if self._chanprefix is None:
            chanprefix = ""
        else:
            chanprefix = self._chanprefix

        # Add channel for sample counting
        sample_cnt = chanprefix + "SVR:CNT"

        self._epicsdb.append(("ai", sample_cnt, OrderedDict([
            ("DESC", "Sample counter for scan client"),
            ("VAL", 0)
        ])))

        # Add channel for VA configuration and control
        channoise = chanprefix + "SVR:NOISE"

        self._epicsdb.append(("ao", channoise, OrderedDict([
            ("DESC", "Noise level of Virtual Accelerator"),
            ("VAL", 0.001),
            ("PREC", 5)
        ])))

        chanstat = chanprefix + "SVR:STATUS"

        self._epicsdb.append(("bi", chanstat, OrderedDict([
            ("DESC", "Status of Virtual Accelerator"),
            ("VAL", 1),
            ("ZNAM", "ERR"),
            ("ONAM", "OK"),
            ("PINI", "1")
        ])))

        chancharge = chanprefix + "SVR:CHARGE"

        self._epicsdb.append(("ai", chancharge, OrderedDict([
            ("DESC", "Q/M of Virtual Accelerator"),
            ("VAL", 0.0),
            ("PREC", 5)
        ])))

        if self.work_dir is not None:
            os.makedirs(self.work_dir)
            self._rm_work_dir = False
        else:
            self.work_dir = tempfile.mkdtemp(_TEMP_DIRECTORY_SUFFIX)
            self._rm_work_dir = True

        _LOGGER.info("VirtualAccelerator: Working directory: %s", self._work_dir)

        # input file paths
        epicsdbpath = os.path.join(self.work_dir, "va.db")
        latticepath = os.path.join(self.work_dir, "test.in")
        modelmappath = os.path.join(self.work_dir, "model.map")

        # output file paths
        fort18path = os.path.join(self.work_dir, "fort.18")
        fort24path = os.path.join(self.work_dir, "fort.24")
        fort25path = os.path.join(self.work_dir, "fort.25")
        epicslogpath = os.path.join(self.work_dir, "softioc.log")

        if os.path.isabs(self.data_dir):
            abs_data_dir = self.data_dir
        else:
            abs_data_dir = os.path.abspath(self.data_dir)

        for datafile in os.listdir(abs_data_dir):
            srcpath = os.path.join(abs_data_dir, datafile)
            destpath = os.path.join(self.work_dir, datafile)
            if os.path.isfile(os.path.join(abs_data_dir, datafile)):
                os.symlink(srcpath, destpath)
                _LOGGER.debug("VirtualAccelerator: Link data file %s to %s", srcpath, destpath)

        with open(epicsdbpath, "w") as outfile:
            self._write_epicsdb(outfile)

        self._ioc_logfile = open(epicslogpath, "w")
        self._ioc_process = _Cothread_Popen(["softIoc", "-d", "va.db"], cwd=self.work_dir,
                                            stdout=self._ioc_logfile, stderr=subprocess.STDOUT)

        self._subscriptions = []

        self._subscriptions.append(catools.camonitor(channoise, self._handle_noise_monitor))

        self._subscriptions.extend(catools.camonitor(self._csetmap.keys(), self._handle_cset_monitor))

        while self._continue:
            # update the RSET channels with new settings
            for cset in self._csetmap.items():
                name, field = self._fieldmap[cset[0]]
                catools.caput(cset[1][0], self._settings[name][field])

            settings = self._copy_settings_with_noise()
            self._latfactory.settings = settings
            lattice = self._latfactory.build()

            catools.caput(chancharge, lattice.initialCharge)

            with open(latticepath, "w") as outfile:
                with open(modelmappath, "w") as mapfile:
                    lattice.write(outfile, mapstream=mapfile)

            start = time.time()

            if os.path.isfile(fort18path):
                os.remove(fort18path)

            if os.path.isfile(fort24path):
                os.remove(fort24path)

            if os.path.isfile(fort25path):
                os.remove(fort25path)

            impact_process = _Cothread_Popen(["mpirun", "-np", str(lattice.nprocessors),
                                              str(self.impact_exe)], cwd=self.work_dir,
                                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

            (stdout, _, status) = impact_process.communicate()

            # The virtual accelerator shutdown is likely to occur while IMPACT is executing,
            # so check if virtual accelerator has been stopped before proceeding.
            if not self._continue:
                break

            _LOGGER.info("VirtualAccelerator: IMPACT execution time: %f s", time.time() - start)

            if status == 0:
                catools.caput(chanstat, _VA_STATUS_GOOD)
            else:
                _LOGGER.warning("VirtualAccelerator: IMPACT exited with non-zero status code: %s\r\n%s", status, stdout)
                catools.caput(chanstat, _VA_STATUS_BAD)

            if os.path.isfile(fort18path):
                fort18 = numpy.loadtxt(fort18path, usecols=(0, 1, 3))
                fort18length = fort18.shape[0]
            else:
                _LOGGER.warning("VirtualAccelerator: IMPACT output not found: %s", fort18path)
                catools.caput(chanstat, _VA_STATUS_BAD)
                fort18length = 0

            if os.path.isfile(fort24path):
                fort24 = numpy.loadtxt(fort24path, usecols=(1, 2))
                fort24length = fort24.shape[0]
            else:
                _LOGGER.warning("VirtualAccelerator: IMPACT output not found: %s", fort24path)
                catools.caput(chanstat, _VA_STATUS_BAD)
                fort24length = 0

            if os.path.isfile(fort25path):
                fort25 = numpy.loadtxt(fort25path, usecols=(1, 2))
                fort25length = fort25.shape[0]
            else:
                _LOGGER.warning("VirtualAccelerator: IMPACT output not found: %s", fort25path)
                catools.caput(chanstat, _VA_STATUS_BAD)
                fort25length = 0

            output_map = []
            for elem in lattice.elements:
                if elem.itype in [-28]:
                    output_map.append(elem.name)

            output_length = len(output_map)

            if fort18length < output_length:
                _LOGGER.warning("VirtualAccelerator: IMPACT fort.18 length %s, expecting %s",
                                fort18length, output_length)
                catools.caput(chanstat, _VA_STATUS_BAD)

            if fort24length < output_length:
                _LOGGER.warning("VirtualAccelerator: IMPACT fort.24 length %s, expecting %s",
                                fort24length, output_length)
                catools.caput(chanstat, _VA_STATUS_BAD)

            if fort25length < output_length:
                _LOGGER.warning("VirtualAccelerator: IMPACT fort.25 length %s, expecting %s",
                                fort25length, output_length)
                catools.caput(chanstat, _VA_STATUS_BAD)

            def get_phase(idx):
                # IMPACT computes the phase in radians,
                # need to convert to degrees for PV.
                return _normalize_phase(2.0 * fort18[idx, 1] * (180.0 / math.pi))

            for idx in range(min(fort18length, fort24length, fort25length)):

                elem = self._elemmap[output_map[idx]]

                if isinstance(elem, BPMElement):
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.x], fort24[idx, 0])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.x], fort24[idx, 0])
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.y], fort25[idx, 0])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.y], fort25[idx, 0])
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.phase], get_phase(idx))
                    catools.caput(self._readfieldmap[elem.name][elem.fields.phase], get_phase(idx))
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.energy], fort18[idx, 2])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.energy], fort18[idx, 2])
                elif isinstance(elem, PMElement):
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.x], fort24[idx, 0])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.x], fort24[idx, 0])
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.y], fort25[idx, 0])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.y], fort25[idx, 0])
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.xrms], fort24[idx, 1])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.xrms], fort24[idx, 1])
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.yrms], fort25[idx, 1])
                    catools.caput(self._readfieldmap[elem.name][elem.fields.yrms], fort25[idx, 1])
                else:
                    _LOGGER.warning("VirtualAccelerator: Output from element type not supported: %s",
                                    type(elem).__name__)

            # Write the default error value to the remaing output PVs.
            for idx in range(min(fort18length, fort24length, fort25length), output_length):

                elem = self._elemmap[output_map[idx]]

                if isinstance(elem, BPMElement):
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.x], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.x], _DEFAULT_ERROR_VALUE)
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.y], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.y], _DEFAULT_ERROR_VALUE)
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.phase], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.phase], _DEFAULT_ERROR_VALUE)
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.energy], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.energy], _DEFAULT_ERROR_VALUE)
                elif isinstance(elem, PMElement):
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.x], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.x], _DEFAULT_ERROR_VALUE)
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.y], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.y], _DEFAULT_ERROR_VALUE)
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.xrms], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.xrms], _DEFAULT_ERROR_VALUE)
                    _LOGGER.debug("VirtualAccelerator: Update read: %s to %s",
                                  self._readfieldmap[elem.name][elem.fields.yrms], _DEFAULT_ERROR_VALUE)
                    catools.caput(self._readfieldmap[elem.name][elem.fields.yrms], _DEFAULT_ERROR_VALUE)
                else:
                    _LOGGER.warning("VirtualAccelerator: Output from element type not supported: %s",
                                    type(elem).__name__)

            # Allow the BPM, PM, etc. readbacks to update
            # before the device setting readbacks PVs.
            cothread.Yield()

            for name, value in self._csetmap.items():
                name, field = self._fieldmap[name]
                _LOGGER.debug("VirtualAccelerator: Update read: %s to %s", value[1], settings[name][field])
                catools.caput(value[1], settings[name][field])

            # Sleep for a fraction (10%) of the total execution time 
            # when one simulation costs more than 0.50 seconds.
            # Otherwise, sleep for the rest of 1 second. 
            # If a scan is being done on this virtual accelerator,
            # then the scan server has a period of time to update
            # setpoints before the next run of IMPACT.
            if (time.time() - start) > 0.50:
                cothread.Sleep((time.time() - start) * 0.1)
            else:
                cothread.Sleep(1.0 - (time.time() - start))