MatLab - Execute functions base on their name - file

I have a couple of MatLab function, and almost all of them have a test function. There is not really a naming convention right now for test functions, so I end up with functions like test_functionName, tests_functionName, FunctionName_Test, etc.
Howerver, I see two things these functions have in common :
The name contains "test" (with different casing).
They have no input or output parameters.
I would like to write a function that would find, under a given folder (or in the PATH), all the functions that respect these two conditions and execute them. This way I could execute all my tests functions in one single call.
Is there any way I can do that?

You can do as follow:
fun=dir('*test*.m'); %% look for matlab scripts which name contains 'test'
fun={fun.name}; %% extract their names
fun=fun(cellfun(#(x) (nargin(x)==0),fun)); %% select the ones with no input arguments
fun = regexprep(fun, '.m', ''); % remove '.m' from the filenames
cellfun(#eval,fun); %% execute them

First, get all files under your folder:
d = dir(myFolder);
Remove those whose extension is not .m :
indexes = strcmp('.m',{d.ext});
d(indexes) = [];
Then, collect all of their names:
fileNames = {d.Name};
Check which one start or end with test:
testPrefix = strncmp('test',fileNames)
testPostfix = %# Left as an exercise to the reader
sutiableFileNames = fileNames( testPrefix | testPostfix);
Now you can check the amount of parameters using `nargin':
numOfInParams = cellfun(#nargin,sutiableFileNames);
numOfOutParams = cellfun(#nargout,sutiableFileNames);
And then filter again (I think you already got the idea)

Related

Repeating syntax for a list of variables in SPSS

I have a dataset with 134 different variables, I have now one variable for where the syntax is working and this runs fine on my SPSS. However, I don't want to have to repeat this step by hand 133 times more, as it is a lot of work. I want to know the string term present in AE_term1 and create a new variable where it is classified as a number, called AE_term1num. However, I don't know how to write a syntax that automatically does this for all 134 AE_term. Could someone please help me?
The data looks like this:
AE_term1
AE_dur1
AE_term2
AE_dur2
etc
Cystitis
14
Heamaturia
3
uti
15
Sepsis
8
etc
etc
etc
etc
To identify the string variable, i have written the following syntax:
`compute AE_term1num=0.
do if (char.index(lower(AE_term1), "cystitis")).
compute AE_term1num=1.
else if (char.index(lower(AE_term1), "uti")).
compute AE_term1num = 2.
else.
compute AE_term1num=0.
end if.
execute.`
This syntax works for finding the correct values and returns what i want, however I do not know how to loop it over the remaining 133 AE_term variables, if this is even possible.
To start with, your original syntax can be streamlined like this:
compute AE_term1num=0.
if char.index(lower(AE_term1), "cystitis") AE_term1num=1.
if char.index(lower(AE_term1), "uti") AE_term1num = 2.
Now if the same conditions exactly apply for all the rest of the variables, you can use do repeat to automate the process:
do repeat AE_term = AE_term1 to AE_term134 / AE_termN = AE_termN1 to AE_termN134.
compute AE_termN=0.
if char.index(lower(AE_term), "cystitis") AE_termN=1.
if char.index(lower(AE_term), "uti") AE_termN= 2.
end repeat.
NOTE - using AE_term1 to AE_term134 - existing variables - requires that they be consecutive in the dataset. Using AE_termN1 to AE_termN134 to create new variables requires that the numbers be at the end of the name, so AE_term1num to AE_term134num wouldn't work.

How can you run a loop in SPSS syntax that calculates the difference between many sets of variables?

I have a set of variables (A1, A2, B1, B2, C1, C3 ...) that I need to calculate the difference for to eventually create a set of Bland-Altman plots after extracting the mean difference and sd of the difference from a t-test using OMS.
As a first step I have it working for a single pair of variables (e.g. A1 and A2) and am now trying to create a macro that will loop through the first few pairs as a test:
```
DEFINE BlandAlt (scan1vars=!CMDEND / scan2vars=!CMDEND)
COMPUTE diff = scan1vars - scan2vars.
EXECUTE.
T-TEST
/TESTVAL=0
/MISSING=ANALYSIS
/VARIABLES=diff
/CRITERIA=CI(.95).
!ENDDEFINE.
BlandAlt
scan1vars = JumpJumpHeightcm.1 JumpJumpHeightt_score.1 JumpMaxChangeinAccelerationms3.1 JumpMaxChangeinAccelerationt_score.1 JumpMaxAccelerationms2.1 JumpMaxAccelerationt_score.1
scan2vars= JumpJumpHeightcm.2 JumpJumpHeightt_score.2 JumpMaxChangeinAccelerationms3.2 JumpMaxChangeinAccelerationt_score.2 JumpMaxAccelerationms2.2 JumpMaxAccelerationt_score.2.
```
When I run the macro I get an error on the first variable:
Error # 4381 in column 35. Text: JumpJumpHeightt_score.1 The
expression ends unexpectedly. Execution of this command stops.
and a warning when it tries to run the t-test:
Text: diff Command: T-TEST An undefined variable name, or a scratch or
system variable was specified in a variable list >which accepts only
standard variables. Check spelling and verify the existence of this
variable. Execution of this command stops.
Is anyone able to help get this part working? I'm hoping it should then be easy to include the other commands within the macro.
See my comment for corrections to your original macro. After correcting the macru it should work well, only you are not using the macro call the way it is built. You need to call it this way:
BlandAlt scan1vars = JumpJumpHeightcm.1 / scan2vars= JumpJumpHeightcm.2 .
BlandAlt scan1vars = JumpJumpHeightt_score.1 / scan2vars=JumpJumpHeightt_score.2 .
...
Now this is obviously not looping throug your variable list. The problem with SPSS macro is that it's very difficult to get it to loop through two lists at the same time. But in your case, there is no need - there is only one actual list to loop through, while letting the macro add the 1 or 2 suffix to the variable name. Try this:
DEFINE BlandAlt (vrs=!CMDEND)
!do !vr !in(!vrs)
COMPUTE diff = !concat(!vr,".1") - !concat(!vr,".2").
EXECUTE.
TTEST.....
!doend
!enddefine.
Now the macro call would look like this:
BlandAlt vrs = JumpJumpHeightcm JumpJumpHeightt_score JumpMaxChangeinAccelerationms3
JumpMaxChangeinAccelerationt_score JumpMaxAccelerationms2 JumpMaxAccelerationt_score .
I have another solution to offer - putting this in a separate answer because it uses a completely different approach. The idea is that sometimes instead of looping through variables for analyses, you can get the same results by restructuring to long format and then analysing only once using split file. Like this:
varstocases
make scan1vars from JumpJumpHeightcm.1 JumpJumpHeightt_score.1 JumpMaxChangeinAccelerationms3.1
JumpMaxChangeinAccelerationt_score.1 JumpMaxAccelerationms2.1 JumpMaxAccelerationt_score.1 /
make scan2vars from JumpJumpHeightcm.2 JumpJumpHeightt_score.2 JumpMaxChangeinAccelerationms3.2
JumpMaxChangeinAccelerationt_score.2 JumpMaxAccelerationms2.2 JumpMaxAccelerationt_score.2 /
index=origvar(scan1vars).
* now you can do the whole process only once.
COMPUTE diff = scan1vars - scan2vars.
sort cases by origvar.
split file by origvar.
T-TEST
/TESTVAL=0
/MISSING=ANALYSIS
/VARIABLES=diff
/CRITERIA=CI(.95).
split file off.

Simplifying stata script with a loop

I'm trying to create three individual dta files for three different variables that creates a new var for a select dxcode (then collapses it to the id) and assigns every record in the newly created variable a value of 1. Then with these new dta files I will merge them with a larger table. My question is, is there any way to simplify the lines of code below (perhaps with a loop since they seem to all do the same thing)?
*Menin variable***
*****************************
use "C:\ICD9study.dta",clear
keep if inlist(dxcode, "32290")
collapse(max) date, by(bene_id)
gen menin = 1
save "C:\Users\Desktop\temp\menin.dta",replace
*BMenin variable***
***************************************
use "C:\ICD9study.dta",clear
keep if inlist(dxcode, "32090")
collapse(min) date, by(bene_id)
gen Bmenin = 1
save "C:\Users\Desktop\temp\Bmenin.dta",replace
*nonBmenin variable***
*********************************************
use "C:\ICD9study.dta",clear
keep if inlist(dxcode, "04790")
collapse(max) date, by(bene_id)
gen nonBmenin = 1
save "C:\Users\Desktop\temp\nonBmenin.dta",replace
This is a sketch, as nothing in your question is reproducible.
local codes 32290 32090 04790
foreach v in menin Bmenin nonBmenin {
use "C:\ICD9study.dta", clear
gettoken code codes : codes
keep if dxcode == "`code'"
collapse (max) date, by(bene_id)
gen `v' = 1
save "C:\Users\Desktop\temp/`v'.dta", replace
}
Your code produces the maximum date in two cases and the minimum in one. If that is really what you want, you'll need to rewrite the code.
There is plenty of advice about good practice on the site and under the Stata tag wiki.

Open policy agent - explicit logical AND in CI pipeline

I am trying to write a policy which governs administrator username compatibility, which consists of three rules: alphanumeric value, not part of disallowed names (admin, administrator etc.), and longer than 5 characters.
I have found that when using OPA as part of a CI pipeline (which is my use case), the most comfortable solution is to create an object (dictionary) which contains policy results so that I can query them directly. My line inside the CI pipeline will look like this:
for file in rego_directory:
opa eval -i file -d data.json "package_name.policy"
Which doesn't print all of the variables and temporary resources I use inside the rego file (which saves a lot of logs and outputs). In order to make this "policy" object, I have inside my rego file the following pattern:
policy[policy_name] = result {
policy_name :=
...
computations...
...
result := <logical condition>
}
Now, my questions are as following: This doesn't seem like a best practice to me. Is there another way to simply omit the variables from the output? previously I've worked with separate values (i.e. something like this:
default policy_1 = false
default policy_2 = false
policy_1 = {
<logical condition>
}
policy_2 = {
<logical condition>
}
Second question: How do I create an output dictionary (since JSON output of a dictionary is a nice format to work with, after all) which can satisfy multiple conditions? looking back at my example, I can't write something like this:
policy[policy_name] = result {
policy_name :=
...
computations...
...
result := <logical condition>
result := <logical condition 2>
}
Since this is double assignment, which is invalid. Even if I use = instead of :=, it creates conflicts if one term is true and the other is false, and errors are not what I'm looking for (I need boolean answers). How do I create a complex rule whose output I can put inside this dictionary?
Thanks in advance.
TLDR; to answer your questions explicitly:
Now, my questions are as following: This doesn't seem like a best practice to me. Is there another way to simply omit the variables from the output?
There's nothing wrong with having your software query for the value generated by some rule. In fact, rules are the fundamental way of defining abstractions in your policies so that you can decouple policy decision-making (i.e., the logic that produces the decision) from policy enforcement (i.e., the logic/actions taken based on the policy decision.)
The only real alternative is to query for a set of rules inside one or more packages like you showed.
Second question: How do I create an output dictionary (since JSON output of a dictionary is a nice format to work with, after all) which can satisfy multiple conditions? looking back at my example, I can't write something like this:
You're asking how to express Logical OR. In this case, you would create multiple definitions (we call them "incremental definitions" in some places) of the policy rule:
policy[policy_name] = result {
policy_name :=
...
computations...
...
result := <logical condition>
}
policy[policy_name2] = result2 {
policy_name2 :=
...
some other computations...
...
result2 := <some other logical condition>
}
This snippet defines an object (named policy) that maps policy_name to result and policy_name2 to result2. We call this kind of rule a Partial Object. You can also define Partial Sets. When you define a Partial Object, you need to ensure that each key maps to at-most-one value (otherwise you'll get a runtime error.)
Another way of structuring your policy would be to (essentially) define a deny-list using partial sets:
package usernames
deny["username must use alphanumeric characters"] {
re_match("[a-zA-Z0-9]", input.username)
}
deny["username must be at least 5 characters long"] {
count(input.username) < 5
}
deny["username is reserved"] {
reserved_usernames[input.username]
}
reserved_usernames := {"admin", "root"}
Then your CI pipeline can simply query for deny:
opa eval -i input.json 'data.usernames.deny'
The result will contain reasons why the username should not be allowed.

Lua string library choices for finding and replacing text

I'm new to Lua programming, having come over from python to basically make a small addon for world of warcraft for a friend. I'm looking into various ways of finding a section of text from a rather large string of plain text. I need to extract the information from the text that I need and then process it in the usual way.
The string of text could be a number of anything, however the below is what we are looking to extract and process
-- GSL --
items = ["itemid":"qty" ,"itemid":"qty" ,"itemid":"qty" ,]
-- ENDGSL --
We want to strip the whole block of text from a potentially large block of text surrounding it, then remove the -- GSL -- and -- ENDGSL -- to be left with:
items = ["itemdid":"qty …
I've looked into various methods, and can't seem to get my head around any of them.
Anyone have any suggestions on the best method to tackle this problem?
EDIT: Additional problem,
Based on the accepted answer I've changed the code slightly to the following.
function GuildShoppingList:GUILDBANKFRAME_OPENED()
-- Actions to be taken when guild bank frame is opened.
if debug == "True" then self:Print("Debug mode on, guild bank frame opened") end
gslBankTab = GetCurrentGuildBankTab()
gslBankInfo = GetGuildBankText(gslBankTab)
p1 = gslBankInfo:match('%-%- GSL %-%-%s+(.*)%s+%-%- ENDGSL %-%-')
self:Print(p1)
end
The string has now changed slightly the information we are parsing is
{itemid:qty, itemid:qty, itemid:qty, itemid:qty}
Now, this is a string that's being called in p1. I need to update the s:match method to strip the { } also, and iterate over each item and its key seperated by, so I'm left with
itemid:qty
itemid:qty
itemid:qty
itemid:qty
Then I can identify each line individually and place it where it needs to go.
try
s=[[-- GSL --
items = ["itemid":"qty" ,"itemid":"qty" ,"itemid":"qty" ,]
-- ENDGSL --]]
print(s:match('%-%- GSL %-%-%s+(.*)%s+%-%- ENDGSL %-%-'))
The key probably is that - is a pattern modifier that needs quoting if you want a literal hyphen. More info on patterns in the Lua Reference Manual, chapter 5.4.1
Edit:
To the additional problem of looping through keys of what is almost an array, you could do 2 things:
Either loop over it as a string, assuming both key and quantity are integers:
p="{1:10, 2:20, 3:30}"
for id,qty in p:gmatch('(%d+):(%d+)') do
--do something with those keys:
print(id,qty)
end
Or slightly change the string, evaluate it as a Lua table:
p="{1:10, 2:20, 3:30}"
p=p:gsub('(%d+):','[%1]=') -- replace : by = and enclose keys with []
t=loadstring('return '..p)() -- at this point, the anonymous function
-- returned by loadstring get's executed
-- returning the wanted table
for k,v in pairs(t) do
print(k,v)
end
If the formats of keys or quantities is not simply integer, changing it in the patterns should be trivial.

Resources