Silent exporting of globals using %GOF in Caché - intersystems-cache

I would like to know if it's possible to use "^%GOF" without user interaction. I'm using Caché 2008. ^%GO isn't an option as it's to slow. I'm using input from a temporary file for automatically answer the questions, but it can fail (rarely happens).
I couldn't find the routine of this utility in %SYS. Where is it located?
Thanks,
Answer: Using "%SYS.GlobalQuery:NameSpaceList" to get list of globals (system globals excluding).
Set Rset = ##class(%ResultSet).%New("%SYS.GlobalQuery:NameSpaceList")
d Rset.Execute(namespace, "*", 0)
s globals=""
while (Rset.Next()){
s globalName=Rset.Data("Name")_".gbl"
if (globals=""){
s globals = globalName
}else{
s globals = globals_","_globalName
}
d ##class(%Library.Global).Export(namespace, globals, "/tmp/export.gof", 7)
The only drawback is that if you have a namespace with concatination of globals exceeding the maximum allowed for a global entry, the program crashes. You should then split the globals list.

I would recommend that you look at the %Library.Global() class with output format 7.
classmethod Export(Nsp As %String = $zu(5), ByRef GlobalList As %String, FileName As %String, OutputFormat As %Integer = 5, RecordFormat As %String = "V", qspec As %String = "d", Translation As %String = "") as %Status
Exports a list of globals GlobalList from a namespace Nsp to FileName using OutputFormat and RecordFormat.
OutputFormat can take the values below:
1 - DTM format
3 - VAXDSM format
4 - DSM11 format
5 - ISM/Cache format
6 - MSM format
7 - Cache Block format (%GOF)
RecordFormat can take the values below:
V - Variable Length Records
S - Stream Data
You can find it in the class documentation here: http://docs.intersystems.com/cache20082/csp/documatic/%25CSP.Documatic.cls
I've never used it, it looks like it would do the trick however.

export your global to file
d $system.OBJ.Export("myGlobal.GBL","c:\global.xml")
import global from your file
d $system.OBJ.Load("c:\global.xml")
Export items as an XML file
The extension of the items determine what
type they are, they can be one of:
CLS - classes
CSP - Cache Server Pages
CSR - Cache Rule files
MAC - Macro routines
INT - None macro routines
BAS - Basic routines
INC - Include files
GBL - Globals
PRJ - Studio Projects
OBJ - Object code
PKG - Package definition
If you wish to export multiple classes then separate then with commas or
pass the items("item")="" as an array or use wild cards.
If filename is empty then it will export to the current device.
link to docbook
edit: adding "-d" as qspec value will suppress the terminal output of the export. If you want to use this programmtically, it might get in the way.

And just for completeness' sake:
SAMPLES>s IO="c:\temp\test.gof"
SAMPLES>s IOT="RMS"
SAMPLES>s IOPAR="WNS"
SAMPLES>s globals("Sample.PersonD")=""
SAMPLES>d entry^%GOF(.globals)
SAMPLES>
-> results in c:\temp\test.gof having the export. You can define up to 65435 globals in you array (named globals in this example)
But I would recommend you go with DAiMor's answer as this is the more 'modern' way.

To avoid maximum string error, you should use subscripts instead of comma delimited string:
Set Rset = ##class(%ResultSet).%New("%SYS.GlobalQuery:NameSpaceList")
d Rset.Execute(namespace, "*", 0)
while (Rset.Next()) {
s globals(Rset.Data("Name"))="" // No need for _".gbl" in recent Cache
}
d ##class(%Library.Global).Export(namespace, .globals, "/tmp/export.gof", 7) // Note dot before globals

Related

SPARQL how to make DAY/MONTH always return 2 digits

I have a datetime in my SPARQL-query that I want to transform to a date.
Therefore I do:
BIND(CONCAT(YEAR(?dateTime), "-",MONTH(?dateTime), "-", DAY(?dateTime)) as ?date)
This part of code works but returns for example 2022-2-3, I want it to be 2022-02-03. If the dateTime is 2022-11-23, nothing should change.
You can take the integers you get back from the YEAR, MONTH, and DAY functions and pad them with the appropriate number of zeros (after turning them into strings):
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT * WHERE {
BIND(2022 AS ?yearInt) # this would come from your YEAR(?dateTime) call
BIND(2 AS ?monthInt) # this would come from your MONTH(?dateTime) call
BIND(13 AS ?dayInt) # this would come from your DAY(?dateTime) call
# convert to strings
BIND(STR(?yearInt) AS ?year)
BIND(STR(?monthInt) AS ?month)
BIND(STR(?dayInt) AS ?day)
# pad with zeros
BIND(CONCAT("00", ?year) AS ?paddedYear)
BIND(CONCAT("0000", ?month) AS ?paddedMonth)
BIND(CONCAT("00", ?day) AS ?paddedDay)
# extract the right number of digits from the padded strings
BIND(SUBSTR(?paddedYear, STRLEN(?paddedYear)-3) AS ?fourDigitYear)
BIND(SUBSTR(?paddedDay, STRLEN(?paddedDay)-1) AS ?twoDigitDay)
BIND(SUBSTR(?paddedMonth, STRLEN(?paddedMonth)-1) AS ?twoDigitMonth)
# put it all back together
BIND(CONCAT(?fourDigitYear, "-", ?twoDigitMonth, "-", ?twoDigitDay) as ?date)
}
#gregory-williams gives a portable answer. An alternative is functions from F&O (XPath and XQuery Functions and Operators 3.1) "fn:format-...."
I'm not sure of the coverage in various triplestores - Apache Jena provides fn:format-number, which is needed for the question, but not fn-format-dateTime etc
See
https://www.w3.org/TR/xpath-functions-3/#formatting-the-number
https://www.w3.org/TR/xpath-functions-3/#formatting-dates-and-times
For example:
fn:format-number(1,"000") returns the string "001".
Apache Jena also has a local extension afn:sprintf using the C or Java syntax of sprintf:
afn:sprintf("%03d", 1) returns "001".

Stata: Unable to return Global Macro of Filename

I am using filelist to generate a dataframe of each folder and the files contained in it. I would like to save each folder name and file name with an observation number x to be able to pull their names out later.
ssc install filelist
filelist
//Save each file's name and corresponding folder:
forvalues x = 1 / `=_N' { //for every row in the filelist dataframe shown
local file = filename[`x']
global folder_`x' dirname[`x'] //save the folder name as folder_i, i = 1, 2, ... _N
global file_`x' filename[`x'] //save the file name as file_i, i = 1, 2, ... _N
}
global filecount `=_N'
This runs smoothly, and if I was to run di $file_2, for instance, it would produce the given filename. The issue I have is that then when I try to use this and access these Globals later on, they appear to have saved the "filename[`x']" rather than the actual filename. For instance, if I run:
import excel "InterestRates.xlsx", sheet("US") firstrow
di $file_2
Then I get the error filename not found. I have tried changing up my `' and "" and {} in many different ways, and I still cannot seem to get this to reference the actual filename. Any help would be greatly appreciated!
There are two ways to assign local or global macros: with an equal sign, and without. If it is assigned without an equal sign, the content will be stored as it is. With an equal sign, the content will be evaluated first.
clear
input str8 filename
"file.dta"
end
global file_1 filename[1]
global file_2 = filename[1]
di "$file_1"
di "$file_2"
Result:
. di "$file_1"
filename[1]
. di "$file_2"
file.dta
Here is a slight alteration to Wouter's code which still gives me the error:
cd [MY_PATH_HERE]
ssc install filelist
filelist
//Save each file's name and corresponding folder:
forvalues x = 1 / `=_N' { //for every row in the filelist dataframe shown
local file = filename[`x']
global folder_`x' dirname[`x'] //save the folder name as folder_i, i = 1, 2, ... _N
global file_`x' filename[`x'] //save the file name as file_i, i = 1, 2, ... _N
}
export excel test.xlsx, firstrow(var)
import excel different.xlsx, firstrow clear
di $file_1
This then still produces the filename not found error as before. It works fine when telling Stata to import the same Excel (test.xlsx) you just saved, but if you import a different Excel, it causes issues. I don't understand why this is the case though if you are saving it as a global macro.

dicom header personal information conversion to a .txt file

I have a series of DICOM Images which I want to anonymize, I found few Matlab codes and some programs which do the job, but none of them export a .txt file of removed personal information. I was wondering if there is a function which can also save removed personal information of a DICOM images in .txt format for features uses. Also, I am trying to create a table which shows the corresponding new images ID to their real name.(subjects real name = personal-information-removed image ID)
Any thoughts?
Thanks for considering my request!
I'm guessing you only want to output to your text file the fields that are changed by anonymization (either modified, removed, or added). First, you may want to modify some dicomanon options to reduce the number of changes, in particular passing the arguments 'WritePrivate', true to ensure private extensions are kept.
First, you can perform the anonymization, saving structures of pre- and post-anonymization metadata using dicominfo:
preAnonData = dicominfo('input_file.dcm');
dicomanon('input_file.dcm', 'output_file.dcm', 'WritePrivate', true);
postAnonData = dicominfo('output_file.dcm');
Then you can use fieldnames and setdiff to find fields that are removed or added by anonymization, and add them to the post-anonymization or pre-anonymization data, respectively, with a nan value as a place holder:
preFields = fieldnames(preAnonData);
postFields = fieldnames(postAnonData);
removedFields = setdiff(preFields, postFields);
for iField = 1:numel(removedFields)
postAnonData.(removedFields{iField}) = nan;
end
addedFields = setdiff(postFields, preFields);
for iField = 1:numel(addedFields)
preAnonData.(addedFields{iField}) = nan;
end
It will also be helpful to use orderfields so that both data structures have the same ordering for their field names:
postAnonData = orderfields(postAnonData, preAnonData);
Finally, now that each structure has the same fields in the same order we can use struct2cell to convert their field data to a cell array and use cellfun and isequal to find any fields that have been modified by the anonymization:
allFields = fieldnames(preAnonData);
preAnonCell = struct2cell(preAnonData);
postAnonCell = struct2cell(postAnonData);
index = ~cellfun(#isequal, preAnonCell, postAnonCell);
modFields = allFields(index);
Now you can create a table of the changes like so:
T = table(modFields, preAnonCell(index), postAnonCell(index), ...
'VariableNames', {'Field', 'PreAnon', 'PostAnon'});
And you could use writetable to easily output the table data to a text file:
writetable(T, 'anonymized_data.txt');
Note, however, that if any of the fields in the table contain vectors or structures of data, the formatting of your output file may look a little funky (i.e. lots of columns, most of them empty, except for those few fields).
One way to do this is to store the tags before and after anonymisation and use these to write your text file. In Matlab, dicominfo() will read the tags into a structure:
% Get tags before anonymization
tags_before = dicominfo(file_in);
% Anoymize
dicomanon(file_in, file_out); % Need to set tags values where required
% Get tags after anonymization
tags_after = dicominfo(file_out);
% Do something with the two structures
disp(['Patient ID:', tags_before.PatientID ' -> ' tags_after.PatientID]);
disp(['Date of Birth:', tags_before.PatientBirthDate ' -> ' tags_after.PatientBirthDate]);
disp(['Family Name:', tags_before.PatientName.FamilyName ' -> ' tags_after.PatientName.FamilyName]);
You can then write out the before/after fields into a text file. You'd need to modify dicomanon() to choose your own values for the removed fields, since by default they are set to empty.

Saving figure without providing filename [duplicate]

this question about matlab:
i'm running a loop and each iteration a new set of data is produced, and I want it to be saved in a new file each time. I also overwrite old files by changing the name. Looks like this:
name_each_iter = strrep(some_source,'.string.mat','string_new.(j).mat')
and what I#m struggling here is the iteration so that I obtain files:
...string_new.1.mat
...string_new.2.mat
etc.
I was trying with various combination of () [] {} as well as 'string_new.'j'.mat' (which gave syntax error)
How can it be done?
Strings are just vectors of characters. So if you want to iteratively create filenames here's an example of how you would do it:
for j = 1:10,
filename = ['string_new.' num2str(j) '.mat'];
disp(filename)
end
The above code will create the following output:
string_new.1.mat
string_new.2.mat
string_new.3.mat
string_new.4.mat
string_new.5.mat
string_new.6.mat
string_new.7.mat
string_new.8.mat
string_new.9.mat
string_new.10.mat
You could also generate all file names in advance using NUM2STR:
>> filenames = cellstr(num2str((1:10)','string_new.%02d.mat'))
filenames =
'string_new.01.mat'
'string_new.02.mat'
'string_new.03.mat'
'string_new.04.mat'
'string_new.05.mat'
'string_new.06.mat'
'string_new.07.mat'
'string_new.08.mat'
'string_new.09.mat'
'string_new.10.mat'
Now access the cell array contents as filenames{i} in each iteration
sprintf is very useful for this:
for ii=5:12
filename = sprintf('data_%02d.mat',ii)
end
this assigns the following strings to filename:
data_05.mat
data_06.mat
data_07.mat
data_08.mat
data_09.mat
data_10.mat
data_11.mat
data_12.mat
notice the zero padding. sprintf in general is useful if you want parameterized formatted strings.
For creating a name based of an already existing file, you can use regexp to detect the '_new.(number).mat' and change the string depending on what regexp finds:
original_filename = 'data.string.mat';
im = regexp(original_filename,'_new.\d+.mat')
if isempty(im) % original file, no _new.(j) detected
newname = [original_filename(1:end-4) '_new.1.mat'];
else
num = str2double(original_filename(im(end)+5:end-4));
newname = sprintf('%s_new.%d.mat',original_filename(1:im(end)-1),num+1);
end
This does exactly that, and produces:
data.string_new.1.mat
data.string_new.2.mat
data.string_new.3.mat
...
data.string_new.9.mat
data.string_new.10.mat
data.string_new.11.mat
when iterating the above function, starting with 'data.string.mat'

Naming a file in matlab

I currently have this:
[filename, pathname, filterindex] = uiputfile({...
... (various filetypes)
'Disks image.jpg');
if isequal(filename,0) || isequal(pathname,0)
disp('User selected Cancel');
else
disp(['User selected ',fullfile(pathname,filename)]);
end
imwrite(M, 'Disks image.jpg', 'jpg');
disp('Image saved');
end
How would I write for the part currently saying 'Disks image.jpg' a name that is either the current time (given by the following):
dateTime = javaMethod('currentTimeMillis', 'java.lang.System');
Or a name that is a combination of both that and some other specified name (e.g. currentTimeMillis_Diffraction_pattern.jpg)
As I am saving two image files, it would be good if I can name the file by the second method, as it gives an ordered list without having to separate the two images into different file folders.
Using time...........+..........._Diffraction_pattern.extension would be great
Thanks
Not sure why you are using a Java function to get the time, rather than built in Matlab time function. I would just use
dateTimeString = datestr(now, 'yyyy-mm-dd-HH_MM_SS_FFF');
Then concatenate that with whatever name you want to create a file name:
myFileName = [dateTimeString '_withSomeName.jpg'];
imwrite( M, myFileName, 'jpg' );
Note - I think that if you include the .jpg extension on the file, it will automatically be converted by imwrite so you don't need the third argument. Also note that using the FFF format specifier will give you the time down to ms - so it's got the same functionality (and granularity) as your original Java function call, but results in more sensible file names.
If you insist on using the Java function, you need to convert it to Matlab's internal clock - this means something like this (untested):
timeNow = javaMethod('currentTimeMillis', 'java.lang.System');
timeMatlab = timeNow / (1000 * 3600 * 24) + datenum('1 Jan 1970');
dateTimeString = datestr(timeMatlab, 'yyyy-mm-dd-HH_MM_SS');
but why would you do that...
String concatenation can be done like this:
filename=[num2str(dateTime) '_Diffraction_pattern.extension'];
Or using sprintf:
filename=sprintf('%d_Diffraction_pattern.extension',dateTime);