Exemple #1
0
 def read(self):
     self.init()
     data_arr = numpy.zeros(self.io_length, uInt8)
     samples_per_chan = int32()
     num_bytes_per_sample = int32()
     DAQmxReadDigitalLines(self.task,
                           1,  # Samples per channel
                           2.0,  # Timeout
                           DAQmx_Val_GroupByScanNumber,  # Interleaved
                           data_arr,
                           len(data_arr),
                           byref(samples_per_chan),
                           byref(num_bytes_per_sample),
                           None)
     return data_arr
Exemple #2
0
    def setupNICard(self):
        ## create the NI task that reads data from the NI card.
        #self.taskHandle = TaskHandle()
        #DAQmxCreateTask("pyEnvDAQ",byref(self.taskHandle))
        ## (see http://zone.ni.com/reference/en-XX/help/370471AE-01/daqmxcfunc/daqmxcreatetask/ )
        ##[DAQmxCreateAIVoltageChan(self.taskHandle, "Dev1/ai"+str(self.channelAddresses[i]), self.channelNames[i+1], DAQmx_Val_Cfg_Default, int(self.channelMins[i+1]), \
        ##    int(self.channelMaxes[i+1]), DAQmx_Val_Volts, None) for i in range(self.numOfRecordedChannels)] # we use i+1 instead of i to skip the time channel
        ##print("numOfNIChannels: ",self.numOfNIChannels)
        #channelIndices = ["Dev1/ai"+str(self.channelIndex[i]) for i in range(self.numOfNIChannels)] # note that this also contains the time channel
        ##[print("channel index: ",channelIndices[i]," name: ",self.channelNames[i]," min ",int(self.channelMins[i]), \
        ##    "max ",int(self.channelMaxes[i]),"\n") for i in range(1,self.numOfNIChannels)]
        #[DAQmxCreateAIVoltageChan(self.taskHandle, channelIndices[i], self.channelNames[i], DAQmx_Val_Cfg_Default, int(self.channelMins[i]), \
        #    int(self.channelMaxes[i]), DAQmx_Val_Volts, None) for i in range(1,self.numOfNIChannels)] # we start from 1 to skip the time channel
        #
        #DAQmxCfgSampClkTiming(self.taskHandle,"",1/self.MEASUREMENT_PERIOD_s,DAQmx_Val_Rising,DAQmx_Val_ContSamps,self.numOfNIChannels-1) # -1 because we don't actually record the time channel
        ## (see http://zone.ni.com/reference/en-XX/help/370471AE-01/daqmxcfunc/daqmxcfgsampclktiming/ )
        ##
        #try:
        #    DAQmxStartTask(self.taskHandle)
        #except DAQError:
        #    self.printError("execution of DAQmxStartTask failed - THe-Monitor is probably on \"Run\". Try \"Pause\"ing it and restarting PyEnvDAQ.")

        self.taskHandle = TaskHandle()
        #DAQmxLoadTask("enviroment_measurement",byref(self.taskHandle))
        DAQmxLoadTask("PyEnvDAQTask", byref(self.taskHandle))
        DAQmxStartTask(self.taskHandle)
Exemple #3
0
 def init(self):
     if self.task_state == "":
         self.task = TaskHandle()
         DAQmxCreateTask(b"", byref(self.task))
         DAQmxCreateDOChan(self.task, self.task_string, b"",
                           DAQmx_Val_ChanPerLine)
         self.task_state = "init"
Exemple #4
0
 def _read(self):
     try:
         DAQmxReadCounterScalarF64(self.task, float64(self._thread_timeout),
                                   byref(self._data), None)
     except Exception as e:
         self._error_queue.put(ThreadError(e))
     return
Exemple #5
0
 def init(self):
     if self.task_state == "":
         self.task = TaskHandle()
         DAQmxCreateTask(b"", byref(self.task))
         DAQmxCreateDIChan(self.task, self.task_string, b"", DAQmx_Val_ChanPerLine)
         self.task_state = "init"
     if self.task_state in ["init", "stopped"]:
         self.start()
def finish_count(pulse, ctr):
    """ finish counting events and return the result. """
    # initialize memory for readout
    count = uInt32()
    # wait for pulse to be done
    pulse.WaitUntilTaskDone(10.)
    # timeout, ref to output value, reserved
    ctr.ReadCounterScalarU32(10., byref(count), None)
    pulse.StopTask()
    ctr.StopTask()
    return count.value
def port_supports_buffered(device_name, port, clock_terminal=None):
    """Empirically determines if the digital port supports buffered output.

    Args:
        device_name (str): NI-MAX device name
        port (int): Which port to intro-spect
        clock_terminal (str, optional): String that specifies the clock terminal.

    Returns:
        bool: True if `port` supports buffered output.
    """
    all_terminals = DAQmxGetDevTerminals(device_name)
    if clock_terminal is None:
        clock_terminal = all_terminals[0]
    npts = 16
    task = Task()
    clock_terminal_full = '/' + device_name + '/' + clock_terminal
    data = np.zeros(npts, dtype=np.uint32)
    task.CreateDOChan(device_name + "/" + port, "", c.DAQmx_Val_ChanForAllLines)
    task.CfgSampClkTiming(
        clock_terminal_full, 100, c.DAQmx_Val_Rising, c.DAQmx_Val_FiniteSamps, npts
    )
    written = int32()
    try:
        task.WriteDigitalU32(
            npts, False, 10.0, c.DAQmx_Val_GroupByScanNumber, data, byref(written), None
        )
    except (
        PyDAQmx.DAQmxFunctions.BufferedOperationsNotSupportedOnSelectedLinesError,
        PyDAQmx.DAQmxFunctions.PhysicalChanNotSupportedGivenSampTimingType653xError,
    ):
        return False
    except (
        PyDAQmx.DAQmxFunctions.CantUsePort3AloneGivenSampTimingTypeOn653xError,
        PyDAQmx.DAQmxFunctions.CantUsePort1AloneGivenSampTimingTypeOn653xError,
    ):
        # Ports that throw this error on 653x devices do support buffered output, though
        # there are requirements that multiple ports be used together.
        return True
    except PyDAQmx.DAQmxFunctions.RouteNotSupportedByHW_RoutingError:
        # Try again with a different terminal
        current_terminal_index = all_terminals.index(clock_terminal)
        if current_terminal_index == len(all_terminals) - 1:
            # There are no more terminals. No terminals can be used as clocks,
            # therefore we cannot do externally clocked buffered output.
            return False
        next_terminal_to_try = all_terminals[current_terminal_index + 1]
        return port_supports_buffered(device_name, port, next_terminal_to_try)
    else:
        return True
    finally:
        task.ClearTask()
Exemple #8
0
    def wrapped(name):
        import warnings

        with warnings.catch_warnings():
            # PyDAQmx warns about a positive return value, but actually this is how you
            # are supposed to figure out the size of the array required.
            warnings.simplefilter("ignore")
            # Pass in null pointer and 0 len to ask for what array size is needed:
            npts = func(name, byref(float64()), 0)
        # Create that array
        result = (float64 * npts)()
        func(name, result, npts)
        result = [result[i] for i in range(npts)]
        return result
Exemple #9
0
    def init(self):
        if self.task_state == "":
            self.task = TaskHandle()
            DAQmxCreateTask(b"", byref(self.task))
            DAQmxCreateCITwoEdgeSepChan(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(), b"",
                                        float64(self.min_val), float64(self.max_val), DAQmx_Val_Seconds,
                                        self.first_edge_type,
                                        self.second_edge_type, b"")
            if self.source_terminal:
                tmp_data = c_char_p(self.source_terminal.encode())
                DAQmxSetCITwoEdgeSepFirstTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(),
                                              tmp_data)
                if self.validate_terminals:
                    tmp_data = c_char_p("".encode())
                    DAQmxGetCITwoEdgeSepFirstTerm(self.task,
                                                  "{}/{}".format(self.device_name, self.counter_chan).encode(),
                                                  tmp_data,
                                                  uInt32(16))
                    if self.destination_terminal not in tmp_data.value.decode('utf-8'):
                        raise InstrumentError(
                            "Destination terminal is set to {}, should be /{}/{}".format(tmp_data.value.decode('utf-8'),
                                                                                         self.device_name,
                                                                                         self.destination_terminal))

            if self.destination_terminal:
                tmp_data = c_char_p(self.destination_terminal.encode())
                DAQmxSetCITwoEdgeSepSecondTerm(self.task, "{}/{}".format(self.device_name, self.counter_chan).encode(),
                                               tmp_data)
                if self.validate_terminals:
                    tmp_data = c_char_p("".encode())
                    DAQmxGetCITwoEdgeSepSecondTerm(self.task,
                                                   "{}/{}".format(self.device_name, self.counter_chan).encode(),
                                                   tmp_data,
                                                   uInt32(16))
                    if self.destination_terminal not in tmp_data.value.decode('utf-8'):
                        raise InstrumentError(
                            "Destination terminal is set to {}, should be /{}/{}".format(tmp_data.value.decode('utf-8'),
                                                                                         self.device_name,
                                                                                         self.destination_terminal))
            self.task_state = "init"
Exemple #10
0
 def wrapped(name):
     result = float64()
     func(name, byref(result))
     return result.value
Exemple #11
0
 def wrapped(name):
     result = int32()
     func(name, byref(result))
     return result.value
Exemple #12
0
 def wrapped(name):
     result = bool32()
     func(name, byref(result))
     return bool(result.value)
Exemple #13
0
 def _read(self):
     self.init()
     return DAQmxReadCounterScalarF64(self.task, float64(10), byref(self._data), None)
Exemple #14
0
 def measure(self):
     """
     Acquire once using the created task.
     """
     if len(self.data.cols) == 0:
         return BaseDriver.measure(self)
     ### measure ###########################################################
     # unpack inputs -------------------------------------------------------
     self.running = True
     #self.update_ui.emit()
     if not self.task_created:
         return
     start_time = time.time()
     # collect samples array -----------------------------------------------
     try:
         self.thread 
         self.read = int32()
         if True:
             DAQmxStartTask(self.task_handle)
             DAQmxReadAnalogF64(self.task_handle,             # task handle
                                int(self.shots),              # number of samples per channel
                                10.0,                         # timeout (seconds) for each read operation
                                DAQmx_Val_GroupByScanNumber,  # fill mode (specifies whether or not the samples are interleaved)
                                self.samples,                 # read array
                                self.samples_len,             # size of the array, in samples, into which samples are read
                                byref(self.read),             # reference of thread
                                None)                         # reserved by NI, pass NULL (?)
             DAQmxStopTask(self.task_handle)                       
         else:
             self.samples = np.random.normal(size=self.samples_len)
     except DAQError as err:
         print("DAQmx Error: %s"%err)
         g.logger.log('error', 'Error in timing definition', err)
         DAQmxStopTask(self.task_handle)
         DAQmxClearTask(self.task_handle)
     # export samples
     samples.write(self.samples)
     ### process ###########################################################
     # calculate shot values for each channel, chopper ---------------------
     active_channels = [channel for channel in channels.read() if channel.active.read()]
     active_choppers = [chopper for chopper in choppers.read() if chopper.active.read()]
     shots_array = np.full((len(active_channels)+len(active_choppers), int(self.shots)), np.nan)
     folded_samples = self.samples.copy().reshape((nsamples.read(), -1), order='F')
     index = 0
     # channels
     for channel_index, channel in enumerate(active_channels):
         # get signal points
         signal_index_possibilities = range(int(channel.signal_start_index.read()), int(channel.signal_stop_index.read()) + 1)
         signal_indicies = [i for i in signal_index_possibilities if sample_correspondances.read()[i] == channel_index + 1]
         signal_indicies = signal_indicies[int(channel.signal_pre_index.read()):]  # remove pre points
         signal_samples = folded_samples[signal_indicies]
         # process signal
         if channel.signal_method.read() == 'Average':
             signal = np.mean(signal_samples, axis=0)
         elif channel.signal_method.read() == 'Sum':
             signal = np.sum(signal_samples, axis=0)
         elif channel.signal_method.read() == 'Min':
             signal = np.min(signal_samples, axis=0)
         elif channel.signal_method.read() == 'Max':
             signal = np.max(signal_samples, axis=0)
         # baseline
         if channel.use_baseline.read():
             # get baseline points
             baseline_index_possibilities = range(int(channel.baseline_start_index.read()), int(channel.baseline_stop_index.read()) + 1)
             baseline_indicies = [i for i in baseline_index_possibilities if sample_correspondances.read()[i] == channel_index + 1]
             baseline_indicies = baseline_indicies[int(channel.baseline_pre_index.read()):]  # remove pre points
             baseline_samples = folded_samples[baseline_indicies]
             # process baseline
             if channel.baseline_method.read() == 'Average':
                 baseline = np.mean(baseline_samples, axis=0)
             elif channel.baseline_method.read() == 'Sum':
                 baseline = np.sum(baseline_samples, axis=0)
             elif channel.baseline_method.read() == 'Min':
                 baseline = np.min(baseline_samples, axis=0)
             elif channel.baseline_method.read() == 'Max':
                 baseline = np.max(baseline_samples, axis=0)
         else:
             baseline = 0
         out = signal - baseline
         # invert
         if channel.invert.read():
             out *= -1
         # finish
         shots_array[index] = out
         index += 1
     # choppers
     for chopper in active_choppers:
         cutoff = 1. # volts
         out = folded_samples[int(chopper.index.read())]
         out[out<=cutoff] = -1.
         out[out>cutoff] = 1.            
         if chopper.invert.read():
             out *= -1
         shots_array[index] = out
         index += 1
     # export shots
     channel_names = [channel.name.read() for channel in active_channels]
     chopper_names = [chopper.name.read() for chopper in active_choppers]
     shots.write(shots_array)  # TODO: can I remove this?
     shots.write_properties((1,), channel_names+chopper_names, shots_array)
     # do math -------------------------------------------------------------
     # pass through shots processing module
     with self.processing_timer:
         path = shots_processing_module_path.read()
         name = os.path.basename(path).split('.')[0]
         directory = os.path.dirname(path)
         f, p, d = imp.find_module(name, [directory])
         processing_module = imp.load_module(name, f, p, d)
         kinds = ['channel' for _ in channel_names] + ['chopper' for _ in chopper_names]
         names = channel_names + chopper_names
         out = processing_module.process(shots_array, names, kinds)
         if len(out) == 3:
             out, out_names, out_signed = out
         else:
             out, out_names = out
             out_signed = False
         
     seconds_for_shots_processing.write(self.processing_timer.interval)
     # export last data
     self.data.write_properties((1,), out_names, out, out_signed)
     self.update_ui.emit()
     ### finish ############################################################
     seconds_since_last_task.write(time.time() - self.previous_time)
     self.previous_time = time.time()
     self.running = False
     stop_time = time.time()
     seconds_for_acquisition.write(stop_time - start_time)
     self.measure_time.write(seconds_for_acquisition.read())
Exemple #15
0
 def create_task(self):
     '''
     Define a new DAQ task. This needs to be run once every time the
     parameters of the aquisition (channel correspondance, shots, etc.)
     change.
     
     No inputs
     '''
     # ensure previous task closed -----------------------------------------
     if self.task_created:
         DAQmxStopTask(self.task_handle)
         DAQmxClearTask(self.task_handle)
     self.task_created = False
     # import --------------------------------------------------------------
     self.shots = nshots.read()
     # calculate the number of 'virtual samples' to take -------------------
     self.virtual_samples = nsamples.read()
     # create task ---------------------------------------------------------
     try:
         self.task_handle = TaskHandle()
         self.read = int32()  # ??? --BJT 2017-06-03
         DAQmxCreateTask('', byref(self.task_handle))
     except DAQError as err:
         print("DAQmx Error: %s"%err)
         g.logger.log('error', 'Error in task creation', err)
         DAQmxStopTask(self.task_handle)
         DAQmxClearTask(self.task_handle)
         return
     # initialize channels -------------------------------------------------
     # The daq is addressed in a somewhat non-standard way. A total of ~1000 
     # virtual channels are initialized (depends on DAQ speed and laser rep 
     # rate). These virtual channels are evenly distributed over the physical
     # channels addressed by the software. When the task is run, it round
     # robins over all the virtual channels, essentially oversampling the
     # analog physical channels.
     #
     # self.virtual_samples contains the oversampling factor.
     #
     # Each virtual channel must have a unique name.
     #
     # The sample clock is supplied by the laser output trigger.
     #
     name_index = 0  # something to keep channel names unique
     try:
         # sample correspondances holds an array of integers
         # zero : rest sample
         # positive : channel
         # negative : chopper
         for correspondance in sample_correspondances.read():
             if correspondance == 0:
                 physical_channel = rest_channel.read()
                 min_voltage = -10.
                 max_voltage = 10.
             elif correspondance > 0:
                 channel = channels.read()[correspondance-1]
                 physical_channel = channel.physical_correspondance.read()
                 min_voltage, max_voltage = channel.get_range()
             elif correspondance < 0:
                 physical_channel = choppers.read()[-correspondance-1].physical_correspondance.read()
                 min_voltage = -10.
                 max_voltage = 10.
             channel_name = 'sample_' + str(name_index).zfill(3)
             DAQmxCreateAIVoltageChan(self.task_handle,                            # task handle
                                      DAQ_device_name + '/ai%i'%physical_channel,  # physical chanel
                                      channel_name,                                # name to assign to channel
                                      DAQmx_Val_Diff,                              # the input terminal configuration
                                      min_voltage, max_voltage,                    # minVal, maxVal
                                      DAQmx_Val_Volts,                             # units 
                                      None)                                        # custom scale
             name_index += 1
     except DAQError as err:
         print("DAQmx Error: %s"%err)
         g.logger.log('error', 'Error in virtual channel creation', err)
         DAQmxStopTask(self.task_handle)
         DAQmxClearTask(self.task_handle)
         return
     # define timing -------------------------------------------------------
     try:
         DAQmxCfgSampClkTiming(self.task_handle,                 # task handle
                               '/' + DAQ_device_name + '/PFI0',  # sorce terminal
                               1000.0,                           # sampling rate (samples per second per channel) (float 64) (in externally clocked mode, only used to initialize buffer)
                               DAQmx_Val_Rising,                 # acquire samples on the rising edges of the sample clock
                               DAQmx_Val_FiniteSamps,            # acquire a finite number of samples
                               int(self.shots))                 # samples per channel to acquire (unsigned integer 64)         
     except DAQError as err:
         print("DAQmx Error: %s"%err)
         g.logger.log('error', 'Error in timing definition', err)
         DAQmxStopTask(self.task_handle)
         DAQmxClearTask(self.task_handle)
         return
     # create arrays for task to fill --------------------------------------
     self.samples = np.zeros(int(self.shots*nsamples.read()), dtype=np.float64)
     self.samples_len = len(self.samples)  # do not want to call for every acquisition
     # finish --------------------------------------------------------------
     self.task_created = True
     self.task_changed.emit()
Exemple #16
0
    def readEnvData(self):
        print("started readEnvData \n"
              )  # commenting this out stops the program from working. why?
        dataForTable = zeros(
            self.numOfChannels + 1, dtype=float64
        )  # this will hold the data to update the table with. (+1 to include the time channel)
        # setup NI card-related parameters
        dataNI = zeros(
            (self.numOfNIChannels, ), dtype=float64
        )  # this will hold the data gathered in a single measurement. -1 because we don't record the time.
        timeOut = 10  # 10s timeout limit?
        read = int32()  # the type of data read is 32int?
        session = requests.Session()
        session.trust_env = False
        while self.isRunning == True:
            # retrieve the data from the MSC box (which is saved after the data from the NI card)
            # setup MCS box-related parameters
            res = session.get(
                'http://tritium-remotemcs/cgi-bin/volt.cgi'
            )  # we also get something if we replace "volt" with "temp", but I don't get the values there
            content = str(
                res.content,
                "windows-1252")  # get the whole HTML code for that page
            content = content[
                419:]  # delete some bullshit before the first value
            content = content.replace(
                "</td><td>", ","
            )  # separate the values with commas instead of with bullshit
            content = content.replace(
                "</td></tr></table><br><table border=1><colgroup width=200 span=4></colgroup><tr><td><b>channel 5</b>,<b>channel 6</b>,<b>channel 7</b>,<b>channel 8</b></td></tr><tr><td>",
                ",")  # remove bullshit
            content = content[:-22]  # get rid of some last bullshit
            content = content.split(",")
            dataMCS = [int(i, 16) for i in content
                       ]  # convert the data from hexadecimal to decimal format
            # (note that there are 8 values here but we only save the first 4 cause we don't know what the other 4 are for)            # retrieve data from NI card's channels.
            # see http://zone.ni.com/reference/en-XX/help/370471AE-01/daqmxcfunc/daqmxreadanalogf64/
            try:
                DAQmxReadAnalogF64(self.taskHandle, 1, timeOut, 0, dataNI,
                                   self.numOfNIChannels, byref(read), None)
            except DAQError as err:
                self.printError(
                    "execution of DAQmxReadAnalogF64 failed. Maybe THe-Monitor is running? If so \"Pause\" it and try again."
                )
                self.pauseMeasurement()
            else:  # this is only executed if no DAQError was raised during execution of the code in the "try:" block
                # self.checkForWarnings(dataNI) # check if some of the values are suspicious and should be reported
                timestamp = round(time())  # the time in units of s
                # save the flow data
                self.previousHeFlowMeterValue = self.currentHeFlowMeterValue
                self.previousN2FlowMeterValue = self.currentN2FlowMeterValue
                self.currentHeFlowMeterValue = dataNI[
                    self.HE_FLOW_METER_CHANNEL_INDEX]
                self.currentN2FlowMeterValue = dataNI[
                    self.N2_FLOW_METER_CHANNEL_INDEX]
                self.currentDataTimeStamp = timestamp

                # get MKS flow data#
                #resultMKSflow = self.clientMKSflow.read_input_registers(0x0001, 2)
                #i1MKSflow = resultMKSflow.registers[0]
                #i2MKSflow = resultMKSflow.registers[1]
                #dataMKSflow = struct.unpack('l',struct.pack('<HH',i1MKSflow,i2MKSflow))[0]/10000
                dataMKSflow = 0
                # merge the data from the NI card and from the MCS box
                data = []
                for blah in dataNI:
                    data.append(blah)
                for j in range(self.numOfMCSChannels):
                    data.append(dataMCS[j])
                data.append(dataMKSflow)
                # data = append(dataNI,dataMCS)
                # data = append(data,dataMKSflow)
                dataForTable[0] = timestamp
                for j in range(self.numOfChannels):
                    dataForTable[j + 1] = data[
                        j]  # +1 to skip [0] which holds the time channel
                dataPrecisionFormat = "{0:." + str(self.DATA_PRECISION) + "f}"
                writeMeIntoFile = str(timestamp) + "\t" + "\t".join([
                    dataPrecisionFormat.format(data[j])
                    for j in range(self.numOfChannels)
                ]) + "\n"
                # writeMeIntoFile = str(timestamp)+"\t" + "\t".join([str(data[j]) for j in range(self.numOfNIChannels-1+self.numOfMCSChannels)]) +"\n"
                #   (note that we save up to DATA_PRECISION=4 digits after the decimal point instead of 6 like in the original program)
                self.comDataRecording.signalNewData.emit(
                    dataForTable, writeMeIntoFile
                )  # emit a signal in order to trigger updatePyEnvFileAndGUI
                # (see http://stackoverflow.com/questions/7127075/what-exactly-the-pythons-file-flush-is-doing )
                sleep(
                    self.MEASUREMENT_PERIOD_s - 0.1
                )  # read at a higher rate than the card's to make sure the buffer is cleared