Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 07/04/2021 in all areas

  1. I believe the unbounded error is because the original code creates conditions for >=0 and <0 with no maximum duration. You can change $gte and $lte to have max durations and this may fix the issue. $gte = ($delta >= 0).setMaximumDuration(7d) $lt = ($delta < 0).setMaximumDuration(7d) In your example, the reversal count will not count 3, it will count one. Let's transform your example as runningDelta() would and assume the previous value was also 5. 5 -> 5 -> 10 -> 15 -> 10 becomes 0 -> 5 -> 5 -> -5 Now let's identify the gte and lt conditions. We would see an $gte {0 -> 5 -> 5->}, and an $lt at {-> -5}. Use our formula and the result would be 1 reversal. However this does bring up a potential issue. If the example had another 10 at the end, the delta samples would become 0 -> 5 -> 5 -> -5 -> 0 and that would create an additional $gte capsule at the very end, resulting in 2 reversals. You could fix this by change the $gte to only greater than instead of greater than or equal zero. Thanks, Andrew
    3 points
  2. TLDR Asset trees are great way to scale your analysis to N number of assets. Currently one needs working knowledge of SPy(Seeq-python) to build multi layered asset tree. With the attached jupyter notebook, Add-on tool can be created as shown here so that users can generate their own multi layered asset trees in their workbenches which can then be shared with colleagues. Pre-Requisite: Seeq Data Lab (powered by SPy module) Detail steps: 1. Get a CSV file (can be done in excel and saved as CSV format) that has hierarchy of your asset tree structure. The columns in screenshot below represent various hierarchical levels (columns A,B,C &D). You don't need exactly 4 columns, the solution supports any number of columns/hierarchical levels. 2. Include a column for "Process Value" (column F in screenshot below) which are your tag values and a column for "Asset Tree Name" which will appear in the tree and are the common attribute names among assets (column E in screenshot below). 3. Use the attached jupyter notebook and create Add-on tool so any user can access the tool from Tools pane in workbench. This is one time step and should be done by someone who has experience with Seeq Data Lab. The Tool name can be "Create Asset Tree from CSV File". Here is KB article on setting up new Add-on tool. https://seeq.atlassian.net/wiki/spaces/KB/pages/961675391/Add-on+Tool+Administration+and+Development 4. Use attached csv file and have your colleague who knows nothing about python, run the tool. UI is self explanatory as seen below. 5. Refresh the workbench from which user created the Asset Tree and watch the results appear like so: Example_SDL_Asset Tree (1).csv Create_asset_tree_with_dynamic_class_attributes.ipynb
    2 points
  3. Hey Andrew, Thank you very much for the response! I did end up computing the error in the way you described, breaking it down step by step. Your reversal count also works really well. I just have one question - I tried to replace the $period with a daily periodic condition I already made that starts at 6AM, but then the formula does not run and says it is unbound. Is there a reason why trying to replace $period in the formula with an already made periodic condition breaks it? Edit: In addition, would that formula not also count anytime the signal still goes up? Say it goes from 5 -> 10 -> 15 -> 10. in that sequence, there is only 1 reversal, but I think the formula above would count a total of 3. Thank you, Norman
    2 points
  4. If you'd like to make the number of samples consistent over time, I'd use the resample() function in a formula. $signal.resample(1min) If you pass resample() a period such as 1min, the result is a signal that will have a sample every 1 minute, regardless of the input sample frequency. To compute the error, I would create a new signal which is the difference between PV and SP. Then create a periodic condition for which you'd like to sum up this value and use the 'Signal from Condition' tool to sum the new signal over the given condition. To count the number of values in a period, use the 'Signal from Condition' tool to count the number of samples in your signal using whatever periodic condition you'd like as a bounding condition. For the number of reversals, I'd first use .runningDelta() to create a running delta signal of the signal you'd like to count the number of reversals for. I'd then create a condition using the 'Value Search' tool for anytime the delta signal is greater than or equal to zero, and another condition for anytime the delta signal is less than zero. Then, using the same method as above, create a periodic signal over which you'd like to calculate the number of reversals and use the 'Signal from Condition' tools to count the number of capsules within a given period. The total number of reversals should equal the number of >= 0 capsules plus number of <0 capsules minus 1. You could do this all in one formula if you'd like. $delta = $cv.runningDelta() //Conditions when delta >= 0 & < 0 $gte = $delta >= 0 $lt = $delta < 0 //Condition when to total the number of reversals $period = periods(10min) //Signal for total number of $gte/$lt conditions $gteCount = $gte.aggregate(count(), $period, startKey()) $ltCount = $lt.aggregate(count(), $period, startKey()) //Signal for total number of reversals $reversals = $gteCount + $ltCount - 1 //Output the reversals signal with Step interpolation $reversals.toStep() And here's some of the outputs. Andrew
    2 points
  5. Here is an example of Scatter plot push. @Asset.Display() def Display(self,metadata,analysis): #define name of worksheet worksheet = analysis.worksheet(self.definition['Name']+' Scatter') #define name of workstep workstep = worksheet.workstep('Trends') # make sure workstep is in Scatter Plot view workstep.view = 'Scatter Plot' # define the display items - need to have at least the 2 signals you want in scatterplot workstep.display_items = [{ 'Item': self.Temperature(metadata) },{ 'Item': self.Relative_Humidity(metadata) }] # define the 2 scatterplot signals workstep.scatter_plot_series = { 'X': {'ID': self.Temperature(metadata)}, 'Y': {'ID': self.Relative_Humidity(metadata)} } return workstep #Thanks @Kjell Raemdonck for the code snippet
    1 point
  6. Yasmin, This should be pretty straight forward using the integral function in formula Step 1 - Create a condition that marks the start and end time for when you want to calculate the integral. This could be done with a value search or manual condition Step 2 - Use the integral function to calculate the new signal $signal.integral($condition.removeLongerThan(5d)).convertUnits('kWh')
    1 point
  7. A generally interest question I want to document this morning Step 1 - Create a condition from the last sample till "Now" $caps = $MySignal.toCapsules() $timeSinceSample = past().subtract($caps) $timeSinceSample Step 2 - Create a Scorecard to Capture the duration of the condition created in Step 1 Make sure the Maximum Capsule Duration is longer than the longest gap you would expect in your signal. In this example it is 180 days
    1 point
  8. Hi Sivaji. You will be able to select a No Borders option for tables in Organizer Topics upon upgrade to R52 (currently available). After upgrade this configuration can be applied to each table so lines do not display in a PDF. Thank you for the feedback!
    1 point
  9. Awesome. Happy to hear!
    1 point
  10. Hello, I am looking to calculate some metrics on a loop - error, total control output travel, and number of reversals/changes. Error: Total Travel: The error needs to sum up the difference between two values over a time period and divide it by the total number of values used in that time period. The total travel would sum up all the movements of a number over the day (for eg if a value went from 10->15->20 total travel would be 10). Number of reversals/changes is as stated how many times a signal changes direction/value. I noticed that for some signals, the total count can be different depending on how often the value changes. Is there a simple way to pull the value of a number at a specific time stamp? And then to continue on, to do that over a capsule period ie calculating average over a 1 day timeframe? Thank you, Norman Edit 1: I think I solved the total travel. I used a combination of running delta and running sum bounded within a capsule abs($cmfo.runningDelta()).runningSum($d)
    1 point
  11. Capsules can have properties or information attached to the event. By default, all capsules contain information on time context such as the capsule’s start time, end time, and duration. However, one can assign additional capsule properties based on other signals’ values during the capsules. This guide will walk through some common formulas that can be used to assign capsule properties and work with those properties. Note: The formula syntax used in the following examples will all be based on the formula language for Seeq version 49. If you have questions about errors you may be receiving in the formulas on different versions, please check out the What’s New in Seeq Knowledge Base pages for formula changes or drop a comment below with the error message. How can I visualize capsule properties? Capsule Properties can be added to the Capsules Pane in the bottom right hand corner of Seeq Workbench with the black grid icon. Any capsule properties beyond start, end, duration, and similarity that are created with the formulas that follow or come in automatically through the datasource connection can be found by clicking the “Add Column” option and selecting the desired property in the modal to get a tabular view of the properties for each capsule as shown below. In Trend View, you can Capsule Property labels inside the capsules by selecting the property from the labels modal. Note that only Capsule Properties added to the Capsule Pane in the bottom right corner will be available in the labels modal. In Capsule Time, the signals can be colored by Capsule Properties by turning on the coloring to rainbow or gradient. The selection for which property is performing the coloring is done by sorting by the capsule property in the Capsule Pane in the bottom right corner. Therefore, if Batch ID is sorted by as selected below, the legend shown on the chart will show the Batch ID values. When working with Scorecard Metrics, you can use a Capsule Property as the header of a condition based scorecard by typing in the property name into the header modal: How do I create a capsule for every (unique) value of a signal? Let’s say you have a signal that you want to turn into individual capsules for each value or unique value of the signal. This is often used for string signals (e.g. batch IDs, operations, or phases) that may look like the signal below. There’s two main operators that can be used for this: $signal.toCapsules() The toCapsules operator will create a capsule for each data point of the signal. Therefore, if there was only 1 data point per value in the string signal below, it would create one capsule per value, but if the string value was recorded every minute regardless of whether it change values, it would create 1 minute capsules. In addition, the toCapsules operator also automatically records a Capsule Property called ‘Value’ that contains the value of the signal data point. $signal.toCondition('Property Name') The toCondition operator will create a capsule for each change in value of the signal. Therefore, in the case above where the value was recorded every minute regardless of value changes, it would only create one capsule for the entire time the value was equivalent. Similarly to the toCapsules operator, the toCondition operator also automatically records a Capsule Property called ‘Value’ that contains the value of the signal data point. However, with the toCondition operator, there’s an optional entry to store the property under a different name instead by specifying a property name in the parentheses in single quotes as shown in the example above. Note: Sometimes when working with string signals of phases or steps that are just numbered (e.g. Phase 1), if there is only one phase in the operation, you may end up wanting two Phase 1 capsules in a row (e.g. Operation 1 Phase 1 and Operation 2 Phase 1) whereas the toCondition method above will only create a single capsule. In this instance, it can be useful to concatenate the operation and phase signals together to find the unique combination of Operations and Phases. This can be done by using the following formula: ($operationsignal + ': ' + $phasesignal).toCondition('Property Name') How do I assign a capsule property? Option 1: Assigning a constant value to all capsules within a condition $condition.setProperty('Property Name', 'Property Value') Note that it is important to know whether you would like the property stored as a string or numeric value. If the desired property value is a string, make sure that the ‘Property Value’ is in single quotes to represent a string like the above formula. If the desired value is numeric, you should not use the single quotes. Option 2: Assigning a property based on another signal value during the capsule For these operations, you will have to use a transform operator to perform a particular set of operations per capsule to retrieve the desired property. For example, you may want the first value of a signal within a capsule or the average value of a signal during the capsule. Below are some examples of options you have and how you would set these values to capsule properties. The general format for this operation is listed below where we will define some different options to input for Property Scalar Value. $condition.transform($capsule -> $capsule.setProperty('Property Name', Property Scalar Value)) The following are options for what to input into Property Scalar Value in the formula above to obtain the desired property values: First value of signal within a capsule: $signal.toScalars($capsule).first() Last value of signal within a capsule: $signal.toScalars($capsule).last() Average value of signal within a capsule: $signal.average($capsule) Maximum value of signal within a capsule: $signal.maxValue($capsule) Minimum value of signal within a capsule: $signal.minValue($capsule) Standard deviation of signal within a capsule: $signal.stdDev($capsule) Totalization of a signal within a capsule: $signal.totalized($capsule) Count the capsules of a separate condition within a capsule: $DifferentCondition.count($capsule) Duration of capsules in seconds of a separate condition within a capsule: $DifferentCondition.totalduration($capsule) There are more statistical operations that can be done if desired, but hopefully this gives you an idea of the syntax. Please leave a comment if you struggle with a particular operator that you are trying to perform. Finally, there are often times when you want to perform one of the above operations, but only within a subset of each capsule. For example, maybe for each batch, you want to store the max temperature during just a particular phase of the batch. In order to do this, first make sure you have created a condition for that phase of the batch and then you can use the following to input into Property Scalar Value in the formula above: $signal.within($PhaseCondition).maxValue($capsule) In this case, the within function is cutting the signal to only be present during the $PhaseCondition so that only that section of the signal is present when finding the maximum value. Option 3: Assign a property based on a parent or child condition In batch processing, there is often a parent/child relationship of conditions in an S88 (or ISA-88) tree hierarchy where the batch is made up of smaller operations, which is then made up of smaller phases. Some events databases may only set properties on particular capsules within that hierarchy, but you may want to move the properties to higher or lower levels of that hierarchy. This formula will allow you to assign the desired property to the condition without the property: $ConditionWithoutProperty.transform($capsule -> $capsule.setProperty('Current Property Name', $ConditionWithProperty.toGroup($capsule).first().property('Desired Property Name'))) Note that this same formula works whether the condition with the property is the parent or child in this relationship. I also want to point out that if there are multiple capsules of the $ConditionWithProperty within any capsule of the $ConditionWithoutProperty, that this formula is set up to take the property from the first capsule within that time span. If you would like a different capsule to be taken, you can switch the first() operator in the formula above to last() or pick(Number) where last will take the property from the last capsule in the time span and pick is used to specify a particular capsule to take the property from (e.g. 2nd capsule or 2nd to last capsule). There’s another write-up about this use case here for more details and some visuals: How do I filter a condition by capsule properties? Conditions are filtered by capsule properties using the keep operator. Some examples of this are listed below: Option 1: Keep exact match to property $condition.keep('Property Name', isEqualTo('Property Value')) Note that it is important to know whether the property is stored as a string or numeric value. If the property value is a string, make sure that the ‘Property Value’ is in single quotes to represent a string like the above formula. If the value is numeric, you should not use the single quotes. Option 2: Keep regular expression string match $condition.keep('Property Name', isMatch('B*')) $condition.keep('Property Name', isNotMatch('B*')) You can specify to keep either matches or not matches to partial string signals. In the above formulas, I’m specifying to either keep all capsules where the capsule property starts with a B or in the second equation, the ones that do not start with a B. If you need additional information on regular expressions, please see our Knowledge Base article here: https://seeq.atlassian.net/wiki/spaces/KB/pages/146637020/Regex+Searches Option 3: Other keep operators for numeric properties Using the same format of Option 1 above, you can replace the isEqualTo operator with any of the following operators for comparison functions on numeric properties: isGreaterThan isGreaterThanOrEqualTo isLessThan isLessThanOrEqualTo isBetween isNotBetween isNotEqualTo Option 4: Keep capsules where capsule property exists $condition.keep('Property Name', isValid()) In this case, any capsules that have a value for the property specified will be retained, but all capsules without a value for the specified property will be removed from the condition. How do I turn a capsule property into a signal? A capsule property can be turned into a signal by using the toSignal operator. The properties can be placed at either the start timestamp of the capsule (startKey) or the end timestamp of the capsule (endKey): $condition.toSignal('Property Name', startKey()) $condition.toSignal('Property Name', endKey()) This will create a discrete signal where the value is at the selected timestamp for each capsule in the condition. If you would like to turn the discrete signal into a continuous signal connecting the data points, you can do so by adding a toStep or toLinear operator at the end to either add step or linear interpolation to the signal. Inside the parentheses for the interpolation operators, you will need to add a maximum interpolation time that represent the maximum time distance between points that you would want to interpolate. For example, a desired linear interpolation of capsules may look like the following equation: $condition.toSignal('Property Name', startKey()).toLinear(40h) It should be noted that some properties that are numeric may be stored as string properties instead of numeric, particularly if the capsules are a direct connection to a datasource. In this case, a .toNumber() operator may need to be added after the toSignal, but before the interpolation operator. Finally, it is often useful to have the property across the entire duration of the capsule if there are no overlapping capsules (e.g. when looking at batches on a particular unit). This is done by turning the signal into a step signal and then filtering the data to only when it is within a capsule: $condition.toSignal('Property Name', startKey()).toStep(40h).within($condition) What capsule adjustment/combination formulas retain capsule properties? When adjusting or combining conditions, the rule of thumb is that operators that have a 1 to 1 relationship between input capsule and output capsule will retain capsule properties, but when there are multiple capsules that are required as the input to the formula operator, the capsule properties are not retained. For example, moving a capsule by 1 hour has knowledge of the input properties whereas merging 2 capsules together results in not knowing which capsule to keep the properties from. A full list of these operators and their stance on whether they retain or lose capsule properties during usage is below. Operators that retain properties Operators that lose properties afterEnd inverse afterStart merge beforeEnd fragment beforeStart intersect ends join starts union (if more than one capsule overlap) middles grow growEnd shrink move combineWith encloses inside subtract matchesWith touches union (when no capsules overlap) It is important to note that capsule properties are attached to the individual capsule. Therefore, using a combination formula like combinewith where multiple conditions are combined may result in empty values in your Capsule Pane table if each of the conditions being combined has different capsule properties. How do I rename capsule properties? Properties can be swapped to new names by using the renameProperty operator: $condition.renameProperty('Current Property Name', 'New Property Name') A complex example of using capsule properties: What if you had upstream and downstream processes where the Batch ID (or other property) could link the data between an upstream and downstream capsule that do not touch and are not in a specific order? In this case, you would want to be able to search a particular range of time for a matching property value and to transfer another property between the capsules. This can be explained with the following equation: $UpstreamCondition.move(0,7d) .transform($capsule ->{ $matchingDownstreamProperty = ($DownstreamCondition.toSignal('Downstream Property to Match Name') == $capsule.property('Upstream Property to Match Name')) $firstMatchKey = $matchingDownstreamProperty.togroup($capsule,CAPSULEBOUNDARY.INTERSECT).first().startkey() $capsule.setProperty('Desired Property Name',$DownstreamCondition.toSignal('Desired Downstream Property Name').tostep(40h).valueAt($firstMatchKey)) }) .move(0,-7d) Let's walk through what this is doing step by step. First, it's important to start with the condition that you want to add the property to, in this case the upstream condition. Then we move the condition by a certain amount to be able to find the matching capsule value. In this case, we are moving just the end of each capsule 7 days into the future to search for a matching property value and then at the end of the formula, we move the end of the capsule back 7 days to return the capsule to its original state. After moving the capsules, we start the transform. Inside the transform, we find the matching downstream property by turning the capsule property to match from the downstream condition into a signal and match it to the capsule property from the upstream capsule. We then find the key (timestamp) of the first match of the property. Again, similar to some other things, the first option could be swapped out with last or pick to grab a different matching capsule property. Finally, we set the property on the upstream condition to 'Desired Property Name' by turning the downstream capsule property that we want into a step signal and take the value where the first match was found.
    1 point
  12. In v51, the "Assigning a property based on another signal value during the capsule" became much easier: $condition.setProperty('Property Name', $signal, valueStat()) Where valueStat is one of the aggregation operations like average(), maxValue(), totalized(), etc. This form is also much faster.
    1 point
  13. Quick method to calculate the median of multiple related signals over a time period $allSignals = combinewith($p1fr.move(1ns), $p2fr.move(2ns), $p3fr.move(3ns), $p4fr.move(4ns)) $allSignals.aggregate(median(),hours(),durationkey()) The first part of the formula combines all the samples from your signals of interest into a new single signal which has all of the datapoints from the first four signals. One trick with the combinewith() function is that it can't combine samples that occur at the exact same timestamp. Since I am using data from a csv file for this example where the timestamps for all 4 signals are exactly the same I use the move() function to slightly offset each of the signals by a nanosecond so that they all combine smoothly. The final part of the formula is the aggregation where we can calculate the median value of our new combined signals which has all the sample form our prior 4 signals. In this example I am calculating an hourly median but this can be changed to daily() or a calculated condition that makes the most sense for your application.
    1 point
  14. Isaac, In your case you might be able to set the max interpolation to 1 second on your input signal. If that does not work, you can use a certain signal, such as Area A Temperature to create, a similar result to the past() operator. To create a similar condition to the past() condition you can use the following formula. $AreaATemp.isvalid() Once you have that you can use it the same way the past() function was used above. Teddy
    1 point
  15. Hi Shamus, If I understand correctly, is this used to calculate deltaT of the samples in a signal? Lets say we have a signal A. Will this formula give us the new signal B? t A B t1 a1 0 t2 a2 t2-t1 t3 a3 t3-t2 t4 a4 t4-t3 I tried on my end, but error shows like this.
    1 point
  16. There are a couple options you can take for this. The first is to completely exclude the incomplete day and the second is to exclude the data in the signal until the day is complete. Exclude the Incomplete Day This is relatively easy with the past() function in formula. This function is relatively new so older versions of Seeq may not have it. On your condition that you are aggregating over you can remove all capsules past now and any incomplete ones with the following formula. (Example using daily condition) $Daily.inside(past()) Metric created with a normal daily condition: Metric created with the clipped daily condition: Exclude the Data in the Signal Until the Day is Complete This requires you to make the same clipped condition above and then apply it directly to the signal to limit the data in the signal until the last complete day. $signal.within($ClippedCondition) Results with the Clipped Signal and the Normal Signal:
    1 point
  17. Seeq Data Lab allows users to programatically interact with data connected to Seeq through Python. With this, users can create numerous advanced visualizations. Some examples of these are Sankey diagrams, Waterfall plots, radar plots and 3D contour plots. These plots can then be pushed back into Seeq Organizer for other users to consume the visualizations. A common workflow that can stem from this process is the need to update the Python visualizations in an existing Organizer Topic with new ones as newer data become available. Here we'll look over the steps of how you can update an existing Organizer Topic with a new graphic. Step 1: Retrieve the Workbook HTML Behind every organizer topic is the HTML that controls what the reports display. We'll need to modify this HTML to add a new image will also retaining whatever pieces of Seeq content were already on the report. pulled_workbooks = spy.workbooks.pull(spy.workbooks.search({'Name':'Organizer Topic Name'})) org_topic = pulled_workbooks[0] # Note you may need to confirm that the first item in pulled_workbooks is the topic of interest ws_to_update = org_topic.worksheets[0] # Choose the index based on the worksheet intended to be updated ws_to_update.html # View the HTML behind the worksheet Step 2: Create the HTML for The Image The "add_image" function can be used to generate the HTML that will be inserted into the Organizer Topic HTML replace_html = ws_to_update.document.add_image(filename = "Image_To_Insert.png") replace_html Step 3: Replace HTML and Push Back to Seeq To find where in the Organizer Topic HTML to replace, we can use the re module. This will allow us to parse the HTML string to find our previously inserted image, which should begin with "<img src=". Note additional changes are required if multiple images are included in the report. import re before_html = re.findall("(.*)<img src=", ws_to_update.html)[0] # Capture everything before the image after_html = re.findall(".*<img src=.*?>(.*)", ws_to_update.html)[0] # Captures everything after the image full_html = before_html + replace_html + after_html # Combine the before and after with the html generated for the new picture ws_to_update.html = full_html # Reassign the html to the worksheet and push it back to Seeq spy.workbooks.push(pulled_workbooks)
    1 point
  18. Hi Yassine, it might be that there are invalid values in this timeframe. You can try to change your formula to $as32.validValues(). This will remove invalid values from the signal and interpolation should work again. If the gap is greater than the max interpolation setting you can use $as32.validValues().setMaxInterpolation(4weeks) which first removes invalid values and then changes the max interpolation of the signal. Regards, Thorsten
    1 point
  19. Hi Corey, Currently, condition lanes are tied to the order that the conditions are added to the trend. Therefore, to modify that order, remove all conditions from the display and add them back onto the display in the order you would like them to appear (from top to bottom).
    1 point
  20. Hi Teddy, is this option available now in the SEEQ (R51.0.4) without a DataLab? Otherwise can you also please add me to the feature request, so that I can get an update if it rolled out in the newer versions? Thanks.
    1 point
  21. Use Case: It is common in industry to seek to use the behavior of upstream process variables to predict what the behavior of a downstream variable might be minutes, hours or days from the present time. Solution: A traditional predictive modeling workflow can be applied to solve this problem. Identify an appropriate training data set Perform any necessary data cleansing Create a predictive model Evaluate the model fit Improve the model Operationalize the model What differentiates this use case from any other predictive modeling use case is a specific data cleansing step for adjusting signals to remove process lag. 1. Load Data Load your target signal and the relevant upstream signals into the display pane. In this example, the target signal is the product viscosity, measured in an analytical lab based off a sample from a downstream sample point. Three upstream signals: the reactor temperature, reactant conversion, and viscosity modifier flow to the reactor significantly influence the product viscosity measurement and will be used as inputs into the model signal. 2. Identify Training Data Set Identify an appropriate training data set for your regression model. This may involve a longer time window to include variability in product type or seasonality. In this example, we will pan out to 3 months to capture multiple cycles of different product types. With an appropriate training window identified, you can also limit your training data set to a subset of samples present during a particular condition. If this interests you, consult the "advanced options" section of the Prediction Tool KB article for more information. This method is particularly useful if you're wishing to create different models for different modes of operation. 3. Cleanse Signals -- Adjust for Process Lag We can time-shift our upstream signals using either a known constant delay, a known variable delay (like a calculated residence time signal), or an unknown delay of maximum correlation to the target signal. The first two of these options will utilize the .move() function in Formula (or .delay() in earlier versions of Seeq). The latter will utilize the .correlationOffset() function. In this example, we have a known lag of 1.5 hours between the reactor and the product sampling point. We will use the move function with an input scalar of 1.5h, as shown below. The time shift calculation should be applied across all relevant input signals. More information on the different options for time shifting signals using fixed, variable, or calculated offsets is available in this forum post: 4. Cleanse Signals -- Remove signal noise, outliers, abnormal operating data In this example, we apply an agileFilter to each of our time-shifted model input signals. Apply the same technique to each of the model inputs. Note that steps 3 & 4 could have been combined into a single formula. An example of this would be: $reactor_temp.move(1.5h).agileFilter(1min) For guidance on additional cleansing techniques, consult the Interactive Training. 5. Build the Predictive Model Use the Prediction tool panel to create a model of your target signal based on your cleansed, time-adjusted input signals. Ensure your model training window matches the date range that you identified in step 2. You can view the model parameters like coefficients, rSquared, and p-values using the "+ Prediction Model" option. 6. Evaluate the Model Fit Use Scatter Plot view and the model parameters to evaluate the goodness of fit of the model. Switch to a time range outside of your training data set to ensure your model is a good fit for data throughout time. 7. Improve Model (as needed) If the scatter plot indicates a non-linear relationship, test out additional model scales in the prediction tool panel. Consider eliminating variables with p-values higher than your significance level cutoff (frequently 0.05). Add additional variables if relevant. If distinct modes of operation introduce significant signal variability, consider creating a model for each operating mode and stitch the models together into a single model using the splice() function in Formula. 8. Deploy the Model The model should project out into the future by the amount of the process lag between the upstream and target signals.
    1 point
  22. Hello Tom, We do have script/plugin that will do this. However, it requires Seeq Data Lab right now and a fairly new version of Seeq. There is a feature request for this that I can link you to if you want. Regards, Teddy
    1 point
  23. Here is the syntax for a polynomial regression based condition. $condition.removeLongerThan(15h).transform($cap->{ $model=$signaltomodel.regressionModelOLS(group($cap), false, $Time, $Time^2) $cap.setProperty('Coeff1',$model.get('coefficient1')) .setProperty('Coeff2',$model.get('coefficient2')) .setProperty('Intercept',$model.get('intercept'))}) Below is a screenshot of it setup in the formula tool. The result
    1 point
  24. The following steps will create a prediction model for every capsule in a condition. Step 1. pick a condition with capsules that isolate the desired area of regression. Any condition with non-overlapping capsules will work as long as there are enough sample points within its duration. For this example, an increasing temperature condition will be used. However, periodic conditions and value search conditions will work as well. Step 2. Create a time counter for each capsule in the condition. This can be done with the new timesince() function in the formula tool. The timesince() function will have samples spaced depending on the selected period so it is important to select a period that has enough points to build a model with. See below for details on the timesince() formula setup. Step 3. In this step a condition with capsule properties that hold the regression constants will be made. This will be done in the formula tool with one formula. The concept behind the formula below is to split the condition from step one into individual capsules and use each of the capsules as the training window for a regression model. Once the regression model is done for one capsule the coefficients of the model are assigned as properties to the capsule used for the training window. The formula syntax for a linear model-based condition can be seen below. An example of a polynomial regression model can be found in the post below. $Condtition.removeLongerThan(24h).transform($cap-> { $model=$SignalToModel.validValues().regressionModelOLS( group($cap),false,$Time) $cap.setProperty('Slope',$model.get('coefficient1')) .setProperty('Intercept',$model.get('intercept'))}) Below is a screenshot of how the formula looks in Seeq. Note: The regression constants can be added to the capsule pane by clicking on the black stats button and selecting add column. Below is a screen shot of the results. Step 4. Once a condition with the regression coefficients has been created the information will need to be extracted to a signal form. The following formula syntax will extract the information. This will need to be repeated for every constant from your regression model. e.g.(So for a linear model this must be done for both the slope and for the intercept.) The formula syntax for extracting the regression coefficients can be seen below. $signal=$Condition.transformToSamples( $cap -> sample($cap.getmiddle(), $cap.getProperty('Intercept').toNumber()), 1min) $signal.aggregate(average(),$Condition,durationKey()) Below is a screenshot of the formula in Seeq. Below is a screenshot of the display window of how the signals should look. Step 5. Use the formula tool to plot the equation. See screenshot below for details. Final Result
    1 point
This leaderboard is set to Los Angeles/GMT-07:00
×
×
  • Create New...