From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

DIAdem

cancel
Showing results for 
Search instead for 
Did you mean: 

TDMS oder TDM auf Kanal überprüfen ohne Datei zu laden

Solved!
Go to solution

Hallo zusammen,

 

bin ein Neuling was DIAdem-Scripte angeht und bin auf ein Problem gestoßen, welches ich auch durch eine intensive Websuche nicht lösen konnte, vielleicht hat hier jemand einen Tip, wie ich das angehen könnte und ob es eine einfache Möglichkeit gibt?

 

Ich habe Messergebnisse in TDM- und TDMS-Dateien. In jeder Datei sind ein Haufen Gruppen und Kanäle vorhanden, ich benötige jedoch nur einen ganz kleinen Teil und möchte daher die benötigten Kanäle mit dem Befehl "DataFileLoadSel" laden. Das funktioniert soweit auch, jedoch habe ich nun das Problem, dass die zu ladenen Kanäle sich im Namen und auch in der Kanalnummer unterscheiden, d.h. ich kann diese weder im Namen noch in der Kanalnummer eindeutig ansprechen. Die möglichen Namen kenne ich.

 

Jetzt wollte ich diese möglichen Kanäle in ein Array schreiben und nun in einer Schleife prüfen, ob diese in der Datei vorhanden sind, ohne diese komplett ins DIAdem zu laden und im Anschluss den vorhandenen Namen nutzen, um die Datei zu laden. Und genau an dieser Prüfung scheitere ich, da ich bisher nur Möglichkeiten gefunden habe Kanäle zu prüfen, welche bereits ins DIAdem geladen wurden.

 

Ich habe mir erstmal beholfen, indem ich alle Möglichkeiten lade und den Fehler und Scriptabbruch durch nicht vorhandene Kanäle mit "on error resume next" abfange. Das ist natürlich extrem unschön und die Laufzeit meines Programms ist verhältnismäßig lang.

 

Daher meine Frage: Hat jemand einen Tip oder eine Möglichkeit, wie ich Kanäle in Dateien, welche nicht geladen wurde auf Existenz vor dem Laden überprüfen kann?

 

Viele Dank schonmal.

 

Gruß Gerd

0 Kudos
Message 1 of 9
(5,730 Views)

Hi Gerd,

 

The simplest solution is to reference load the whole TDM or TDMS file, then check your possible channel list against the reference loaded channels in the Data Portal and delete the channels that don't match.  I'd recommend a Dictionary object for that lookup task.

 

There are a couple of different ways of reference loading these files.  For the particular case of TDM and TDMS files, and with DIAdem 2011 and later, the default behavior of DIAdem is to reference load TDM and TDMS files.  So if you've got DIAdem 2011 or later you can just use DataFileLoad normally.  If you have an older DIAdem version, or if you've configured DIAdem to NOT reference load TDM or TDMS files, then you will need to explicitly reference load the file like this:

 

Call DataFileLoad(DataFilePath, DataPluginName, "Register")

 

Brad Turpin

DIAdem Product Support Engineer

National Instruments

0 Kudos
Message 2 of 9
(5,724 Views)

If you really have a huge amount of channels in your file and can not use Brads approach you could try two additional approaches.

 

DataFinder: If your files are index by datafinder you can just search the channels (using or condition) and load them.

 

DataStore: Use code like the following one that allows you to extract information without having to multiple reopen the file.

Option Explicit

dim filenamePath : fileNamePath = "C:\temp\example.tdm"
dim store : set store = navigator.ConnectDataStoreByParameter("TDM", filenamePath)

dim group : set group = store.RootElements(1).Children("Example")
if group.Children.Exists("Time") then
  navigator.LoadData group.Children("Time"), "Load" , nothing
elseif group.Children.Exists("Revs") then
  navigator.LoadData group.Children("Revs"), "Load" , nothing
end if

 

0 Kudos
Message 3 of 9
(5,713 Views)

Hi Brad,

 

thanks for your reply.

 

The Problem is, that I have a lot of channels and groups in my files. When I load (or register) them all it'll be tricky to find out which one to delete an which not. Because all the channels I loaded I arrange in Groups with new names. It's possible for sure but I think it's not the simplest solution.

 

Gerd

0 Kudos
Message 4 of 9
(5,624 Views)

Hi Andreas,

 

thanks for your reply.

 

After one week holyday I tried your solution with the DataStore. I think this is the solution I was looking for. But I don't know if i understand what happens exactely so it does not work correct.

 

 

dim filenamePath : fileNamePath = "C:\temp\example.tdm"
-> no problem, my variable has another name so i just exchanged it. It already exists.


dim store : set store = navigator.ConnectDataStoreByParameter("TDM", filenamePath)
-> also no problem

 

dim group : set group = store.RootElements(1).Children("Example")
-> here i don't know for what "1" and "Example" stands. Perhaps 1 is the number of the group (group index) in my file?
-> Or is "Example" the name of the group? Iguess so, but what is the "1"?


if group.Children.Exists("Time") then

-> in which group does the function search the channel "Time"? In The group "Example"?

 

navigator.LoadData group.Children("Time"), "Load" , nothing
-> And I guess when the channel was found it's loaded? But this seems to be the part where my script loads something wrong. When i exchange this line with:

->call DataFileLoadSel(fileNamePath, "TDM" , "Example/Time", "Load")

-> it works and loads the channel i want, but else it loads a channel with the same name but different values. And in the data portal ist not a "~" in front of the channel, ther is a "123"

 

 

 

my code looks like this:

"Richtung" is variable with the group name in my file where the channel is located

"oResult" is the result of the file search (the file whith the data)

"v_Fahrzeug", "GPS_Speed" and "Geschwindikgeit" are the possibilities for the channel names.

 

 

 

dim store : set store = navigator.ConnectDataStoreByParameter(Right(oResult.name, (len(oResult.name) - inStrRev(oResult.name, "."))), "D:\DIADEM_Auswertung\Auswertung_Daten\Messung\" & oResult.name)
dim group : set group = store.RootElements(1).Children(Richtung)
if group.Children.Exists("v_Fahrzeug") then
  call DataFileLoadSel("D:\DIADEM_Auswertung\Auswertung_Daten\Messung\" & oResult.name,Right(oResult.name, (len(oResult.name) - inStrRev(oResult.name, "."))) , Richtung & "/v_Fahrzeug", "Load")
  'navigator.LoadData group.Children("v_Fahrzeug"), "Load" , nothing
elseif group.Children.Exists("GPS_Speed") then
  navigator.LoadData group.Children("GPS_Speed"), "Load" , nothing
elseif group.Children.Exists("Geschwindikgeit") then
  navigator.LoadData group.Children("Geschwindikgeit"), "Load" , nothing
end if

 

 

 

So where is the mistake?

 

Could you please explain me the function of your code an the expression "navigator.LoadData group.Children("Time"), "Load" , nothing"?

 

Sorry if it's not clear what I want to know, my english is not the best and a bit "rusty".

 

Gerd

 

 

 

 

 

 

0 Kudos
Message 5 of 9
(5,619 Views)

If you already use datafinder to determine oResult you shoult try to determine the channels you want to load by extending the query.

 

If you want to load using datastore I expanded the example with some extra lines and comments. Trying to answer your questions.

 

Option Explicit 

dim filenamePath : fileNamePath = "C:\temp\example.tdm"

dim storeType : storeType =  UCase(Right(filenamePath, (len(filenamePath) - inStrRev(filenamePath, "."))))

' open the file Readonly, storetype must be TDM or TDMS
dim store : set store = navigator.ConnectDataStoreByParameter(storeType, "<filename readonly=""yes"">" & replace(filenamePath, "&", "&amp;") & "</filename>")

dim root : set root = store.RootElements(1) ' tdm datastores do always have exactly one root
dim group : set group = root.Children("Example") ' get the group by name
if group.Children.Exists("Time") then
  navigator.LoadData group.Children("Time"), "Load" , nothing
elseif group.Children.Exists("Revs") then
  navigator.LoadData group.Children("Revs"), "Load" , nothing
end if

store.Close ' closes the access to the file. Will happen automatically if script finishes

 

I am not aware of any case where DataFileLoadSel loads something different than the channel loaded using the datastore API. So if you have such files I would be very interested to get one of them.

(What does different values mean?)

 

I have also no idea what " ist not a "~" in front of the channel, ther is a "123"" refers to. If DIAdem loads to channels named Time by default the second one gets 1 atatched.

The navigator.LoadData returns the result channels/channels so it is possible to change the name to your needs.

 

Message 6 of 9
(5,608 Views)

Okay, I think I have to explain my problem detailed that you understand what I'm doing.

 

I have a folder "D:\DIADEM_Auswertung\Auswertung_Daten". In this folder there are two diffrent folders called "Messung" and "Simulation" where are files created out of measurements in one folder and files created out of simulations in the other folder. Sometimes just one measurement file and one simulation file but probably sometimes more than one.

Now we have to compare the simulation and the measurement to find out if the measurement was okay. The problem now is, that the files out of the measurement contain a lot of data (goups and channels) which are not interesting for us. One file has about 500 mb. So I don't want to load the whole file but just the few channels we need. In addition in one file there are more than one measurement (4-6). This different data is stored in groups. So I have 4 to 6 groups in one file which i have to look through. Unfortunately this are not all the groups in the file and the group index is not always the same. Also the names of the channels and the index of the channels are not the same.

Now the task is to find the channels, load them, rename them, and probably change the unit or convert them to another unit. Furthermore I have to organize the loaded channels in Groups named after the files.

 

First of all I use the navigator to find my files in the folder "Messungen". For each one I call a function which loads all of my 10 channels if they are existing. Moreover I have a function call for each measurement in one file.

 

Afterwards I have to do the same with the files out the simulation but this is no problem because the channels are named always the same so I can load them directly.

 

Here is a bigger part of my code:

 

sub LoadData
.
.
.
 i = 1
 Rueckgabe = 0
 For Each oResult In oResult.Elements
      
  Richtung = "Beschl_Richtung 1 - Nord-Sued_01"
      Rueckgabe = Messung (i, Richtung, oResult)
      i=i+1-Rueckgabe
      
      Richtung = "Beschl_Richtung 1 - Nord-Sued_02"
      Rueckgabe = Messung (i, Richtung, oResult)
      i=i+1-Rueckgabe
.
.
.
end sub


function Messung (byval i, Richtung, oResult)

dim filenamePath : filenamePath = "D:\DIADEM_Auswertung\Auswertung_Daten\Messung\" & oResult.name
dim storeType : storeType =  UCase(Right(filenamePath, (len(filenamePath) - inStrRev(filenamePath, "."))))
dim store : set store = navigator.ConnectDataStoreByParameter(storeType, filenamePath)
dim root : set root = store.RootElements(1)
if root.Children.Exists(Richtung) then

  Dim KanalGeschFahr : KanalGeschFahr = Array("v_Fahrzeug", "GPS_Speed", "Geschwindikgeit")
  Dim KanalBeschleunigung : KanalBeschleunigung = Array("GS2_Acceleration", "a_Fahrzeug_x", "Beschleunigung")
.
.
.
  dim m
 
  Call GroupCreate(left(oResult.name, inStrRev(oResult.name, ".")-1)& ":  " & Richtung,i)
  data.Root.ChannelGroups(left(oResult.name, inStrRev(oResult.name, ".")-1)& ":  " & Richtung).Activate

  dim group : set group = root.Children(Richtung)

  for m=0 to ubound (KanalGeschFahr)
    if group.Children.Exists(KanalGeschFahr(m)) then
      'navigator.LoadData group.Children(KanalGeschFahr(m)), "Load" , nothing
      call DataFileLoadSel(filenamePath, storeType, Richtung & "/" & KanalGeschFahr(m), "Load")
      Call ChnPropSet(KanalGeschFahr(m),"unit_string", "km/h")
      Call ChnPropSet(KanalGeschFahr(m),"name", "GeschwindigkeitFahrzeug")
      exit for
    end if
  next

  for m=0 to ubound (KanalBeschleunigung)
    if group.Children.Exists(KanalBeschleunigung(m)) then
      call DataFileLoadSel(filenamePath, storeType, Richtung & "/" & KanalBeschleunigung(m), "Load")
      Call ChnPropSet(KanalBeschleunigung(m),"unit_string", "m/s")
      Call ChnPropSet(KanalBeschleunigung(m),"name", "Beschleunigung")
      exit for
    end if
  next
.
.
.

  if cno(left(oResult.name, inStrRev(oResult.name, ".")-1)& ":  " & Richtung & "/GeschwindigkeitFahrzeug") = 0 _
    and cno(left(oResult.name, inStrRev(oResult.name, ".")-1)& ":  " & Richtung & "/Beschleunigung") = 0 _
    .
.
.  then
      Messung="1"
  else
      Messung="0"
  end if

else
  Messung="1"
end if
    
end function


 

Is that code okay in your opinion?

 

To your last question about the loading by DataFileLoadSel and the channel loaded using the datastore API:

The channels in the file out of the measurement are chanels in wave form. When I'm using the DataFileLoadSel the loaded channel is also in wave form, otherwise I use the channel loaded using the datastore API I get channels loaded in numeric form. I hope this is explained right. Here is also a picture where you probably see what I mean. The marked channels.

 

 

 

 

 

Message 7 of 9
(5,595 Views)
Solution
Accepted by topic author auxxburger

First I want to add a datafinder example which I think might solve your issue with less code:

 

option explicit

dim filenamePath : fileNamePath = "C:\Users\Public\Documents\National Instruments\DIAdem 2012\Data\Example.tdm"
dim targetGroupName : targetGroupName =  Right(filenamePath, (len(filenamePath) - inStrRev(filenamePath, "\")))

dim targetGroup : set targetGroup = data.Root.ChannelGroups.Add(targetGroupName) ' create a target group
call targetGroup.Activate() ' set this group as target for load events 

'--- Search without GUI
Dim oMyDataFinder, oMyQuery, oMyResults
Set oMyDataFinder = Navigator.ConnectDataFinder("My DataFinder")
Set oMyQuery = oMyDataFinder.CreateQuery(eAdvancedQuery)
oMyQuery.ReturnType = eSearchChannel
Set oMyConditions = oMyQuery.Conditions
 
Dim oMyConditions
'--- Fill the query
Call oMyConditions.Add(eSearchFile,"fullpath","=",fileNamePath)
Call oMyConditions.Add(eSearchChannelGroup,"name","=","Noise data")
Call oMyConditions.Add(eSearchChannel,"name","=",Array("Noise_1", "Schall_1", "Noise_2", "NotContained"))
oMyConditions.Logic = "C1 AND C2 AND C3"
 
'--- Search without GUI
Call oMyDataFinder.Search(oMyQuery)
Set oMyResults = oMyDataFinder.Results
if oMyResults.Count > 0 then
  call navigator.LoadData(oMyResults, "Load", nothing)
end if

 The different names are just part of the query. They are used as an array.

 

Second I extend the datastore example to load meta data which will also import the waveform properties.

Option Explicit 

dim filenamePath : fileNamePath = "C:\Users\Public\Documents\National Instruments\DIAdem 2012\Data\Example.tdm"

dim storeType : storeType =  UCase(Right(filenamePath, (len(filenamePath) - inStrRev(filenamePath, "."))))
dim targetGroupName : targetGroupName =  Right(filenamePath, (len(filenamePath) - inStrRev(filenamePath, "\")))

' open the file Readonly, storetype must be TDM or TDMS
dim store : set store = navigator.ConnectDataStoreByParameter(storeType, "<filename readonly=""yes"">" & replace(filenamePath, "&", "&amp;") & "</filename>")

' we want to load meta data also. So we craete a load configuration
dim loadconfig : set loadconfig = navigator.Settings.CreatePropertyImportSet(store)
Call loadconfig.Properties.Add("tdm_channel","<InstanceProperties>") ' also add all custom properties

dim root : set root = store.RootElements(1) ' tdm datastores do always have exactly one root
dim group : set group = root.Children("Noise data") ' get the group by name

dim targetGroup : set targetGroup = data.Root.ChannelGroups.Add(targetGroupName) ' create a target group
call targetGroup.Activate() ' set this group as target for load events 

dim sourceChannel : set sourceChannel = nothing
if group.Children.Exists("Noise_1") then
  set sourceChannel = group.Children("Noise_1")
elseif group.Children.Exists("Revs") then
  set sourceChannel = group.Children("Revs")
end if
call navigator.LoadData(sourceChannel, "Load" , loadconfig)

call store.Close() ' closes the access to the file. Will happen automatically if script finishes

 

In both cases the result of LoadData can be used to do post processing steps.

 

 

Message 8 of 9
(5,584 Views)

Thanks a lot!

0 Kudos
Message 9 of 9
(5,574 Views)