def fill_irregularly_sampled_signal_with_zeros( irregular_sig: IrregularlySampledSignal, sampling_rate: Quantity(10000, "Hz") ) -> AnalogSignal: # allocate array for the regular signal num_regular_samples = ceil( Quantity(irregular_sig.duration * sampling_rate).magnitude) regular_sig = Quantity(np.zeros(num_regular_samples, dtype=np.float64), irregular_sig.dimensionality) # calculate the indices of the samples idcs: Quantity = (irregular_sig.times - irregular_sig.times[0]) * sampling_rate idcs = idcs.magnitude to_int = np.vectorize(np.int) idcs = to_int(idcs) # conversion step regular_sig[idcs] = irregular_sig[:].ravel() result: AnalogSignal = AnalogSignal(regular_sig, t_start=irregular_sig.times[0], sampling_rate=sampling_rate) return result
def convert_substance(substance, to_units, from_units=molecule): if not isinstance(substance, Quantity): if not isinstance(from_units, Quantity): from_units = substance_units[from_units] # assumes from_units is a mappable string substance = Quantity(substance, from_units) if not isinstance(to_units, Quantity): to_units = substance_units[to_units] # assumes to_units is a mappable string return substance.rescale(to_units)
def __array_finalize__(self, obj): Quantity.__array_finalize__(self, obj) self._uncertainty = getattr( obj, 'uncertainty', Quantity( np.zeros(self.shape, self.dtype), self._dimensionality, copy=False))
def _interpolate(self): # Extract x, y, z points points = list(zip(*self._control_points)) self._tck, self._u = interp.splprep(points, s=0) if self._num_points is None: # Reinterpolate with so many points that the trajectory doesn't move (both # translation and rotation taken into account) by more than pixel size between two # consecutive parameter values self._derivatives = interp.splev(self._u, self._tck, der=1) self._length = self._get_length() * q.m max_du = self.get_maximum_du() coeff = max(np.gradient(self.parameter)) / max_du # Use 4 times more points then approximated to try to fit the curve the best n = 4 * int(np.ceil(coeff * len(self.parameter))) if coeff > 1 else len( self.parameter) else: n = self._num_points LOG.debug("Using {} points for interpolation".format(n)) # Reinterpolate based on the updated number of points self._tck, self._u = reinterpolate(self._tck, self._u, n) self._points = np.array(interp.splev(self._u, self._tck)) * q.m self._derivatives = interp.splev(self._u, self._tck, der=1) self._length = self._get_length() * q.m # Velocity profile time_dist = None if self._velocity is not None: # Constant velocity duration = (self.length / self._velocity).simplified time_dist = get_constant_velocity(self._velocity, duration) elif self._time_dist is not None: time_dist = self._time_dist if time_dist is not None: t_0, s_0 = list(zip(*time_dist)) t_0 = np.array(t_0) s_0 = np.array(s_0) # Time must be monotonic and distances cannot be negative if len(set(t_0)) != len(t_0) or np.any(t_0 != np.sort(t_0)): raise ValueError("Time must be strictly monotonically rising.") if np.any(t_0 < 0): raise ValueError("Time cannot be negative.") if np.any(s_0 < 0): raise ValueError("Distance cannot be negative.") t_units = time_dist[0][0].units d_units = time_dist[0][1].units t_0 = Quantity(t_0 * t_units).simplified.magnitude s_0 = Quantity(s_0 * d_units).simplified.magnitude self._times, self._distances = interpolate_1d( t_0, s_0, len(self.parameter)) self._time_tck = interp.splrep(self._times, self._distances)
def set_uncertainty(self, uncertainty): if not isinstance(uncertainty, Quantity): uncertainty = Quantity( uncertainty, self._dimensionality, copy=False) try: assert self.shape == uncertainty.shape except AssertionError: raise ValueError('data and uncertainty must have identical shape') if uncertainty._dimensionality != self._dimensionality: uncertainty = uncertainty.rescale(self._dimensionality) self._uncertainty = uncertainty
def __init__(self, sym=None, sNum=None, unit=None): '''初始化一个LSym符号 【参数说明】 1.sym(可选,str):符号。sym为None时,将不会生成代数表达式。默认sym=None。 2.sNum(可选):符号对应的数值。默认sNum=None。sNum可以是以下数据类型: (1)Num:直接给出符号对应的Num数值。 (2)str:通过给出数值的字符串表达式,得到符号对应的Num数值。 3.unit(可选,str):当unit为None时,会选择Num的unit作为LSym的unit,否则没有单位。默认unit=None。 注意:sym和sNum必须至少有一个不为None,否则LSym的符号运算将失去意义。 【应用举例】 >>> m = LSym('m') #有符号,无数值和单位 >>> t = LSym('t', '13.35') #有符号和数值,无单位 >>> x = LSym('x', ('3.66', 'mm')) #有符号、数值和单位 >>> g = LSym('g', 9.7964) #有符号,纯数字 ''' if sym == None and sNum == None: return if sym != None: self.__symText = '{' + sym + '}' self.__genSym = (sym != None) self.__genCal = (sNum != None) if type(sNum) == Num: self.__sNum = sNum if unit != None: self.__sNum._Num__q = Quantity( 1., unit) if type(unit) == str else unit elif type(sNum) == str: self.__sNum = Num(sNum) if unit != None: self.__sNum._Num__q = Quantity( 1., unit) if type(unit) == str else unit elif sNum != None: raise expressionInvalidException('用于创建符号的参数无效') if type(self.__sNum) == Num: if self.__sNum._Num__sciDigit() != 0: self.__calPrior = 2 self.__calText = '{' + self.__sNum.dlatex() + '}' if self.__sNum != None: #如果是原始符号,则需要考虑是否因为负数或科学记数法而需要改变prior的情形 if self.__sNum < 0: #负数prior为0 self.__calPrior = 0 elif type( self.__sNum ) == Num and self.__sNum._Num__sciDigit() != 0: #科学记数法prior为2 self.__calPrior = 2 else: self.__calPrior = 6 else: self.__calPrior = 6
def __init__(self, sym, value, unit=None, showValue=True): '''初始化一个Const常数 【参数说明】 1.sym(str):常数符号。 2.value(int或float):常数对应的数值。 【应用举例】 >>> k = Const('k', 8.973e-7) ''' if sym == None: return self.__symText = '{%s}' % sym self.__value = value if showValue: self.__calText = dec2Latex(value, noBracket=True) if value < 0: #负数calPrior为0 self.__calPrior = 0 elif '^' in self.__calText: #科学计数法calPrior为0 self.__calPrior = 2 else: self.__calText = self.__symText self.__c_decL = False self.__c_decR = False if unit != None: if type(unit) == str: self.__q = Quantity(1, unit) elif type(unit) == Quantity: self.__q = unit
def _cd(name): entry = physical_constants[name] if False: #entry['precision']: return UncertainQuantity(entry['value'], entry['units'], entry['precision']) else: return Quantity(entry['value'], entry['units'])
def __init__(self, halfWidth, distribution=1, unit=None, **param): '''初始化一个测量仪器 【参数说明】 1.halfWidth(str或Num):半宽度。可以选择以字符串或Num数值形式给出。 2.distribution(可选,int):分布类型,从以下列表中取值。默认distribution=Ins.rectangle。 ①Ins.norm:正态分布; ②Ins.rectangle:矩形分布; ③Ins.triangle:三角分布; ④Ins.arcsin:反正弦分布; ⑤Ins.twopoints:两点分布; ⑥Ins.trapezoid:梯形分布,此分布下需要通过附加参数beta给出β值。 3.unit(可选,str):测量结果的单位。默认unit=None。 ''' self.distribution = distribution if unit == None: self.q = 1 else: self.q = Quantity(1., unit) if type(unit) == str else unit if type(halfWidth) == str: self.a = Num(halfWidth, self.q) elif type(halfWidth) == Num: self.a = halfWidth if unit == None: self.q = halfWidth._Num__q else: halfWidth._Num__q = self.q self.halfWidth = halfWidth if len(param) > 0: self.beta = param['beta']
def resetUnit(self, unit=None): '''重设Num数值的单位 【参数说明】 unit(可选,str):重设后的单位。默认unit=None,即没有单位。''' if unit == None: self.__q = 1 else: self.__q = Quantity(1., unit) if type(unit) == str else unit
def __init__(self, sym, sNumItem, unit=None, subs=None): '''初始化一个LSymItem符号组 【参数说明】 1.sym(str):符号组的符号。 2.sNumItem:符号组对应的数值数组。sNumItem可以是以下数据类型: (1)NumItem:直接给出符号组对应的NumItem数组。 (2)str:对于还没有转换成Num的数值,将数值以空格隔开,表示成字符串表达式,以此生成符号组对应的NumItem数组。 (3)list<Num>:对于已经转换成Num的数值,将数值用list表示出,以此生成符号组对应的NumItem数组。 3.unit(可选,str):单位。当unit为None时,会选择list<Num>中第1个元素的unit,或者NumItem的unit作为LSymItem的unit,否则没有单位。默认unit=None。 4.subs(可选,str):符号组中每个符号的下标,以空格隔开。在LSymItem.sepSymCalc为False的前提下,当subs为None时,会按照0、1、2...给每个符号索引,1、2、3...给每个符号编号;给出subs时,按照subs中给出的编号给每个符号索引和编号。默认subs=None。''' if sym == None and sNumItem == None: return if unit != None: self.__q = Quantity(1., unit) if type(unit) == str else unit if type(sNumItem) == str: try: sNumItem = NumItem(sNumItem) except: raise expressionInvalidException('用于创建符号组的数组部分的参数无效') elif type(sNumItem) == list and type(sNumItem[0]) == Num: if unit == None: self.__q = sNumItem[0]._Num__q elif type(sNumItem) == NumItem: if unit == None: self.__q = sNumItem._NumItem__arr[0]._Num__q else: raise expressionInvalidException('用于创建符号组的参数无效') if unit != None: for ni in sNumItem: ni._Num__q = self.__q if LSymItem.sepSymCalc: #将代数表达式与数值表达式分离 if subs == None: #未给出下标时,lsyms为list self.__lsyms = [LSym(None, ni) for ni in sNumItem] else: #给出下标时,lsyms为dict subs = subs.split(' ') if len(sNumItem) != len(subs): raise itemNotSameLengthException( '给出subs时,sNumItem和subs必须为等长列表') self.__lsyms = {} for i in range(len(sNumItem)): self.__lsyms[subs[i]] = LSym(None, sNumItem[i]) self.__sepSym = LSym(sym, None) else: if subs == None: #未给出下标时,lsyms为list self.__lsyms = [LSym('{' + sym + '}', ni) for ni in sNumItem] for i in range(len(sNumItem)): self.__lsyms[i]._LSym__symText += '_{' + str(i + 1) + '}' else: #给出下标时,lsyms为dict subs = subs.split(' ') if len(sNumItem) != len(subs): raise itemNotSameLengthException( '给出subs时,sNumItem和subs必须为等长列表') self.__lsyms = {} for i in range(len(sNumItem)): self.__lsyms[subs[i]] = LSym('{%s}_{%s}' % (sym, subs[i]), sNumItem._NumItem__arr[i])
def resetUnit(self, unit=None): '''重设LSymItem符号组中各符号对应数值的单位 【参数说明】 unit(可选,str):重设后的单位。默认unit=None,即没有单位。''' if self.__sNum != None: if unit == None: self.__q = 1 else: self.__q = Quantity(1., unit) if type(unit) == str else unit self.__qUpdate()
def __new__(cls, data, units='', uncertainty=None, dtype='d', copy=True): ret = Quantity.__new__(cls, data, units, dtype, copy) ret._uncertainty._dimensionality = ret._dimensionality if uncertainty is not None: ret.uncertainty = uncertainty elif isinstance(data, UncertainQuantity): if copy or self._dimensionality != uncertainty._dimensionality: uncertainty = data.uncertainty.rescale(ret.units) ret.uncertainty = uncertainty return ret
def format_data(self, observation): for key, val in list(observation.items()): try: assert type(observation[key]) is Quantity except Exception as e: quantity_parts = val.split(" ") number = float(quantity_parts[0]) units = " ".join(quantity_parts[1:]) observation[key] = Quantity(number, units) return observation
def get_rescaled_transform_matrix(self, units, coeff=1): """The last column of the transformation matrix holds displacement information has SI units, convert those to the *units* specified, apply coefficient *coeff* and return a copy of the matrix. """ trans_mat = np.copy(self.transform_matrix) for i in range(3): trans_mat[i, 3] = coeff * Quantity( trans_mat[i, 3] * q.m).rescale(units) return trans_mat
def resetUnit(self, unit=None): '''重设测量(含测量值和不确定度)的单位 【参数说明】 unit(可选,str):重设后的单位。默认unit=None,即没有单位。''' assert type(self) == Measure, '单位重设仅供Measure使用,不可用于BaseMeasure' if unit == None: q = 1 else: q = Quantity(1., unit) if type(unit) == str else unit self.value()._Num__q = q self.__q_rep = q
def get_flux(self, photon_energy, vertical_angle, pixel_size): """Get the photon flux coming from the source consisting of photons with *photon_energy* and get it at the vertical observation angle *vertical_angle*. """ gama = Quantity(self.electron_energy / (qe.electron_mass * q.c**2)).simplified gama_psi = gama * vertical_angle.rescale(q.rad) norm_energy = photon_energy.rescale( self.critical_energy.units) / self.critical_energy xi = Quantity(0.5 * norm_energy.magnitude * (1.0 + gama_psi**2)**(3.0 / 2)).magnitude angle_step = np.arctan(pixel_size.simplified / self.sample_distance.simplified) # 1e-3 for 0.1 % BW return Quantity(BendingMagnet._SR_CONST * gama**2 * self.el_current / q.elementary_charge * norm_energy**2 * (1.0 + gama_psi**2)**2 * (special.kv(2.0 / 3, xi)**2 + gama_psi**2 / (1.0 + gama_psi**2) * special.kv(1.0 / 3, xi)**2) * angle_step.rescale(q.rad)**2 * 1e-3).simplified
def __init__(self, numStr, unit=None): '''初始化一个Num数值 【参数说明】 1.numStr(str):要生成数值的字符串表达式,可以是一般计数法或科学记数法。注意要以字符串的形式给出,而不是直接给出int和float。 2.unit(可选,str):单位。默认unit=None,即没有单位。 【应用举例】 >>> t = Num('1.62') >>> t = Num('1.62', 's') >>> x = Num('1.32e-8') 【错误案例】 >>> t = Num(float('1.62')) #不能以float或int形式给出数值 >>> t = Num('1.62s') #单位的给出方式不对''' if numStr == None: return if type(numStr) != str: raise expressionInvalidException('用于创建数值的参数无效,数值只能以字符串形式给出') sci_exp = 0 #默认不使用科学记数法 self.__value = float(numStr) for E in ['e', 'E']: if numStr.__contains__(E): strArr = numStr.split(E) sci_exp = int(strArr[1]) #获得指数 numStr = strArr[0] #只保留numStr的指数前部分 break strArr = numStr.split('.') #以小数点为界分割数值 self.__d_front = getDigitFront(abs(float(strArr[0]))) if len(strArr) == 1: self.__d_behind = 0 #对于整数,有效数字位数即为小数点前位数 self.__d_valid = self.__d_front else: self.__d_behind = len(strArr[1]) self.__d_valid = self.__d_front + self.__d_behind #考虑小数点后无效0位数(排除诸如0.0000的情况) if self.__d_front == 0 and float(strArr[1]) != 0: for i in range(len(strArr[1])): if strArr[1][i] != '0': break self.__d_valid -= 1 if sci_exp != 0: #对于科学记数法,进行后续处理 self.__d_front += sci_exp if self.__d_front < 0: self.__d_front = 0 self.__d_behind -= sci_exp if self.__d_behind < 0: self.__d_behind = 0 if unit != None: #给出单位时,添加单位 self.__q = Quantity(1., unit) if type(unit) == str else unit
def extend_downwards(self, raw_signal: AnalogSignal, el_stimuli: Iterable[ElectricalStimulusWrapper], num_sweeps: int = 1, max_shift: Quantity = 0.003 * second, \ max_slope: Quantity = 0.003 * second, radius: int = 2, window_size: Quantity = 1 * ms, slope_penalty_term: str = 'cos', verbose = False): try: for i in tqdm(range(num_sweeps)): # Get the last R (radius) latencies to fit a line sweep_idcs = self.sweep_idcs latencies = self.latencies # fit a line to the existing sweep indices (depending on the chosen radius) and latencies to get estimates for the line parameters if len(self._latencies) > 1: slope, latency_intercept = np.polyfit(x = sweep_idcs[min(-len(self._latencies), -radius - 1) : ], \ y = latencies [min(-len(self._latencies), -radius - 1) : ], deg = 1) elif len(self._latencies) == 1: slope = 0 latency_intercept = latencies[0] else: raise RuntimeError("Cannot extend an empty track!") # using these parameters, predict the latency in the very next sweep next_sweep_idx = max(sweep_idcs) + 1 pred_latency = Quantity( slope * next_sweep_idx + latency_intercept, "s") if verbose == True: print(f"""Next predicted latency: {pred_latency}""") # search for the maximum TC in a certain environment around the predicted latency max_tc_latency, tc = search_for_max_tc(raw_signal = raw_signal, el_stimuli = el_stimuli, sweep_idx = next_sweep_idx, latency = pred_latency, max_shift = max_shift, max_slope = max_slope, \ slope_penalty_term = slope_penalty_term, established_slope = slope, radius = radius, window_size = window_size) self.insert_latency(sweep_idx=next_sweep_idx, latency=max_tc_latency) if verbose == True: print("Added AP to track: sweep " + str(next_sweep_idx) + " , latency " + str(max_tc_latency)) except Exception as err: print(err) print(traceback.format_exc())
class Converter(HasTraits): data = Array _data_quantity = Instance(Quantity) display_quantity = Instance(Quantity) def _data_units_default(self): raise NotImplementedError def _display_units_default(self): raise NotImplementedError units_editor = Instance(EnumEditor) @on_trait_change('data, data_units') def update_data_quantity(self): self._data_quantity = Quantity(self.data, self.data_units_) @on_trait_change('_data_quantity, display_units') def update_display_quantity(self): self.display_quantity = self._data_quantity.rescale(self.display_units_) # @on_trait_change('display_quantity') # def print_display_quantity(self): # print self.display_quantity def traits_view(self): return View( Item('data_units', editor=self.units_editor, ), Item('display_units', editor=self.units_editor, ), )
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Wed Aug 15 10:25:06 2018 @author: xingrongtech Referenced and modified by `markup` module, `quantities` package written by bjodah and apdavison """ import re from quantities.quantity import Quantity superscripts = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'] rad = Quantity(1., 'rad') deg = Quantity(1., 'deg') def superscript(val): items = re.split(r'\*{2}([\d]+)(?!\.)', val) ret = [] while items: try: s = items.pop(0) e = items.pop(0) ret.append(s + ''.join(superscripts[int(i)] for i in e)) except IndexError: ret.append(s) return ''.join(ret) def format_units_unicode(q):
def update_data_quantity(self): self._data_quantity = Quantity(self.data, self.data_units_)
def __init__(self, nums, unit=None, mu=None, sym=None, muSym=r'\mu'): '''初始化一个NumItem数组 【参数说明】 1.nums:要初始化的数值,可以是str或list: (1)str:对于还没有转换成Num的数值,将数值以空格隔开,表示成字符串表达式。 (2)list<Num>:对于已经转换成Num的数值,将数值用list表示出。 (3)list<LSym>:从由LSym符号形成的list中获取Num数值,生成NumItem。 (4)LSymItem:从由LSymItem符号组中获取Num数值,生成NumItem。 2.unit(可选,str):单位。当unit为None时,会选择list<Num>或list<LSym>中第1个元素的unit,或者LSymItem的unit作为NumItem的unit,否则没有单位。默认unit=None。 3.mu(可选,str):真值μ,用于误差分析。默认不给出,但进行误差分析时,必须给出μ。默认mu=None。 4.sym(可选,str):符号,一般情况下不需要给出,当需要展示计算过程时,最好给出。默认sym=None。 5.muSym(可选,str):真值μ对应的符号,默认muSym=r'\mu'。 【应用举例】 >>> t = NumItem('1.62 1.66 1.58 1.71 1.69') >>> >>> p1, p2, p3 = Num('13.42'), Num('13.52'), Num('13.49') >>> p = NumItem([p1, p2, p3]) >>> >>> t = NumItem('1.62 1.66 58 1.71 1.69', mu='1.65') >>> w = NumItem('38.42 38.56 38.47 38.41 38.55') >>> t = NumItem('1.62 1.66 1.58 1.71 1.69', 's', sym='t') 【错误案例】 >>> t = NumItem(1.62,1.66,1.58,1.71,1.69) #不能直接用float或int初始化数组 >>> t = NumItem([1.62,1.66,1.58,1.71,1.69]) #使用list初始化数组时,数值必须是Num >>> t = NumItem('1.62,1.66,1.58,1.71,1.69') #数值之间应该用空格,而不是逗号或其他符号隔开 >>> >>> p1, p2, p3 = Num('13.42'), Num('13.52'), Num('13.49') >>> p = NumItem(p1, p2, p3) #使用list初始化数组时,应将Num用中括号括住,表示是一个list ''' if nums == None: return if unit != None: self.__q = Quantity(1., unit) if type(unit) == str else unit if type(nums) == str: strArr = nums.split(' ') self.__arr = [Num(s) for s in strArr] if unit != None: for ri in self.__arr: ri._Num__q = self.__q elif type(nums) == list: if len(nums) == 0: self.__arr = [] elif type(nums[0]) == Num: self.__arr = nums elif str(type(nums[0])) == "<class 'analyticlab.lsym.LSym'>": self.__arr = [ni.num() for ni in nums] if unit == None: self.__q = self.__arr[0]._Num__q else: raise expressionInvalidException('用于创建数组的参数无效') if unit == None and len(self.__arr) > 0: self.__q = self.__arr[0]._Num__q else: for ri in self.__arr: ri._Num__q = self.__q elif str(type(nums)) == "<class 'analyticlab.lsymitem.LSymItem'>": if type(nums._LSymItem__lsyms) == list: lsymList = nums._LSymItem__lsyms else: lsymList = list(nums._LSymItem__lsyms.values()) self.__arr = [li.num() for li in lsymList] if unit == None: self.__q = self.__arr[0]._Num__q else: for ri in self.__arr: ri._Num__q = self.__q else: raise expressionInvalidException('用于创建数组的参数无效') if mu != None: if type(mu) == str: self.__mu = Num(mu, self.__q) elif type(mu) == Num: if mu._Num__q != self.__q: self.__mu = mu self.__mu._Num__q = self.__q else: self.__mu = mu else: raise expressionInvalidException('真值参数无效,真值只能以数值或字符串形式给出') self.__muSym = muSym if len(self.__arr) > 0: self.__findGeneralValid() if sym == None: self.__sym = '{x_{%d}}' % id(self) else: self.__sym = '{%s}' % sym