#================================================================================================== # CREATE A GROUP CONTAINING A RECT, SHOWING HOW TO USE (INSTANCE) IT ROTATED AND TRANSLATED drawing.createGroup('r1') drawing.rect((0, 0), 10, 30, scene=False, groupId='r1') # add this rect to the group drawing.use('r1', (400, 100), rotation=10, fill='blue') drawing.use('r1', (400, 200), rotation=20, fill='blue') drawing.use('r1', (400, 300), rotation=30, fill='blue') drawing.use('r1', (400, 400), rotation=40, fill='blue') drawing.use('r1', (400, 500), rotation=50, fill='blue') #================================================================================================== drawing.save() #================================================================================================== """ The general format for the command line invocation of inkscape is: for PDF export: inkscape -f sourceFile.svg -A destinationFile.pdf or with the standard installation (without inkscape addd to the search path: /Applications/Inkscape.app/Content/Resources/bin/inkscape -f sourceFile.svg -A destinationFile.pdf for PNG export: inkscape -f sourceFile.svg -e destinationFile.png
rot = math.radians(trackRotation) z1 = lengthRatio*l z2 = z1 - l # draw the length line drawing.line( (x + z1*math.sin(rot), z + z1*math.cos(rot)), (x + z2*math.sin(rot), z + z2*math.cos(rot)), scene=True, stroke='red', stroke_width=2.0) # draw the width line x1 = w/2.0 x2 = -w/2.0 drawing.line( (x + x1*math.cos(rot), z - x1*math.sin(rot)), (x + x2*math.cos(rot), z - x2*math.sin(rot)), scene=True, stroke='blue', stroke_width=2.0) #drawing.federalCoordinates() # drawing.grid(0.5) drawing.save(toPDF=True) session.close() print 'Test Complete'
def _postAnalyze(self): h = Histogram( data=self._uncs, binCount=80, xLimits=(0, max(*self._uncs)), color='r', title='Distribution of Spatial (X, Z) Uncertainties', xLabel='Uncertainty Value (m)', yLabel='Frequency') p1 = h.save(self.getTempFilePath(extension='pdf')) h.isLog = True h.title += ' (log)' p2 = h.save(self.getTempFilePath(extension='pdf')) self.mergePdfs([p1, p2], self.getPath('Spatial-Uncertainty-Distribution.pdf')) average = NumericUtils.getMeanAndDeviation(self._uncs) self.logger.write('Average spatial uncertainty: %s' % average.label) #------------------------------------------------------------------------------------------- # FIND LARGE UNCERTAINTY TRACKS largeUncertaintyCount = 0 drawing = None sitemap = None # If track uncertainty is 2x average, add that track to the spreadsheet and map overlay for t in self._tracks: # if the tracksite has changed, save previous map and make a new one if sitemap != t.trackSeries.trackway.sitemap: # save the last site map drawing (if there was one) if drawing: drawing.save() # then start a new drawing for this new site map sitemap = t.trackSeries.trackway.sitemap fileName = sitemap.name + "_" + sitemap.level + '_uncertainty.svg' path = self.getPath(self.DRAWING_FOLDER_NAME, fileName, isFile=True) drawing = CadenceDrawing(path, sitemap) # create a group to be instanced for the spreadsheet values drawing.createGroup('rect1') # create a rectangle of 100x100 cm that is to be scaled by fractional meters drawing.rect((0, 0), 100, 100, scene=True, groupId='rect1') # create another group to be instanced for the mapped values. drawing.createGroup('rect2') # create a rectangle of 100x100 cm that is to be scaled by fractional meters drawing.rect((0, 0), 100, 100, scene=True, groupId='rect2') # and place a grid and the federal coordinates in the drawing file drawing.grid() drawing.federalCoordinates() # now examine the positional uncertainties for this track x = t.xValue z = t.zValue if x.uncertainty > 0.15 or z.uncertainty > 0.15: # s = '%s%s %s%s: %s %s'% ( # t.site, t.level, t.trackwayType, t.trackwayNumber, t.name, t.uid) # print('%s: (%s and %s)' % (s, x.uncertainty, z.uncertainty)) print('%s\t%s' % (t.uid, t.fingerprint)) if max(x.uncertainty, z.uncertainty) <= 2.0*average.uncertainty: # then just indicate that this track has low uncertainty self._drawLowUncertaintyMarker(drawing, t) # label this track with green drawing.text( t.name, (t.x - 20, t.z), scene=True, stroke='green', stroke_width='0.25', font_size='8px', font_family='Arial') continue # else, since the uncertainty is high, first write that track in the spreadsheet largeUncertaintyCount += 1 self._largeUncCsv.createRow( uid=t.uid, fingerprint=t.fingerprint, x=x.label, z=z.label) # if either the measured width or length is 0, mark with a yellow disk with red outline if t.widthMeasured == 0 or t.lengthMeasured == 0: drawing.circle( (t.x, t.z), 100*(t.widthUncertainty + t.lengthUncertainty)/2.0, scene=True, fill='yellow', stroke='red') drawing.text( t.name, (t.x - 20, t.z), scene=True, stroke='black', stroke_width='0.25', font_size='6px', font_family='Arial') continue self._drawHighUncertaintyMarker(drawing, t) # label this track with red drawing.text( t.name, (t.x - 20, t.z), scene=True, stroke='red', stroke_width='0.25', font_size='6px', font_family='Arial') # # # draw this track indicating it has high uncertainty # drawing.use( # 'rect1', # (t.x, t.z), # scene=True, # rotation=t.rotation, # opacity='0.5', # scale=t.widthMeasured, # scaleY=t.lengthMeasured, # fill='red', # stroke='red') # # # draw the map dimensions with an outline gray rectangle # drawing.use( # 'rect2', # (t.x, t.z), # scene=True, # rotation=t.rotation, # scale=t.width, # scaleY=t.length, # fill='none', # stroke='gray') # and close off with a final save of the drawing file if drawing: drawing.save() self.logger.write('%s Tracks with large spatial uncertainties found (%s%%)' % ( largeUncertaintyCount, NumericUtils.roundToOrder( 100.0*float(largeUncertaintyCount)/float(len(self._tracks)), -1) )) self._largeUncCsv.save() self._tracks = []
def _postAnalyze(self): h = Histogram( data=self._uncs, binCount=80, xLimits=(0, max(*self._uncs)), color="r", title="Distribution of Rotational Uncertainties", xLabel="Uncertainty Value (degrees)", yLabel="Frequency", ) p1 = h.save(self.getTempFilePath(extension="pdf")) h.isLog = True h.title += " (log)" p2 = h.save(self.getTempFilePath(extension="pdf")) self.mergePdfs([p1, p2], self.getPath("Rotational-Uncertainty-Distribution.pdf")) average = NumericUtils.getMeanAndDeviation(self._uncs) self.logger.write("Average rotational uncertainty: %s" % average.label) # ------------------------------------------------------------------------------------------- # FIND LARGE UNCERTAINTY TRACKS largeUncertaintyCount = 0 drawing = None sitemap = None # If track uncertainty is 2x average, add that track to the spreadsheet and map overlay for t in self._tracks: # if the tracksite has changed, save previous map and make a new one if sitemap != t.trackSeries.trackway.sitemap: # save the last site map drawing (if there was one) if drawing: drawing.save() # then start a new drawing for this new site map sitemap = t.trackSeries.trackway.sitemap fileName = "%s-%s-ROTATION_UNC.svg" % (sitemap.name, sitemap.level) path = self.getPath(self.DRAWING_FOLDER_NAME, fileName, isFile=True) drawing = CadenceDrawing(path, sitemap) # create a group to be instanced for the spreadsheet values drawing.createGroup("rect1") # create a rectangle of 100x100 cm that is to be scaled by fractional meters drawing.rect((0, 0), 100, 100, scene=True, groupId="rect1") # create another group to be instanced for the mapped values. drawing.createGroup("rect2") # create a rectangle of 100x100 cm that is to be scaled by fractional meters drawing.rect((0, 0), 100, 100, scene=True, groupId="rect2") # and place a grid and the federal coordinates in the drawing file drawing.grid() drawing.federalCoordinates() # now examine the positional uncertainties for this track rotation = t.rotationAngle.valueDegrees if rotation.uncertainty <= 2.0 * average.uncertainty: # then just indicate that this track has low uncertainty self._drawLowUncertaintyMarker(drawing, t) # label this track green # drawing.text( # t.name, # (t.x - 20, t.z), # scene=True, # stroke='green', # stroke_width='0.25', # font_size='8px', # font_family='Arial') continue # else, since the uncertainty is high, first write that track in the spreadsheet largeUncertaintyCount += 1 self._largeUncCsv.createRow(uid=t.uid, fingerprint=t.fingerprint, r=rotation.label) # if either the measured width or length is 0, mark with a yellow disk with red outline if t.rotationMeasured == 0: drawing.circle( (t.x, t.z), 100 * (t.widthUncertainty + t.lengthUncertainty) / 2.0, scene=True, fill="yellow", stroke="red", ) # drawing.text( # t.name, # (t.x - 20, t.z), # scene=True, # stroke='black', # stroke_width='0.25', # font_size='6px', # font_family='Arial') continue self._drawHighUncertaintyMarker(drawing, t) # label this track with red # drawing.text( # t.name, # (t.x - 20, t.z), # scene=True, # stroke='red', # stroke_width='0.25', # font_size='6px', # font_family='Arial') # and close off with a final save of the drawing file if drawing: drawing.save() self.logger.write( "%s Tracks with large rotational uncertainties found (%s%%)" % ( largeUncertaintyCount, NumericUtils.roundToOrder(100.0 * float(largeUncertaintyCount) / float(len(self._tracks)), -1), ) ) self._largeUncCsv.save() self._tracks = []
class RotationStage(AnalysisStage): """ Compares the rotational values from the field measurements, where they exist, with the measurements entered digitally determine the level of equivalence between the data sets. """ DRAWING_FOLDER_NAME = 'Rotation-Comparison-Maps' #___________________________________________________________________________ def __init__(self, key, owner, **kwargs): """Creates a new instance of RotationStage.""" super(RotationStage, self).__init__( key, owner, label='Rotation Comparison', **kwargs) self._paths = [] self._diffs = [] self._data = [] self._csv = None self._currentDrawing = None #=========================================================================== # G E T / S E T #___________________________________________________________________________ @property def deviations(self): return self.cache.get('trackDeviations') #=========================================================================== # P R O T E C T E D #___________________________________________________________________________ def _preAnalyze(self): """_preAnalyze doc...""" self.cache.set('trackDeviations', {}) self._diffs = [] self._data = [] self._currentDrawing = None csv = CsvWriter() csv.path = self.getPath('Rotation-Report.csv', isFile=True) csv.addFields( ('uid', 'UID'), ('fingerprint', 'Fingerprint'), ('delta', 'Discrepancy'), ('entered', 'Entered'), ('measured', 'Measured'), ('deviation', 'Deviation'), ('relative', 'Relative'), ('axis', 'Axis'), ('axisPairing', 'Axis Pairing')) self._csv = csv #___________________________________________________________________________ def _analyzeSitemap(self, sitemap): # start a drawing for the SVG and PDF files fileName = sitemap.name + "_" + sitemap.level + '_rotation.svg' path = self.getPath(self.DRAWING_FOLDER_NAME, fileName, isFile=True) self._currentDrawing = CadenceDrawing(path, sitemap) # create a group to be instanced for the map annotations self._currentDrawing.createGroup('pointer') self._currentDrawing.line( p1=(0, 0), p2=(0, -10), scene=False, groupId='pointer') # and place a grid and the federal coordinates in the drawing file self._currentDrawing.grid() self._currentDrawing.federalCoordinates() super(RotationStage, self)._analyzeSitemap(sitemap) if self._currentDrawing: self._currentDrawing.save() #___________________________________________________________________________ def _analyzeTrackSeries(self, series, trackway, sitemap): if len(series.tracks) < 2: # At least two tracks are required to make the comparison return for track in series.tracks: fieldAngle = Angle( degrees=track.rotationMeasured \ if track.rotationMeasured \ else 0.0) dataAngle = Angle(degrees=track.rotation) strideLine = StrideLine(track=track, series=series) if track.hidden or strideLine.pairTrack.hidden: continue try: strideLine.vector.normalize() except ZeroDivisionError: pair = strideLine.pairTrack self.logger.write([ '[ERROR]: Stride line was a zero length vector', 'TRACK: %s (%s, %s) [%s]' % ( track.fingerprint, NumericUtils.roundToSigFigs(track.x, 3), NumericUtils.roundToSigFigs(track.z, 3), track.uid), 'PAIRING: %s (%s, %s) [%s]' % ( pair.fingerprint, NumericUtils.roundToSigFigs(pair.x, 3), NumericUtils.roundToSigFigs(pair.z, 3), pair.uid) ]) continue axisAngle = strideLine.angle if track.left: fieldAngle.radians += axisAngle.radians else: fieldAngle.radians = axisAngle.radians - fieldAngle.radians # Adjust field angle into range [-180, 180] fieldAngle.constrainToRevolution() if fieldAngle.degrees > 180.0: fieldAngle.degrees -= 360.0 fieldAngleUnc = Angle(degrees=5.0) fieldAngleUnc.radians += \ 0.03/math.sqrt(1.0 - math.pow(strideLine.vector.x, 2)) fieldDeg = NumericUtils.toValueUncertainty( value=fieldAngle.degrees, uncertainty=fieldAngleUnc.degrees) # Adjust data angle into range [-180, 180] dataAngle.constrainToRevolution() if dataAngle.degrees > 180.0: dataAngle.degrees -= 360.0 dataAngleUnc = Angle(degrees=track.rotationUncertainty) dataDeg = NumericUtils.toValueUncertainty( value=dataAngle.degrees, uncertainty=dataAngleUnc.degrees) angle1 = Angle(degrees=dataDeg.value) angle2 = Angle(degrees=fieldDeg.value) # fill color for the disks to be added to the map are based on # diffDeg diffDeg = NumericUtils.toValueUncertainty( value=angle1.differenceBetween(angle2).degrees, uncertainty=min(90.0, math.sqrt( math.pow(dataAngleUnc.degrees, 2) + math.pow(fieldAngleUnc.degrees, 2))) ) self._diffs.append(diffDeg.value) deviation = diffDeg.value/diffDeg.uncertainty self.deviations[track.uid] = diffDeg # for now, convert +/- 180 headings to 0-360, using e and m # comment the next four lines toggle comments for entered and # measured below to revert e = dataDeg.value m = fieldDeg.value if e < 0.0: e += 360.0 if m < 0.0: m += 360.0 data = dict( uid=track.uid, fingerprint=track.fingerprint, entered=str(e), measured=str(m), delta=abs(diffDeg.value), deviation=deviation, relative=NumericUtils.roundToOrder(track.rotationMeasured, -2), axis=NumericUtils.roundToOrder(axisAngle.degrees, -2), axisPairing='NEXT' if strideLine.isNext else 'PREV') self._csv.createRow(**data) data['track'] = track self._data.append(data) # draw the stride line pointer for reference in green self._currentDrawing.use( 'pointer', (track.x, track.z), scene=True, rotation=axisAngle.degrees, stroke_width=1, scale=0.5, stroke='green') # indicate in blue the map-derived estimate of track rotation self._currentDrawing.use( 'pointer', (track.x, track.z), scene=True, rotation=dataDeg.value, stroke_width=1, stroke='blue') # add the measured (spreadsheet) estimate of rotation self._currentDrawing.use( 'pointer', (track.x, track.z), scene=True, rotation=fieldDeg.value, stroke_width=1, stroke='red') # place a translucent disk of radius proportional to the difference # in degrees radius = 100.0*diffDeg.value/180.0 self._currentDrawing.circle( (track.x, track.z), radius, scene=True, fill='red', stroke_width=0.5, stroke='red', fill_opacity='0.5') #_______________________________________________________________________________ def _postAnalyze(self): """_postAnalyze doc...""" self._csv.save() meanDiff = NumericUtils.getMeanAndDeviation(self._diffs) self.logger.write('Rotation %s' % meanDiff.label) self._paths.append(self._makePlot( label='Rotation Differences', data=self._diffs, histRange=[-180, 180])) self._paths.append(self._makePlot( label='Rotation Differences', data=self._diffs, histRange=[-180, 180], isLog=True)) circs = [] circsUnc = [] diffs = [] diffsUnc = [] entries = self.owner.getStage('lengthWidth').entries for entry in entries: track = entry['track'] if track.uid not in self.deviations: # Skip those tracks with no deviation value (solo tracks) continue diffDeg = self.deviations[track.uid] diffs.append(abs(diffDeg.value)) diffsUnc.append(diffDeg.uncertainty) # Compute the circularity of the track from its aspect ratio. If # the aspect is less than or equal to 1.0 use the aspect value # directly. However, if the value is greater than one, take the # reciprocal so that large and small aspect ratios can be compared # equally. aspect = entry['aspect'] if aspect.value > 1.0: a = 1.0/aspect.raw aspect = NumericUtils.toValueUncertainty(a, a*(aspect.rawUncertainty/aspect.raw)) circs.append(abs(aspect.value - 1.0)) circsUnc.append(aspect.uncertainty) pl = self.plot self.owner.createFigure('circular') pl.errorbar(x=circs, y=diffs, xerr=circsUnc, yerr=diffsUnc, fmt='.') pl.xlabel('Aspect Circularity') pl.ylabel('Rotation Deviation') pl.title('Rotation Deviation and Aspect Circularity') self._paths.append(self.owner.saveFigure('circular')) self.mergePdfs(self._paths) self._paths = [] #_______________________________________________________________________________ def _makePlot(self, label, data, isLog =False, histRange =None, color ='r', binCount = 72): """_makePlot doc...""" pl = self.plot self.owner.createFigure('histogram') pl.hist(data, binCount, range=histRange, log=isLog, facecolor=color, alpha=0.75) pl.title('%s Distribution%s' % (label, ' (log)' if isLog else '')) pl.xlabel('Difference (Degrees)') pl.ylabel('Frequency') pl.grid(True) axis = pl.gca() xlims = axis.get_xlim() pl.xlim((max(histRange[0], xlims[0]), min(histRange[1], xlims[1]))) path = self.getTempPath('%s.pdf' % StringUtils.getRandomString(16), isFile=True) self.owner.saveFigure('histogram', path) return path