Jump to content

Thorsten Vogt

Super Seeqer
  • Posts

    171
  • Joined

  • Last visited

  • Days Won

    53

Posts posted by Thorsten Vogt

  1. Hi,

    the error means that you are referencing a variable that is not defined in your variable list. You should change your variable "$signal1" in the formula to a variable you have in your variables list:

    image.thumb.png.8f12be8eab4def534b839cf9f63cb03b.png

    1 hour ago, Mohammed Ali Albatran said:

    getting signal by creating  signal of tow signal or signal of signal and condition

    Also be aware that you cannot use a signal and a condition together on combineWith(). You can combine either signals only or conditions only.

    Regards,

    Thorsten

     

    • Like 2
  2. Hello Kspring,

    I think you can do it that way:

    First create a condition based on the material signal by using toCondition(). The function creates a capsule everytime the value of the signal changes and stores the value in a defined property, in this case "Material":

    $signal.toCondition('Material')

    image.thumb.png.a08a3b2693994b19a50691e9a9724a20.png

    Next filter only for batches where the current material is produced using formula:

    //Create capsule of 1 day ending now
    $capsule = capsule(now()-1d, now())
    
    //Get current material by selecting last value inside capsule created above
    $currentMaterial = $gradeCode.toScalars($capsule).last()
    
    //Only keep batches for current Material
    $batches.removeLongerThan(1mo).keep($c -> $c.property('Material') == $currentMaterial)

    image.thumb.png.5393fba186b89e68883ad40f17f38b5a.png

    Then create the condition the time range you want to aggregate over. Here I am using a monthly condition:

    image.png.cfd8b4a941a0073bd2ec11234b74edd5.png

    Last step is calculating the value. The within() function is used to only keep that portions of the signal during the specified condition.

    $temperature.within($filteredBatches).aggregate(average(), $month, middleKey()).toDiscrete()

    image.thumb.png.08848abea1a21ecbab08939dde57dd9b.png

    Depending on your data you might need to do some adjustments on the timeranges I used in the formulas.

    Regards,

    Thorsten

     

  3. Hi Bellas,

    for creating the line at a certain y-value you can click on the "f(x)" button:

    image.png.62f1ab7abdedd571b9e235cf389c6f27.png

    Then click on "New Formula":

    image.png.1b5bedd17081f80aaf40b59dcd5c6288.png

    Enter the formula for the trend line. In this case I am going to display the line at y=60:

    image.png.1c831734730c8f796a5e9ac8316fe153.png

    After executing click the "f(x)" button again and select the just created signal from the dropdown:
    image.png.071c0bac0da8f5500446840cb05eca5c.png

    The scatter plot now shows the line:

    image.thumb.png.0e29d1271d8c24c0508fe0ed0bd7a57c.png

    Coloring an area above that line is not possible as far as I know. But you can color all points above that line. First you need to create a condition that identifies all points of the y-axis signal above the threshold:

    image.png.d9778c3b322f364bcbf9c7fe98cfe846.png

    Next, click on the "Color" button:

    image.png.38e9b0d6a7d365d0ee091c3c8f4f4997.png

    Select the condition from the conditions list:

    image.png.cb1d08f36a259c3d7e4b2446ae1eb8ee.png

    After closing the dialog all points identified by this condition are colored in the specific color of the condition:

    image.thumb.png.a690187c17cf2d879bfb6e5fdff570ce.png?

    Regards,

    Thorsten

     

     

  4. Hi Robin,

    you can create a batch condition by using replace() to extract the batchnumber and toCondition() for creating the capsules for each batch:
     

    $subbatches.replace('/(\\d{1,7})NR\\d{3}/', '$1').toCondition()

    image.thumb.png.13095176a332c08e84fa8792e9fe4935.png

    In the next step you can do the aggregation:
     

    $v1.aggregate(sum(), $batch.removeLongerThan(1wk), middleKey()) +
    $v2.aggregate(sum(), $batch.removeLongerThan(1wk), middleKey())

    image.thumb.png.b4a2b1d532c2658bdf749f0a922b3478.png

    Regards,

    Thorsten

    • Like 1
  5. Hi Javad, 

    I got a solution based on this starting point:
    image.thumb.png.ee1a29da7cfae9f228f6076fc0a76459.png

    The following formula compares the durations of the first capsules for conditions B,C and D bounded by each capsule of condition A and sets a property on capsules of condition A indicating if these should be shown. The keep function on the end only displays capsules where the property is set to true

    $a.transform($a_capsule -> {
     
     $b_capsule = $b.toGroup($a_capsule).first()
     $c_capsule = $c.toGroup($a_capsule).first()
     $d_capsule = $d.toGroup($a_capsule).first()
     $show_a = ($b_capsule.duration() > $d_capsule.duration() and  $d_capsule.duration() > $c_capsule.duration())
     $a_capsule.setProperty('show', $show_a)
    }, 40h).keep('show', isequalTo(true) )

    image.thumb.png.49d924c51018129f61b37eb7a34c04c9.png

    Changing capsule duration of B gets no capsule for result, which is expected:
    image.thumb.png.c21d5cdadc22fff64a66a182fd1b140f.png

     

    If you want to show another capsule for the last case, you can adjust the formula to generate another condition with the property show set to the inverse and select one of the conditions based on that value. Therefore you have to do the transform twice:

    $tempCondition1 = $a.transform($a_capsule -> {
     
     $b_capsule = $b.toGroup($a_capsule).first()
     $c_capsule = $c.toGroup($a_capsule).first()
     $d_capsule = $d.toGroup($a_capsule).first()
     $show_a = ($b_capsule.duration() > $d_capsule.duration() and  $d_capsule.duration() > $c_capsule.duration())
     $a_capsule.setProperty('show', $show_a)
    }, 40h)
    
    
    $tempCondition2 = $tempCondition1.transform($a_capsule -> {
     $d_capsule = $d.toGroup($a_capsule).first()
     $d_capsule.setProperty('show', not $a_capsule.property('show'))
    }, 40h)
    
    $tempCondition1.keep('show', isequalTo(true)) or $tempCondition2.keep('show', isequalTo(true))

    As a result capsules for condition D are shown:

    image.thumb.png.042f858ad3906a7640913309c8f33309.png

    Changing duration of capsule B to its original value show capsules of A as the result:

    image.thumb.png.ec7f3ce717aca80234f53a83f7d8e302.png

    Hope this helps.

    Regards,

    Thorsten

     

    • Like 1
  6. Hi Matthias,

    you can try this:

    First, calculate the duration of each capsule using "Signal from Condition" tool:
    image.thumb.png.9b00e88740550704612a46c1cd1bd1ca.png

    Then you can use timesince() to calculate the percentage value over the duration and also splice() to insert it into the base signal of 0% everytime the condition is met:

    0%.splice(timesince($condition.removeLongerThan(40h), 1min)/$duration, $condition)

    image.thumb.png.23d7d90e89f17bcdaa5009fb5dabb8c9.png

    Did I understand your question correctly?

    Regards,

    Thorsten

    • Like 1
  7. Hi Kenny,

    you can do this by first calculating the total duration of each capsule using Signal from Condition Tool:
    image.thumb.png.f9434dd94689d283ddafff50f6957575.png

    Here "Discrete" is used as the interpolation method as interpolated values of the calculated duration between the capsules for further calculations are not needed.

    Next you can calculate the average duration again using Signal from Condtion:
    image.thumb.png.f809656cded27bf235bc5b6088210e72.png

     

    Depending on where you put the value in step 1 the calculated average can change. In the foregoing example I put the value to the start of the capsule therefore only capsules starting in the bounding condition are used for calculation. If necessary, further adjustments must be made with regard to your usecase.

    Regards,

    Thorsten

  8. Hi Dylan, 

    you can use the aggregate function for this:

    $signal.aggregate(average(), ($signal > 90).removeLongerThan(1wk), durationKey())

    In this example the average of the signal is calculated whenever its value is above 90 and the result is drawn as a line over the duration of each capsule. You can find more information on the function and its parameters inside formula documentation.

    Hope this helps.

    Regards,

    Thorsten

    • Like 1
  9. 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

    • Like 1
  10. Hello Bayu,

    you may try it this way. I set up a sample in which my forecasted value will exceed the threshold two times in the next 3 days:

    image.thumb.png.243b0e068b5a6ab770fab2d78b65dd3e.png

    First step is identifying these periods by using the following formula:

    ($forecast > $limit).afterStart(0ns)

    This will create capsules with zero duration as I just need the timestamps for the points in time when the value will be exceed the limit.

    Next step is creating a new signal with the timestamp as the value:

    //Iterate over all capsules to create a signal 
    //with the value of the timestamp at start of the capsule
    $limitExceeded.toSamples($c ->
    {
      //Get date of capsule start
      $date = $c.startKey()
      
      //Create sample for signal
      sample($c.startKey(), $date)
    }, 1s)

    Last step is creating the scorecard:
    image.png.23e251dd3195bdbbaa9aba7f7427479d.png

     

    In case you may want to display the timestamp in another format you may read this post and adjust the formula in step 2.

    Hope this helps.

    Regards,

    Thorsten

    • Like 1
  11. Hi Aaron,

    you can use a formula for this. The following example calculates the total duration of all capsules of the operation condition since 06 Mar 2021 up to now. The result is a scalar.

    $operation.aggregate(totalDuration('h'), capsule('2021-03-06T00:00:00Z', now()))

    image.thumb.png.d98eaaf85745c2d0af4a848070302395.png

    Another option would be creating a condition that can be used in the "Signal from Condition" tool. You have to select an appropriate maximum capsule duration for the condition:

     condition(30d, capsule('2021-03-06T00:00:00Z', now()))

    image.thumb.png.3739c3fb5896d3f7f361cf9502255a67.png

    A more dynamic way would be calculating the duration based on the last maintenance. The following formula creates a condition for the times your equipment is running, in case you only have the maintenance capsules. growEnd(30d) extends the capsules to 30 days so you can use it for the current time. As growEnd() extends the capsules to the beginning of the next capsule I use subtract() to remove the maintenance periods from it.

    $maintenance.inverse().growend(30d).subtract($maintenance)

    The resulting condition is used inside Signal from Condition Tool:
    image.thumb.png.52f1dde816c56f3f1416269334e9d195.png

    Will this work for you?

    Regards,

    Thorsten

  12. Hi Robin, 

    you can use toCondition() on the Product ID Signal. This will create a condition with capsules each time the value changes. Then you can use Signal from Condition to get the desired values for each capsule.

    In the following example I calculate the used energy during each compressor stage:

    image.thumb.png.59be94bdfb2443401e0fd740af77b8e9.png

     

    Regards,

    Thorsten

    • Like 1
  13. Hi Vladimir,

    you can add another boundary to the signal. When choosing "Other" as the relation type a dashed line will be added to the display. 

    image.thumb.png.8502da9f35e98d4e3efe0f4eec7fe537.png

    In case you only want to have the dashed line for the range where the limits are equal you can create another signal for that and chosse this as the boundary:
    image.png.edf9526b4fc2673fe67066cbe8ea6739.png
     

    image.thumb.png.ba1062f93b5efd682de5ef41d9c57ea1.png

    Will this work for you?

    Regards,

    Thorsten

    • Like 2
  14. Hi Stephanie,

    yes, there a multiple solutions. I guess the easiest one is using the shifts() function:

    //Create shift at 05:30 and combine with shift at 17:30
    shifts(5.5, 12h).combineWith(shifts(17.5, 12h))

    You could also use periods together with move() or a startdate of the initial shift

    //Create a 12h capsule every 12hs and move to 05:30 / 17:30
    periods(12h, 12h).move(5.5h)
    //Create a 12h capsules every 12hs based on the specified date
    periods(12h,12h, '2021-01-01T05:30:00+01:00')

    In order to create just two capsules based on the current date you may use the following formula. As it uses now() the capsules have an uncertain state.

    //Get timestamp for today and yesterday at midnight
    $today = now().floorTime(1d)
    $yesterday = $today - 1d
    
    //create capsules
    condition(12h, capsule($yesterday + 5.5h, $yesterday + 17.5h), capsule($yesterday + 17.5h, $today + 5.5h))

    This is what it looks like in Workbench

    image.thumb.png.668bd9842c1bb189fc5247e5103c6394.png

    Regards,

    Thorsten

    • Like 1
  15. The API shown above returns the data in JSON format. To create a CSV file you

    - can write some custom code making use of the Seeq SDKs (here Python)

    import seeq_sdk as sdk
    import csv
     
    # login prompt definition
    def get_authenticated_client(api_url):
        api_client = sdk.ApiClient(api_url)
        auth_api = sdk.AuthApi(api_client)
        auth_input = sdk.AuthInputV1()
        auth_input.username =  <username>
        auth_input.password = <password>
        auth_input.auth_provider_class = "Auth"
        auth_input.auth_provider_id = "Seeq"
        auth_api.login(body=auth_input)
        return api_client
    
    seeq_api_url = 'http://seeqserver:34216/api'
    seeq_api_client = get_authenticated_client(seeq_api_url)
    datasourcesApi = sdk.DatasourcesApi(seeq_api_client)
    output = datasourcesApi.get_items_hosted_by_datasource(id=<id of datasource>, limit=300)
    
    with open("C:\\temp\\items.csv", "w", newline='') as csvFile:
        writer = csv.writer(csvFile)
        writer.writerow(["Name", "Type"])
        for item in output.items:
            writer.writerow([item.name, item.type])

    - take the output from the response body and use 3rd-party tools to convert to csv

    - use Seeq Data Lab (requires Seeq Data Lab license)

    data = spy.search({"Datasource Name": "Example Data"})
    data.to_csv('items.csv')

    Regards,

    Thorsten

    • Thanks 1
  16. Hi Vegini,

    I guess there are two ways to accomplish this. 

    First one is using Seeq CLI using the command seeq datasource items on the Seeq server. As you can see below you are able to filter for specific datasources you are interested in and also export the results to a .csv file.

    image.png.300a0c7604a47c630ead978747429771.png

    To get the name, class or id of a datasource you can execute seeq datasource list first to get the desired information to be used for filtering:image.thumb.png.60b5a5780b05fcad5ffed259b342087e.png

     

    More information on the CLI can be found here: https://support.seeq.com/space/KB/215384254/Seeq%20Server%20Command%20Line%20Interface%20(CLI)

    The second way would be utilizing the API, for example in a python script. As you see you have to specify the ID of the datasource to get the associated items. 

    image.thumb.png.e5fb7d1f66da148f0c58ed080db158dd.png

    The ID of a datasource can be determined by calling the datasources endpoint:

    image.thumb.png.a37f31d72ade275fad6f56dac58c7f3c.png

     

    Hope this helps.

    Regards,

    Thorsten

    • Like 3
×
×
  • Create New...