wasatch 2.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wasatch/AbstractUSBDevice.py +29 -0
- wasatch/AndorDevice.py +910 -0
- wasatch/AreaScanImage.py +19 -0
- wasatch/AutoRaman.py +457 -0
- wasatch/AutoRamanRequest.py +96 -0
- wasatch/BLEDevice.py +1032 -0
- wasatch/BalanceAcquisition.py +136 -0
- wasatch/CSVLoader.py +188 -0
- wasatch/CommandSettings.py +95 -0
- wasatch/ControlObject.py +17 -0
- wasatch/DetectorROI.py +36 -0
- wasatch/DetectorRegions.py +158 -0
- wasatch/DeviceFinderBLE.py +107 -0
- wasatch/DeviceFinderTCP.py +20 -0
- wasatch/DeviceFinderUSB.py +236 -0
- wasatch/DeviceID.py +344 -0
- wasatch/EEPROM.py +1450 -0
- wasatch/EEPROM_multical.sav +48 -0
- wasatch/FPGAOptions.py +125 -0
- wasatch/FeatureIdentificationDevice.py +3961 -0
- wasatch/FirmwareRequirements.py +76 -0
- wasatch/HardwareInfo.py +36 -0
- wasatch/IDSCamera.py +916 -0
- wasatch/IDSDevice.py +329 -0
- wasatch/IMX385.py +179 -0
- wasatch/InterfaceDevice.py +40 -0
- wasatch/MockUSBDevice.py +353 -0
- wasatch/OceanDevice.py +215 -0
- wasatch/PollStatus.py +15 -0
- wasatch/ProcessedReading.py +352 -0
- wasatch/ROI.py +33 -0
- wasatch/Reading.py +80 -0
- wasatch/RealUSBDevice.py +64 -0
- wasatch/SPIDevice.py +628 -0
- wasatch/SpectrometerRequest.py +15 -0
- wasatch/SpectrometerResponse.py +38 -0
- wasatch/SpectrometerSettings.py +446 -0
- wasatch/SpectrometerState.py +255 -0
- wasatch/StatusMessage.py +14 -0
- wasatch/TCPDevice.py +409 -0
- wasatch/TakeOneRequest.py +43 -0
- wasatch/WasatchBus.py +87 -0
- wasatch/WasatchDevice.py +1060 -0
- wasatch/WasatchDeviceWrapper.py +452 -0
- wasatch/WrapperWorker.py +304 -0
- wasatch/__init__.py +4 -0
- wasatch/applog.py +177 -0
- wasatch/simulation_protocol.py +227 -0
- wasatch/utils.py +731 -0
- wasatch-2.3.2.dist-info/LICENSE +21 -0
- wasatch-2.3.2.dist-info/METADATA +347 -0
- wasatch-2.3.2.dist-info/RECORD +53 -0
- wasatch-2.3.2.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Simulated device components for demonstration program. Simple blocking calls
|
|
3
|
+
# with simulated delays for simulated spectrometer readings. Long-polling
|
|
4
|
+
# multiprocessing wrappers.
|
|
5
|
+
#
|
|
6
|
+
# @warning none of this is currently used
|
|
7
|
+
|
|
8
|
+
import copy
|
|
9
|
+
import time
|
|
10
|
+
import logging
|
|
11
|
+
import numpy
|
|
12
|
+
|
|
13
|
+
log = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Read recorded spectrum from file, respond with noise on the
|
|
17
|
+
# baseline read from file. Default spectrum is pure noise from numpy.
|
|
18
|
+
# When the laser is on, it's the IPA csv entry (0). This is designed
|
|
19
|
+
# to simulate a vial of IPA in a holder. Changing the integration time
|
|
20
|
+
# scales just the noise on the spectrum. A integration time of 1 has
|
|
21
|
+
# 1-10k counts of noise. An integration time of 10k has 0-1 counts of
|
|
22
|
+
# noise.
|
|
23
|
+
class SimulateMaterial:
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
super(SimulateMaterial, self).__init__()
|
|
27
|
+
log.debug("%s setup", self.__class__.__name__)
|
|
28
|
+
|
|
29
|
+
self.serial_number = "SIM-512"
|
|
30
|
+
self.software_code = "SIM.0.0.1"
|
|
31
|
+
self.fpga_revision = "SIM.022-007"
|
|
32
|
+
|
|
33
|
+
self.pixels = 1024
|
|
34
|
+
self.ccd_gain = 1.9
|
|
35
|
+
|
|
36
|
+
self.max_integration = 10000 # ms
|
|
37
|
+
self.min_integration = 1 # ms
|
|
38
|
+
|
|
39
|
+
# For a simple inverse relationship of noise apperance
|
|
40
|
+
self.integration = self.min_integration
|
|
41
|
+
self.noise_level = self.max_integration - self.integration
|
|
42
|
+
|
|
43
|
+
# Add to max integration to always show noise
|
|
44
|
+
self.noise_margin = 100
|
|
45
|
+
|
|
46
|
+
randint = numpy.random.randint
|
|
47
|
+
startup_noise = randint(low=0, high=self.noise_level, size=self.pixels)
|
|
48
|
+
self.startup_noise = startup_noise
|
|
49
|
+
#print "All startup nosie: %s level %s" % (startup_noise, self.noise_level)
|
|
50
|
+
|
|
51
|
+
self.initial_data = self.startup_noise
|
|
52
|
+
|
|
53
|
+
self.ipa_data = numpy.asarray(self.load_raw_data()[0])
|
|
54
|
+
self.signal_modifier = self.integration
|
|
55
|
+
self.ipa_data = self.ipa_data / self.signal_modifier
|
|
56
|
+
|
|
57
|
+
self.laser_status = "disable"
|
|
58
|
+
self.detector_tec_setpoint_degC = 15.0
|
|
59
|
+
self.detector_tec_enable = 0
|
|
60
|
+
self.ccd_adc_setpoint = 2047 # Midway of a 12bit ADC
|
|
61
|
+
|
|
62
|
+
# Defaults from Original (stroker-era) settings. These are known
|
|
63
|
+
# to set ccd setpoints effectively for stroker 785 class units.
|
|
64
|
+
self.original_degC_to_dac_coeff_0 = 3566.62
|
|
65
|
+
self.original_degC_to_dac_coeff_1 = -143.543
|
|
66
|
+
self.original_degC_to_dac_coeff_2 = -0.324723
|
|
67
|
+
|
|
68
|
+
self.degC_to_dac_coeff_0 = self.original_degC_to_dac_coeff_0
|
|
69
|
+
self.degC_to_dac_coeff_1 = self.original_degC_to_dac_coeff_1
|
|
70
|
+
self.degC_to_dac_coeff_2 = self.original_degC_to_dac_coeff_2
|
|
71
|
+
|
|
72
|
+
self.model = "785"
|
|
73
|
+
# Set default to zero bad pixels which is a list of -1's of
|
|
74
|
+
# length 15
|
|
75
|
+
self.bad_pixels = []
|
|
76
|
+
for _ in range(15):
|
|
77
|
+
self.bad_pixels.append(-1)
|
|
78
|
+
|
|
79
|
+
## Return the spectrum read from file. Add the noise.
|
|
80
|
+
def read(self):
|
|
81
|
+
randint = numpy.random.randint
|
|
82
|
+
temp_data = randint(low=0, high=self.noise_level, size=self.pixels)
|
|
83
|
+
|
|
84
|
+
if self.laser_status == "enable":
|
|
85
|
+
temp_data += copy.copy(self.ipa_data)
|
|
86
|
+
|
|
87
|
+
return temp_data
|
|
88
|
+
|
|
89
|
+
## Wrap the read data simulation in a sleep-wait to ensure fidelity for
|
|
90
|
+
# longer exposure integration times.
|
|
91
|
+
def get_line(self):
|
|
92
|
+
wait_interval = (1.0 * self.integration) / 1000.0
|
|
93
|
+
log.debug("Waiting %sms", wait_interval)
|
|
94
|
+
time.sleep(wait_interval)
|
|
95
|
+
return self.read()
|
|
96
|
+
|
|
97
|
+
## Perform the specified setting such as simulating a laser enable,
|
|
98
|
+
# changing the integration time, turning the cooler on etc.
|
|
99
|
+
def write_setting(self, record):
|
|
100
|
+
|
|
101
|
+
log.debug("Changing %s to: %s", record.setting, record.value)
|
|
102
|
+
if record.setting == "laser":
|
|
103
|
+
self.laser_status = record.value
|
|
104
|
+
|
|
105
|
+
elif record.setting == "integration":
|
|
106
|
+
self.integration = int(record.value)
|
|
107
|
+
log.debug("Set integration to: %s", self.integration)
|
|
108
|
+
|
|
109
|
+
temp_margin = self.max_integration + self.noise_margin
|
|
110
|
+
self.noise_level = temp_margin - self.integration
|
|
111
|
+
log.debug("Set noise level to: %s", self.noise_level)
|
|
112
|
+
|
|
113
|
+
elif record.setting == "detector_tec_setpoint_degC":
|
|
114
|
+
self.detector_tec_setpoint_degC = int(record.value)
|
|
115
|
+
|
|
116
|
+
elif record.setting == "degC_to_dac_coeffs":
|
|
117
|
+
self.set_degC_to_dac_coeffs(record.value)
|
|
118
|
+
|
|
119
|
+
elif record.setting == "detector_tec_enable":
|
|
120
|
+
self.detector_tec_enable = int(record.value)
|
|
121
|
+
|
|
122
|
+
else:
|
|
123
|
+
log.critical("Unknown setting: %s", record.setting)
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
return True
|
|
127
|
+
|
|
128
|
+
##
|
|
129
|
+
# Temporary solution for modifying the CCD TEC setpoint
|
|
130
|
+
# calibration coefficients. These are used as part of a third
|
|
131
|
+
# order polynomial for transforming the setpoint temperature into
|
|
132
|
+
# an AD value. Expects a great deal of accuracy on part of the
|
|
133
|
+
# user, otherwise sets default.
|
|
134
|
+
def set_degC_to_dac_coeffs(self, coeffs):
|
|
135
|
+
degC_to_dac_coeff_0 = self.original_degC_to_dac_coeff_0
|
|
136
|
+
degC_to_dac_coeff_1 = self.original_degC_to_dac_coeff_1
|
|
137
|
+
degC_to_dac_coeff_2 = self.original_degC_to_dac_coeff_2
|
|
138
|
+
try:
|
|
139
|
+
(degC_to_dac_coeff_0, degC_to_dac_coeff_1, degC_to_dac_coeff_2) = coeffs.split(" ")
|
|
140
|
+
except Exception as exc:
|
|
141
|
+
log.critical("TEC Coeffs split failiure: %s", exc)
|
|
142
|
+
log.critical("Setting original class coeffs")
|
|
143
|
+
|
|
144
|
+
self.degC_to_dac_coeff_0 = float(degC_to_dac_coeff_0)
|
|
145
|
+
self.degC_to_dac_coeff_1 = float(degC_to_dac_coeff_1)
|
|
146
|
+
self.degC_to_dac_coeff_2 = float(degC_to_dac_coeff_2)
|
|
147
|
+
log.info("Succesfully changed CCD TEC setpoint coefficients")
|
|
148
|
+
|
|
149
|
+
##
|
|
150
|
+
# Apparently MS windows keeps some portion of the dictreader
|
|
151
|
+
# in place that prevents a clean exit in multiprocessing
|
|
152
|
+
# applications. This will only manifest when attempting to close
|
|
153
|
+
# the enlighten software. The temporary fix here is to load the
|
|
154
|
+
# file directly from disk, and manually slice the data required.
|
|
155
|
+
def load_raw_data(self, filename=None):
|
|
156
|
+
if filename is None:
|
|
157
|
+
filename = "enlighten/assets/example_data/"
|
|
158
|
+
filename += "Spectra_093016_785L_192.csv"
|
|
159
|
+
|
|
160
|
+
log.info("Raw data load file: %s", filename)
|
|
161
|
+
csv_data = []
|
|
162
|
+
line_count = 0
|
|
163
|
+
with open(filename, "r") as csv_file:
|
|
164
|
+
for line_data in csv_file:
|
|
165
|
+
if line_count > 1:
|
|
166
|
+
line_data = line_data.replace('"','')
|
|
167
|
+
commas = [x.strip() for x in line_data.split(",")]
|
|
168
|
+
ints = [int(x.strip()) for x in commas[17:]]
|
|
169
|
+
csv_data.append(ints)
|
|
170
|
+
#log.info("Strip: %s", csv_data)
|
|
171
|
+
line_count += 1
|
|
172
|
+
return csv_data
|
|
173
|
+
|
|
174
|
+
## Placeholder to log disconnect event.
|
|
175
|
+
def disconnect(self):
|
|
176
|
+
log.info("Disconnect")
|
|
177
|
+
return True
|
|
178
|
+
|
|
179
|
+
def get_serial_number(self):
|
|
180
|
+
return self.serial_number
|
|
181
|
+
|
|
182
|
+
def get_standard_software_code(self):
|
|
183
|
+
return self.software_code
|
|
184
|
+
|
|
185
|
+
def get_integration_time_ms(self):
|
|
186
|
+
return self.integration
|
|
187
|
+
|
|
188
|
+
def get_fpga_revision(self):
|
|
189
|
+
return self.fpga_revision
|
|
190
|
+
|
|
191
|
+
def get_ccd_gain(self):
|
|
192
|
+
return self.ccd_gain
|
|
193
|
+
|
|
194
|
+
def get_model_number(self):
|
|
195
|
+
return self.model
|
|
196
|
+
|
|
197
|
+
## Simulate a 12-bit AD
|
|
198
|
+
def get_detector_temperature_raw(self):
|
|
199
|
+
adc_wiggle = 100
|
|
200
|
+
adc_min = self.ccd_adc_setpoint - adc_wiggle
|
|
201
|
+
adc_max = self.ccd_adc_setpoint + adc_wiggle
|
|
202
|
+
|
|
203
|
+
adc_value = numpy.random.uniform(low=adc_min, high=adc_max)
|
|
204
|
+
log.debug("RAW adc: %s", adc_value)
|
|
205
|
+
|
|
206
|
+
return adc_value
|
|
207
|
+
|
|
208
|
+
## Return randomized laser and detector temperature simulation within range.
|
|
209
|
+
def get_detector_temperature_degC(self, raw=0):
|
|
210
|
+
detector_wiggle_degC = 2.0
|
|
211
|
+
detector_min_degC = self.detector_tec_setpoint_degC - detector_wiggle_degC
|
|
212
|
+
detector_max_degC = self.detector_tec_setpoint_degC + detector_wiggle_degC
|
|
213
|
+
detector_temp_degC = numpy.random.uniform(low=detector_min_degC, high=detector_max_degC)
|
|
214
|
+
log.debug("CCD: %s", detector_temp_degC)
|
|
215
|
+
return detector_temp_degC
|
|
216
|
+
|
|
217
|
+
def get_laser_temperature_raw(self):
|
|
218
|
+
return numpy.random.randint(4096)
|
|
219
|
+
|
|
220
|
+
## Return randomized laser and ccd temperature simulation within range.
|
|
221
|
+
def get_laser_temperature_degC(self, raw=0):
|
|
222
|
+
laser_temp = numpy.random.uniform(low=35.0, high=45.0)
|
|
223
|
+
log.debug("LASER: %s", laser_temp)
|
|
224
|
+
return laser_temp
|
|
225
|
+
|
|
226
|
+
def get_sensor_line_length(self):
|
|
227
|
+
return self.pixels
|