how to read PC information with DM script - dm-script

I want to release a DM script tied to a specific PC. GMS license won't work because free license has a common license ID,
"GATAN_FREE"
How can I insert a secret code to give error message when the script runs on a different machine?
I am thinking to use computer name or username. Is there a way to read Windows system variables? If using
LaunchExternalProcessAsync(callString)
to launch DOS command "echo -username", how to catch the output?
Any solution or suggestions?

Nice thinking.
The trick with LaunchExternalProcess is to create some useful string which can be 'executed'. You can try various applications with their own command-line parameters.
In the most general situation, you can create a dummy-batch file and execute it. (Provided you have read/write access on the computer!)
As the LaunchExternalProcess also returns the exit code from the launched process, you can at least pass back one integer variable directly. Otherwise, you need to have the batch file save to a file and have DM read that file.
// Temporary batch file creation
string batchPath = "C:\\Dummy.bat"
string batchText
string auxFilePath = "C:\\tmp_dummy.txt"
batchText += "dir *.* >> " + auxFilePath + "\n"
batchText += "exit 999" + "\n"
// Ensure no files exist...
if ( DoesFileExist(auxFilePath) )
DeleteFile(auxFilePath)
if ( DoesFileExist(batchPath) )
DeleteFile(batchPath)
// Write the batch file....
number fileID = CreateFileForWriting(batchPath)
WriteFile(fileID,batchText)
CloseFile(fileID)
// Call the batch file and retrieve its exit code
number kTimeOutSec = 5 // Prevent freezing of DM if something in the batch file is wrong
number exitCode = LaunchExternalProcess( batchPath, kTimeOutSec )
// Do something with the results
Result( "\n Exit value of batch was:" + exitCode )
if ( DoesFileExist(auxFilePath) )
{
string line
fileID = OpenFileForReading(auxFilePath)
ReadFileLine( fileID, line )
CloseFile(fileID)
Result("\n First line of auxiliary file:" + line )
}
// Ensure no files exist...
if ( DoesFileExist(auxFilePath) )
DeleteFile(auxFilePath)
if ( DoesFileExist(batchPath) )
DeleteFile(batchPath)

This is not a direct answer to your question, but to the overall goal you've mentioned.
An alternative "DM only" solution for restricting script access would be to use the persistent tags of the application itself! (These are stored in the preferences of the application.)
string tagPath = "MyScripts:LicensedComputer"
string installPW = "password"
string mayLoadPassCode = ""
GetPersistentStringNote( tagPath, mayLoadPassCode )
if ( mayLoadPassCode != installPW )
{
string pw
if ( !GetString( "Forbidden.\n Enter password:", pw, pw ) )
exit(0)
if ( pw != installPW )
Throw( "Invalid password." )
SetPersistentStringNote( tagPath, pw )
}
OKDialog( "You may use my script..." )
Obviously this isn't the most secure lock-out, as any user could set the tag manually as well, but as long as the tag-path is "secret" and the password remains "secret" (i.e. you don't share the script in source code) it is reasonably 'save'.
In a similar way, you could make your script write a specific "license" file to the computer and check for that each time. The advantage is, that deleting/resetting the DM preference file would not affect this.

Related

Passing list of filenames to nextflow process

I am a newcomer to Nextflow and I am trying to process multiple files in a workflow. The number of these files is more than 300, so I would like to not to paste it into a command line as an option. So what I have done is I've created a file with every filename of the files I need to process, but I am not sure how to pass it into the process. This is what I've tried:
params.SRRs = "srr_ids.txt"
process tmp {
input:
file ids
output:
path "*.txt"
script:
'''
while read id; do
touch ${id}.txt;
echo ${id} > ${id}.txt;
done < $ids
'''
}
workflow {
tmp(params.SRRs)
}
The script is supposed to read in the file srr_ids.txt, and create files that have their ids in it (just testing on a smaller task). The error log says that the id variable is unbound, but I don't understand why. What is the conventional way of passing lots of filenames to a pipeline? Should I write some other process that parses the list?
Maybe there's a typo in your question, but the error is actually that the ids variable is unbound:
Command error:
.command.sh: line 5: ids: unbound variable
The problem is that when you use a single-quote script string, you will not be able to access Nextflow variables in your script block. You can either define your script using a double-quote string and escape your shell variables:
params.SRRs = "srr_ids.txt"
process tmp {
input:
path ids
output:
path "*.txt"
script:
"""
while read id; do
touch "\${id}.txt"
echo "\${id}" > "\${id}.txt"
done < "${ids}"
"""
}
workflow {
SRRs = file(params.SRRs)
tmp(SRRs)
}
Or, use a shell block which uses the exclamation mark ! character as the variable placeholder for Nextflow variables. This makes it possible to use both Nextflow and shell variables in the same piece of code without having to escape each of the shell variables:
params.SRRs = "srr_ids.txt"
process tmp {
input:
path ids
output:
path "*.txt"
shell:
'''
while read id; do
touch "${id}.txt"
echo "${id}" > "${id}.txt"
done < "!{ids}"
'''
}
workflow {
SRRs = file(params.SRRs)
tmp(SRRs)
}
What is the conventional way of passing lots of filenames to a
pipeline?
The conventional way, I think, is to actually supply one (or more) glob patterns to the fromPath channel factory method. For example:
params.SRRs = "./path/to/files/SRR*.fastq.gz"
workflow {
Channel
.fromPath( params.SRRs )
.view()
}
Results:
$ nextflow run main.nf
N E X T F L O W ~ version 22.04.4
Launching `main.nf` [sleepy_bernard] DSL2 - revision: 30020008a7
/home/steve/working/stackoverflow/73702711/path/to/files/SRR1910483.fastq.gz
/home/steve/working/stackoverflow/73702711/path/to/files/SRR1910482.fastq.gz
/home/steve/working/stackoverflow/73702711/path/to/files/SRR1448795.fastq.gz
/home/steve/working/stackoverflow/73702711/path/to/files/SRR1448793.fastq.gz
/home/steve/working/stackoverflow/73702711/path/to/files/SRR1448794.fastq.gz
/home/steve/working/stackoverflow/73702711/path/to/files/SRR1448792.fastq.gz
If instead you would prefer to pass in a list of filenames, like in your example, use either the splitCsv or the splitText operator to get what you want. For example:
params.SRRs = "srr_ids.txt"
workflow {
Channel
.fromPath( params.SRRs )
.splitText() { it.strip() }
.view()
}
Results:
$ nextflow run main.nf
N E X T F L O W ~ version 22.04.4
Launching `main.nf` [fervent_ramanujan] DSL2 - revision: 89a1771d50
SRR1448794
SRR1448795
SRR1448792
SRR1448793
SRR1910483
SRR1910482
Should I write some other process that parses the list?
You may not need to. My feeling is that your code might benefit from using the fromSRA factory method, but we don't really have enough details to say one way or the other. If you need to, you could just write a function that returns a channel.

How to run same syntax on multiple spss files

I have 24 spss files in .sav format in a single folder. All these files have the same structure. I want to run the same syntax on all these files. Is it possible to write a code in spss for this?
You can use the SPSSINC PROCESS FILES user submitted command to do this or write your own macro. So first lets create some very simple fake data to work with.
*FILE HANDLE save /NAME = "Your Handle Here!".
*Creating some fake data.
DATA LIST FREE / X Y.
BEGIN DATA
1 2
3 4
END DATA.
DATASET NAME Test.
SAVE OUTFILE = "save\X1.sav".
SAVE OUTFILE = "save\X2.sav".
SAVE OUTFILE = "save\X3.sav".
EXECUTE.
*Creating a syntax file to call.
DO IF $casenum = 1.
PRINT OUTFILE = "save\TestProcess_SHOWN.sps" /"FREQ X Y.".
END IF.
EXECUTE.
Now we can use the SPSSINC PROCESS FILES command to specify the sav files in the folder and apply the TestProcess_SHOWN.sps syntax to each of those files.
*Now example calling the syntax.
SPSSINC PROCESS FILES INPUTDATA="save\X*.sav"
SYNTAX="save\TestProcess_SHOWN.sps"
OUTPUTDATADIR="save" CONTINUEONERROR=YES
VIEWERFILE= "save\Results.spv" CLOSEDATA=NO
MACRONAME="!JOB"
/MACRODEFS ITEMS.
Another (less advanced) way is to use the command INSERT. To do so, repeatedly GET each sav-file, run the syntax with INSERT, and sav the file. Probably something like this:
get 'file1.sav'.
insert file='syntax.sps'.
save outf='file1_v2.sav'.
dataset close all.
get 'file2.sav'.
insert file='syntax.sps'.
save outf='file2_v2.sav'.
etc etc.
Good luck!
If the Syntax you need to run is completely independent of the files then you can either use: INSERT FILE = 'Syntax.sps' or put the code in a macro e.g.
Define !Syntax ()
* Put Syntax here
!EndDefine.
You can then run either of these 'manually';
get file = 'file1.sav'.
insert file='syntax.sps'.
save outfile ='file1_v2.sav'.
Or
get file = 'file1.sav'.
!Syntax.
save outfile ='file1_v2.sav'.
Or if the files follow a reasonably strict naming structure you can embed either of the above in a simple bit of python;
Begin Program.
imports spss
for i in range(0, 24 + 1):
syntax = "get file = 'file" + str(i) + ".sav.\n"
syntax += "insert file='syntax.sps'.\n"
syntax += "save outfile ='file1_v2.sav'.\n"
print syntax
spss.Submit(syntax)
End Program.

How to process various tasks like video acquisition parallel in Matlab?

I want to acquire image data from stereo camera simultaneously, or in parallel, save somewhere and read the data when need.
Currently I am doing
for i=1:100
start([vid1 vid2]);
imageData1=getdata(vid1,1);
imageData2=getdata(vid2,1);
%do several calculations%
....
end
In this cameras are working serially and it is very slow. How can I make 2 cameras work at a time???
Please help..
P.S : I also tried parfor but it does not help .
Regards
No Parallel Computing Toolbox required!
The following solution can generally solve problems like yours:
First the videos, I just use some vectors as "data" and save them to the workspace, these would be your two video files:
% Creating of some "videos"
fakevideo1 = [1 ; 1 ; 1];
save('fakevideo1','fakevideo1');
fakevideo2 = [2 ; 2 ; 2];
save('fakevideo2','fakevideo2');
The basic trick is to create a function which generates another instance of Matlab:
function [ ] = parallelinstance( fakevideo_number )
% create command
% -sd (set directory), pwd (current directory), -r (run function) ...
% finally "&" to indicate background computation
command = strcat('matlab -sd',{' '},pwd,{' '},'-r "processvideo(',num2str(fakevideo_number),')" -nodesktop -nosplash &');
% call command
system( command{1} );
end
Most important is the use of & at the end of the terminal command!
Within this function another function is called where the actual video processing is done:
function [] = processvideo( fakevideo_number )
% create file and variable name
filename = strcat('fakevideo',num2str(fakevideo_number),'.mat');
varname = strcat('fakevideo',num2str(fakevideo_number));
% load video to workspace or whatever
load(filename);
A = eval(varname);
% do what has to be done
results = A*2;
% save results to workspace, file, grandmothers mailbox, etc.
save([varname 'processed'],'results');
% just to show that both processes run parallel
pause(5)
exit
end
Finally call the two processes in your main script:
% function call with number of video: parallelinstance(fakevideo_number)
parallelinstance(1);
parallelinstance(2);
My code is completely executable, so just play around a bit. I tried to keep it simple.
After all you will find two .mat files with the processed video "data" in your workspace.
Be aware to adjust the string fakevideo to name root of all your video files.

Why "Process" class in vb.net doesn't capture errors from cmd.exe?

I'm trying to run dos commands within vb.net program and capture output. I have the following code:
Dim CMDServer As Diagnostics.ProcessStartInfo
Dim CMDReply As Diagnostics.Process
CMDServer = New Diagnostics.ProcessStartInfo
CMDServer.FileName = "cmd.exe"
CMDServer.UseShellExecute = False
CMDServer.RedirectStandardOutput = True
CMDServer.CreateNoWindow = True
CMDServer.Arguments = "/C " + command
CMDReply = Process.Start(CMDServer)
Dim Reply As String = CMDReply.StandardOutput.ReadToEnd()
The code runs successfully if command is a valid dos command, and I get the output in Reply. If the command have no output ( eg: cd\ ) Reply is null. The problem is Reply is null even when the command is invalid. How to capture errors like "command is not recognized as an internal or external command...", "The system cannot find the path specified.." etc.. Please help me. Thanks..
Error messages come in a different output stream called StandardError. Just use a StreamReader or read it directly. Of course, the RedirectStandardError-Property of your ProcessStartInfo instance must be set to True.
Also, there is a ExitCode-Property which returns the ExitCode of the program after it has finished. 0 means 'successful'. Other error codes can be found in the MSDN Documentation. Here is a list of the common exit codes. For example, 2 means The system cannot find the file specified..
Errors are probably output on CMDReply.StandardError, not CMDReply.StandardOutput; try reading it, too. (And set CMDServer.RedirectStandardError to True as well.)

How to match similar filenames and rename so that diff tools like Beyond Compare see them as a pair to perform a binary comparison?

I'm looking for the best approach to comparing files that I believe are identical but which have different filenames. Comparison tools like BeyondCompare are great but they don't yet handle different filenames - when comparing files in separate folders they attempt comparisons with the files that have the same name on either side.
(I don't work for or have a financial interest in BeyondCompare, but I use the tool a lot and find it has some great features).
There is MindGems Fast Duplicate File Finder for matching files in any location throughout several folder trees that have different names but this is based on CRC checks I believe, I am using this tool but I am only gradually trusting it, so far no faults but don't trust it as much as BeyondCompare yet. BeyondCompare offers the complete piece of mind of doing a full binary compare on the file.
In my case the files tend to have similar names, the difference being ordering of the words, punctuation, case differences and not all words present. So it's not easy to use a regex filter to match the files that some diff tools like Beyond Compare already provide because the file substrings can be out of order.
I'm looking for a way to match similar filenames before renaming the files to be the same and then 'feeding' them to a tool like BeyondCompare. Solutions could be scripts or perhaps in the form of an application.
At the moment I have an idea for an algorithm (to implement in Perl) to match the filenames to suit my problem whereby the filenames are similar as described above.
Can you suggest something better or a completely different approach?
Find a list of files with the exact same filesize
Make a hash of alphanumeric substrings from first file, using
non-alphanumeric characters or space as delimiter
Make a hash of alphanumeric substrings from second file, using
non-alphanumeric characters or space as delimiter
Match occurrences
Find which file has the highest number of substrings.
Calculate a percentage score for the comparison on the pair based on
number of matches divided by the highest number of substrings.
Repeat comparison for each file with every other file with the exact
file size
sort the pair comparisons by percentage score to get suggestions of
files to compare.
Rename one file in the pair so that it is the same as the other. Place in separate folders.
Run a comparison tool like BeyondCompare with the files, folder comparison mode.
As I already have Fast Duplicate File Finder Pro, this outputs a text report of the duplicates in CSV and XML format.
I will process the CSV to see the groupings and rename the files so that I can get beyond compare to do a full binary comparison on them.
Update:
And here is my code. This Perl script will look at each pair of files (in the directories/folders being compared) that are the same and rename one of them to be the same as the other so that the two folders can be run through Beyond Compare which will do a full binary compare (if the flatten folders option is switched on). Binary compare confirms the match so that means that one of each duplicate pair can be purged.
#!/usr/bin/perl -w
use strict;
use warnings;
use File::Basename;
my $fdffCsv = undef;
# fixed
# put matching string - i.e. some or all of path of file to keep here e.g. C:\\files\\keep\\ or just keep
my $subpathOfFileToKeep = "keep";
# e.g. jpg mp3 pdf etc.
my $fileExtToCompare = "jpg";
# changes
my $currentGroup = undef;
my $group = undef;
my $filenameToKeep = "";
my $path = undef;
my $name = undef;
my $extension = undef;
my $filename = undef;
open ( $fdffCsv, '<', "fast_duplicate_filefinder_export_as_csv.csv" );
my #filesToRenameArray = ();
while ( <$fdffCsv> )
{
my $line = $_;
my #lineColumns = split( /,/, $line );
# is the first column and index value
if ( $lineColumns[0] =~ m/\d+/ )
{
$group = $lineColumns[0];
( $line ) =~ /("[^"]+")/;
$filename = $1;
$filename =~ s/\"//g;
if ( defined $currentGroup )
{
if ( $group == $currentGroup )
{
( $name, $path, $extension ) = fileparse ( $filename, '\..*"' );
store_keep_and_rename();
}
else # group changed
{
match_the_filenames();
( $name, $path, $extension ) = fileparse ( $filename, '\..*"' );
store_keep_and_rename();
}
}
else # first time - beginning of file
{
$currentGroup = $group;
( $name, $path, $extension ) = fileparse ( $filename, '\..*"' );
store_keep_and_rename();
}
}
}
close( $fdffCsv );
match_the_filenames();
sub store_keep_and_rename
{
if ( $path =~ /($subpathOfFileToKeep)/ )
{
$filenameToKeep = $name.$extension;
}
else
{
push( #filesToRenameArray, $filename );
}
}
sub match_the_filenames
{
my $sizeOfFilesToRenameArraySize = scalar( #filesToRenameArray );
if ( $sizeOfFilesToRenameArraySize > 0 )
{
for (my $index = 0; $index < $sizeOfFilesToRenameArraySize; $index++ )
{
my $PreRename = $filesToRenameArray[$index];
my ( $preName, $prePath, $preExtension ) = fileparse ( $PreRename, '\..*' );
my $filenameToChange = $preName.$preExtension;
my $PostRename = $prePath.$filenameToKeep;
print STDOUT "Filename was: ".$PreRename."\n";
print STDOUT "Filename will be: ".$PostRename."\n\n";
rename $PreRename, $PostRename;
}
}
undef( #filesToRenameArray ); #filesToRenameArray = ();
$currentGroup = $group;
}
Beyond Compare can do that.
Just select the file on the left and the file to compare on the right.
Choose 'compare' or use the align function (right mouse button)