@@ -35,8 +35,8 @@ def read_chunk_from_file(file_path, start, end, typ, buf_loc) -> np.ndarray:
3535 f .seek (buf_loc )
3636 # read the chunk of data from the file
3737 chunk = np .fromfile (f , dtype = typ , offset = start * typ .itemsize , count = end - start )
38-
39- return chunk
38+
39+ return chunk
4040
4141def toTimestamp (serialFormat ):
4242 return (serialFormat - 25569 ) * 86400.0
@@ -45,7 +45,7 @@ def toDatetime(timestamp):
4545 return datetime .utcfromtimestamp (timestamp )
4646
4747def get_clr (n , name = 'hsv' ):
48- '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
48+ '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
4949 RGB color; the keyword argument name must be a standard mpl colormap name.'''
5050 return plt .cm .get_cmap (name , n )
5151
@@ -57,35 +57,35 @@ class Channel:
5757 APReader uses the Channel-Lengths to connect Channels together.
5858 Say there are two Channels with Length 100, then one of those will have "Time" in its name.
5959 The other one then gets a reference to the "time" one.
60-
61- If there is more than one channel having the same amount of entries, every channel will
60+
61+ If there is more than one channel having the same amount of entries, every channel will
6262 get the same reference to the time channel.
63- """
63+ """
6464 # data: List[float]
6565 verbose : bool
6666 # Defines if data should be filtered.
6767 filterData : bool
68-
68+
6969 # Specifies if channel entries should be loaded in parallel.
7070 parallelLoad : bool
7171 # Amount of parallel processes that can be used to load data.
7272 parallelProcs : int
7373 # The parallel pool which holds parallel processes.
7474 parallelPool : mpPool
75-
75+
7676 def __init__ (self , reader : BinaryReader , fileName = 'unknown' , filepath = '' , \
7777 verbose = False , parallelPool = None ):
7878 """
7979 Creates the Channel.
8080
8181 Uses a reader (BinaryReader) to read the data from the file accessed by "APReader.__init__".
8282 """
83-
83+
8484 # parallel stuff
8585 self .parallelLoad = parallelPool is not None
8686 self .parallelPool = parallelPool
8787 self .parallelProcs = len (mp .active_children ())
88-
88+
8989 # defines, if the apreader should output verbose debug messages
9090 self .verbose = verbose
9191
@@ -108,11 +108,11 @@ def __init__(self, reader: BinaryReader, fileName='unknown', filepath='', \
108108 tName = self .Name .replace (' ' ,"_" ) # temporary name
109109 self .fullName = f"{ fileName } .{ tName } "
110110 self .filePath = filepath
111- # retrieve unit of channel
112-
111+ # retrieve unit of channel
112+
113113 self .unit = reader .read_string (reader .read_int16 ())
114-
115- # get comment of channel
114+
115+ # get comment of channel
116116 self .comment = reader .read_string (reader .read_int16 ())
117117
118118 # 0: numeric, 1: string, 2: binary object
@@ -125,7 +125,7 @@ def __init__(self, reader: BinaryReader, fileName='unknown', filepath='', \
125125 # extended channel header
126126 self .nHdrBytes = reader .read_int32 ()
127127 self .extHeader = self .readExtHeader (reader )
128-
128+
129129 precDict = {0 :8 , 1 :4 , 2 :2 } # key: Attribute "Exportformat", value: precision in bytes
130130 try :
131131 self .precision = precDict [self .extHeader ['ExportFormat' ]]
@@ -161,13 +161,13 @@ def readExtHeader(self, rdr: BinaryReader):
161161 values are stored at byte addresses which are integer multiples of their
162162 width in bytes (i.e. doubles are stored on addresses divisible by eight,
163163 floats on addresses divisible by four etc.)
164-
165- See the link below for more info:
164+
165+ See the link below for more info:
166166 https://stackoverflow.com/questions/4306186/structure-padding-and-packing
167-
167+
168168 For this reason, I've added three bytes of padding before the attribute
169169 'NominalRange', which is a float.
170-
170+
171171 """
172172 pos0 = rdr .tell () # In general not a multiple of eight, which is unexpected!
173173
@@ -176,41 +176,41 @@ def readExtHeader(self, rdr: BinaryReader):
176176 exthdr ['dt' ] = rdr .read_double () # 16
177177 exthdr ['SensorType' ] = rdr .read_int16 () # 18
178178 exthdr ['SupplyVoltage' ] = rdr .read_int16 () # 20
179-
179+
180180 exthdr ['FiltChar' ] = rdr .read_int16 () # 22
181181 exthdr ['FiltFreq' ] = rdr .read_int16 () # 24
182182 exthdr ['TareVal' ] = rdr .read_float () # 28
183- exthdr ['ZeroVal' ] = rdr .read_float () # 32
183+ exthdr ['ZeroVal' ] = rdr .read_float () # 32
184184 exthdr ['MeasRange' ] = rdr .read_float () # 36
185185 exthdr ['InChar' ] = [rdr .read_float () for i in range (4 )] # 40, 44, 48, 52
186-
186+
187187 exthdr ['SerNo' ] = rdr .read_string (32 ) # 84
188188 exthdr ['PhysUnit' ] = rdr .read_string (8 ) # 92
189189 exthdr ['NativeUnit' ] = rdr .read_string (8 ) # 100
190-
190+
191191 exthdr ['Slot' ] = rdr .read_int16 () # 102
192192 exthdr ['SubSlot' ] = rdr .read_int16 () # 104
193193 exthdr ['AmpType' ] = rdr .read_int16 () # 106
194194 exthdr ['APType' ] = rdr .read_int16 () # 108
195195 exthdr ['kFactor' ] = rdr .read_float () # 112
196196 exthdr ['bFactor' ] = rdr .read_float () # 116
197-
197+
198198 exthdr ['MeasSig' ] = rdr .read_int16 () # 118
199199 exthdr ['AmpInput' ] = rdr .read_int16 () # 120
200200 exthdr ['HPFilt' ] = rdr .read_int16 () # 122
201201 exthdr ['OLImportInfo' ] = rdr .read_byte () # 123
202202 exthdr ['ScaleType' ] = rdr .read_byte () # 124
203- exthdr ['SoftwareTareVal' ] = rdr .read_float () # 128
203+ exthdr ['SoftwareTareVal' ] = rdr .read_float () # 128
204204 exthdr ['WriteProtected' ] = rdr .read_byte () # 129
205205 rdr .read_string (3 ) # 132
206-
207- exthdr ['NominalRange' ] = rdr .read_float () # 136
206+
207+ exthdr ['NominalRange' ] = rdr .read_float () # 136
208208 exthdr ['CLCFactor' ] = rdr .read_float () # 140
209209 exthdr ['ExportFormat' ] = rdr .read_byte () # 141
210210 rdr .read_string (7 ) # 148
211- # reserve = rdr.read_string(10)
211+ # reserve = rdr.read_string(10)
212212 posN = rdr .tell ()
213-
213+
214214 if (posN - pos0 ) != self .nHdrBytes :
215215 print ("""
216216 WARNING:
@@ -224,7 +224,7 @@ def readExtHeader(self, rdr: BinaryReader):
224224 """ .format (self .Name ))
225225 rdr .seek (pos0 + self .nHdrBytes )
226226 exthdr ['ExportFormat' ] = 0
227-
227+
228228 return exthdr
229229
230230 def readData (self ):
@@ -237,29 +237,29 @@ def readData(self):
237237 # if something was wrong previously, nothing will happen here
238238 if self .broken :
239239 return
240-
240+
241241 # The data is stored channelwise. We therefore only need to pass pointers to the first and last byte.
242242 if self .precision == 8 or self .precision == 4 :
243- datatype = np .dtype ('f{}' .format (self .precision ))
243+ datatype = np .dtype ('f{}' .format (self .precision ))
244244 # parallel loading will split up the incoming bin array
245245 if self .parallelLoad :
246246 self .data = self .read_data_parallel (datatype )
247-
247+
248248 # default loading will load all entries at once
249249 else :
250250 self .data = np .fromfile (self .reader .buf , dtype = datatype , count = self .length )
251-
251+
252252 elif self .precision == 2 :
253253 MinValue = self .reader .read_double ()
254254 MaxValue = self .reader .read_double ()
255255 sf = (MaxValue - MinValue )/ 32767 # scale factor
256256 self .data = np .fromfile (self .reader .buf , dtype = np .dtype ('u2' ), count = self .length )* sf + MinValue
257-
257+
258258 def __str__ (self ):
259259 """
260260 Default conversion to string.
261261 """
262- return f'Channel "{ self .Name } " ({ self .length } Entries)'
262+ return f'Channel "{ self .Name } " ({ self .length } Entries)'
263263
264264 def __getitem__ (self , key ) -> float :
265265 """Return the item at index key.
@@ -271,8 +271,8 @@ def __getitem__(self, key) -> float:
271271 double: self.data[key]
272272 """
273273 return self .data [key ]
274-
275- def plot (self , governed = False , axes = None , clr = 'b' ):
274+
275+ def plot (self , governed = False , axes = None , clr = 'b' , ls = "-" ):
276276 """
277277 Plot the channel over its connected time-channel.
278278
@@ -288,31 +288,31 @@ def plot(self, governed = False, axes=None, clr='b'):
288288
289289 if self .Time is None :
290290 print ("\t [ APREAD/PLOT ] Channel does not have time data. Not plotting." )
291- return
291+ return
292292
293293 plotbase = axes if axes is not None else plt
294-
295-
294+
295+
296296 if self .verbose :
297297 print (f'\t [ APREAD/PLOT ] Plotting { self .Name } ' )
298-
298+
299299 if not governed :
300300 plt .figure (self .Name )
301301 plt .xlabel ('Time [s]' )
302302 plt .ylabel (self .unit )
303303
304- line = plotbase .plot (self .Time .data , self .data , color = clr , label = self .Name )
305-
306-
304+ line = plotbase .plot (self .Time .data , self .data , color = clr , label = self .Name , linestyle = ls )
305+
306+
307307 if not governed :
308308 plt .title (self .Name )
309309 plt .draw ()
310- plt .legend ()
310+ plt .legend ()
311311 plt .show ()
312-
312+
313313 return line
314-
315-
314+
315+
316316
317317 def read_data_parallel (self , dtype ):
318318 """Reads in the underlying binary data using multiple parallel tasks.
@@ -324,8 +324,8 @@ def read_data_parallel(self, dtype):
324324 ndarray: Array of the binary data.
325325 """
326326 # chunk the total length of this channel
327- chunk_size = self .length // self .parallelProcs
328-
327+ chunk_size = self .length // self .parallelProcs
328+
329329 # current location of the buffered binary reader
330330 cur_loc = self .reader .tell ()
331331
@@ -338,12 +338,12 @@ def read_data_parallel(self, dtype):
338338 r .wait ()
339339 if not r .successful ():
340340 print ('Error in loading task!' )
341-
341+
342342 # concatenate the data structure
343343 data = np .empty (self .length , dtype )
344344 for result , (start , end ) in zip (results , chunks ):
345345 data [start :end ] = result .get ()
346-
346+
347347 # push the underlying original reader to after the channel items
348348 self .reader .seek (cur_loc + self .length * dtype .itemsize )
349349 return data
@@ -356,7 +356,7 @@ class Group:
356356 Helps calling plot functions..
357357 """
358358 # all (unsorted) channels in this group
359- Channels : List [Channel ]
359+ Channels : List [Channel ]
360360 """List of all channels"""
361361 # Name of the time channel of this group
362362 Name : str
@@ -384,7 +384,7 @@ def __init__(self, channels: List[Channel], fileName='unknown', verbose=False):
384384 """Create group of channels.
385385
386386 Args:
387- channels (list[Channel]): The channels this group is based on.
387+ channels (list[Channel]): The channels this group is based on.
388388 """
389389 self .verbose = verbose
390390 # save all channels
@@ -440,18 +440,18 @@ def __getitem__(self, key):
440440 double: self.data[key]
441441 """
442442 return (self .ChannelX [key ], [chan [key ] for chan in self .ChannelsY ])
443-
444- def __str__ (self ):
443+
444+ def __str__ (self ):
445445 return f'Group "{ self .Name } " ({ len (self .ChannelsY )} Data-channels, { self .ChannelX .length } Entries)'
446-
446+
447447 def plotChannel (self , channelIndex ):
448448 """Plot a specific channel
449449
450450 Args:
451451 channelIndex (int): The index of the channel.
452452 """
453453 self .plotChannels (channelIndex , channelIndex )
454-
454+
455455 def plotChannels (self , start , end ):
456456 """Plot a range of channels
457457
@@ -460,51 +460,50 @@ def plotChannels(self, start, end):
460460 end (int): Ending index, supports -[index] to mark index from the end.
461461 """
462462 self .plot (range (start ,end ))
463-
463+
464464 def plot (self , channelIndices = None , sameAxis = False ):
465465 """
466466 Plots this group of channels.
467-
467+
468468 Args:
469- channelIndices The starting index of data channels to be plotted.
470-
469+ channelIndices The starting index of data channels to be plotted.
470+
471471 Examples:
472472 grp.plot() will plot all channels
473473 grp.plot([0]) will plot the first data channel
474- grp.plot([0, 1, 3]) will plot the first, second and third data channel
474+ grp.plot([0, 1, 3]) will plot the first, second and third data channel
475475 """
476476 fig , ax1 = plt .subplots ()
477477 ax1 .set_xlabel (self .ChannelX .unit )
478-
479-
478+
479+
480480 if channelIndices is None :
481- channels = self .ChannelsY
481+ channels = self .ChannelsY
482482 else :
483483 channels = [self .ChannelsY [x ] for x in channelIndices ]
484-
484+
485485 # create colormap
486486 cmap = get_clr (len (channels )+ 1 )
487487 # save labels to retrieve them afterwards when building legend
488488 lns = []
489-
489+
490490 axis = ax1
491- for i ,channel in enumerate (channels ):
491+ for i ,channel in enumerate (channels ):
492492 if i > 0 and not sameAxis :
493493 axis = ax1 .twinx ()
494- axis .spines ['right' ].set_position (('outward' , 60 * (i - 1 )))
494+ axis .spines ['right' ].set_position (('outward' , 60 * (i - 1 )))
495495 axis .set_ylabel (channel .unit )
496496 axis .tick_params (axis = 'y' , colors = cmap (i ))
497- axis .get_yaxis ().label .set_color (cmap (i ))
498-
497+ axis .get_yaxis ().label .set_color (cmap (i ))
498+
499499 chanLine = channel .plot (governed = True , clr = cmap (i ))
500-
500+
501501 lns += chanLine
502502
503503 labs = [l .get_label () for l in lns ]
504504 ax1 .legend (lns , labs , loc = 0 )
505505 ax1 .grid ()
506-
506+
507507 plt .title (self .Name )
508508 plt .draw ()
509509 plt .show ()
510-
0 commit comments