Skip to content

Commit

Permalink
Pull request to merge changes (#3)
Browse files Browse the repository at this point in the history
* Added a function, extract_tree, to
extract the full tree of ONC location codes.  Once loaded, the locations
can be navigated with tab completion

* Added a check to see if any files returned.
If not, returns an error message

* Fixed a bug where "getTree" was improperly parsed
by util.param

* Fixed a bug where .mat files were
not properly downloaded
  • Loading branch information
slonimer committed Mar 8, 2023
1 parent ac8e78b commit 245b20f
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 6 deletions.
4 changes: 3 additions & 1 deletion onc/+onc/DataProductFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@
else
this.fileSize = strlength(response.Body.Data);
end
saveResult = util.save_as_file(response, outPath, filename, overwrite);
%save_as_file doesn't work properly! Use urlwrite instead
[~, saveResult] = urlwrite(uri.EncodedURI,fullfile(outPath, filename));
%saveResult = util.save_as_file(response, outPath, filename, overwrite);
this.downloadingTime = round(duration, 3);

% log status
Expand Down
14 changes: 13 additions & 1 deletion onc/+onc/OncDiscovery.m
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,19 @@
% - method: ([char]) Method to request, one of {'get', 'getTree'}
%
% Returns: ([struct]) List of elements found
[method] = util.param(varargin, 'method', 'get');

%BUG: if varargin = {'method','getTree'}, not actually using getTree...
%[method] = util.param(varargin, 'method', 'get');
if nargin>3
if strcmpi(varargin{1},'method') & strcmpi(varargin{2},'getTree')
[method] = util.param(varargin, 'method', 'getTree');
else
[method] = util.param(varargin, 'method', 'get');
end
else
[method] = util.param(varargin, 'method', 'get');
end

url = this.serviceUrl(service);

filters = util.sanitize_filters(filters);
Expand Down
136 changes: 136 additions & 0 deletions onc/+util/extract_tree.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
function tree = extract_tree(this)
%Code to extract the Search Tree, and all of the "location codes"
%Can run with no input and get the entire tree, or give it a starting point
%further down the tree. The codes for these can be found in Search Tree
%Maintenance. These codes can then be used for input to onc.getDevices by
%providing the locationCodes
%
% Ex. 1 : All ONC locations
% tree = extract_tree
% Ex. 2: Just the Salish Sea
% tree = extract_tree('SAL')
%
% Example usage once extracted:
% >> my_token = '17x081dx-x36x-48c1-x930-01b2d1697x83'; % Found in your ONC profile
% >> onc = Onc(my_token);
% Then, type:
% >> onc.tree
% Then click the "tab" key to see all options, and select one. Continue to
% add periods and select tab-completion until you've narrowed down your
% desired site.
% >> onc.tree.Pacific.Salish_Sea.Baynes_Sound.Baynes_Sound_Mooring.L2mbss.aa_info


%if nargin == 0
filters = {'locationCode', 'ONC'};
%else
% filters = {'locationCode', varargin{1}};
%end

%filters = {'locationCode', %'ARCT','dateFrom','2019-07-27T00:00:00.000Z','dateTo','2019-08-27T00:00:00.000Z'}; % Not compatible with getTree
result = this.getLocationHierarchy(filters);
%onc.print(result);
%To get this to work, I had to edit the code in OncDiscovery L118 to
%actually use the "getTree" method... was not properly working, and was
%continuing to use the "get" method

%GOAL: Create a tab/auto-complete dictionary for reference ti easily scan through the
%search tree directory and get site and device codes

field{1,1} = result.locationName; %Arctic
%tree.(field{1,1}) = field{1,1};

%Info for the top Level
struct_set_info{1} = 'locationCode';
struct_set_info{2} = result.locationCode;
struct_set_info{3} = 'locationName';
struct_set_info{4} = result.locationName;
struct_set_info{5} = 'hasDeviceData';
struct_set_info{6} = result.hasDeviceData;
struct_set_info{7} = 'description';
struct_set_info{8} = result.description;
struct_set{1} = 'aa_info';
struct_set{2} = struct(struct_set_info{:});
%Children of the top Level:
for ii=1:size(result.children,1)
treeLocationName = strjoin(strsplit(result.children(ii).locationName,' '),'');
treeLocationName = strjoin(strsplit(treeLocationName,'-'),'');
%result.children(ii).locationName = strjoin(strsplit(result.children(ii).locationName,' '),'');
%result.children(ii).locationName = strjoin(strsplit(result.children(ii).locationName,'-'),'');
struct_set{2*(ii+1) - 1} = treeLocationName;
struct_set{2*(ii+1)} = '';
end
tree = struct(struct_set{:});


%Enter a recursive loop to construct the tree:
tree = probe_children(result.children, tree);


end


function tree = probe_children(input, tree)
%This is a recursive loop to get details about each child

for ii=1:size(input,1)

%Clear variables:
clear struct_set struct_set_info

%Info for the top Level
struct_set_info{1} = 'locationCode';
struct_set_info{2} = input(ii).locationCode;
struct_set_info{3} = 'locationName';
struct_set_info{4} = input(ii).locationName;
struct_set_info{5} = 'hasDeviceData';
struct_set_info{6} = input(ii).hasDeviceData;
struct_set_info{7} = 'description';
struct_set_info{8} = input(ii).description;
struct_set{1} = 'aa_info';
struct_set{2} = struct(struct_set_info{:});
%Children of the top Level:
for jj=1:size(input(ii).children,1)
%location_name = input(ii).children(jj).locationName;
treeLocationName = strjoin(strsplit(input(ii).children(jj).locationName,' '),'_');
treeLocationName = strjoin(strsplit(treeLocationName,'-'),'_');
treeLocationName = strjoin(strsplit(treeLocationName,'('),'_');
treeLocationName = strjoin(strsplit(treeLocationName,')'),'_');
treeLocationName = strjoin(strsplit(treeLocationName,'.'),'_');
treeLocationName = strjoin(strsplit(treeLocationName,''''),'_');
treeLocationName = strjoin(strsplit(treeLocationName,'/'),'_');

%Split and check to see if the first character is a number
split_parts = strsplit(treeLocationName,'_');
if isempty(split_parts{1})
for kk=1:length(split_parts)-1
split_parts{kk} = split_parts{kk+1};
end
split_parts = split_parts(1:end-1);

elseif ~isnan(str2double(split_parts{1}(1)))
if length(split_parts)>1
temp = split_parts{1};
split_parts{1} = split_parts{2};
split_parts{2} = temp;
else
split_parts{1} = ['L',split_parts{1}];
end
end
treeLocationName = strjoin(split_parts,'_');

struct_set{2*(jj+1) - 1} = treeLocationName;
struct_set{2*(jj+1)} = '';
end
fieldnames = fields(tree);
tree.(fieldnames{ii+1}) = struct(struct_set{:});

tree.(fieldnames{ii+1}) = probe_children(input(ii).children, tree.(fieldnames{ii+1}));
%input(ii).children = probe_children(input(ii).children);



end

end

15 changes: 11 additions & 4 deletions onc/+util/filter_by_extension.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@

% determine the row structure
isStructRow = false;
if ~isempty(results.files)
if isa(results.files(1), 'struct')
isStructRow = true;

if isfield(results,'files')
if ~isempty(results.files)
if isa(results.files(1), 'struct')
isStructRow = true;
end
end

else
error('%s: %s (error ID %d)',results.errors.errorMessage, results.errors.parameter, results.errors.errorCode);
end



% preallocate an array of flags
flags = zeros([n, 1], 'logical');

Expand Down
29 changes: 29 additions & 0 deletions onc/Onc.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
% showInfo - Print verbose comments for debugging
% outPath - Output path for downloaded files
% timeout - Number of seconds before a request to the API is canceled
% tree - ONC data search tree
%
% ONC Methods:
%
Expand Down Expand Up @@ -53,6 +54,7 @@
showInfo = false % Print verbose comments for debugging
outPath = 'output' % Output path for downloaded files
timeout = 60 % Number of seconds before a request to the API is canceled
tree = [] % ONC Data Search Tree
end

properties (SetAccess = private)
Expand Down Expand Up @@ -102,6 +104,32 @@
if not(this.production)
this.baseUrl = 'https://qa.oceannetworks.ca/';
end

%If a search tree file exists, load it. If not, generate and save one
[source_path,~,~] = fileparts(which('Onc.m'));
tree_path = fullfile(source_path,'onc_tree.mat');
if ~exist(tree_path,'file')
fprintf('\n Loading ONC search tree. Accessible with onc.tree \n');
tree = util.extract_tree(this);
save(tree_path, 'tree')
elseif exist(tree_path,'file')
%Check if it's more than a week old. If so, update it:
dir_files = dir(source_path);
filenames = {dir_files(:).name};
[~,idx] = ismember('onc_tree.mat',filenames);
treeFileDate = dir_files(idx).datenum;
if now - treeFileDate > 7
fprintf('\n Updating ONC search tree. Accessible with onc.tree \n');
tree = util.extract_tree(this);
save(tree_path, 'tree')
end
end
temp = load(tree_path);
this.tree = temp.tree;
%These codes can then be used for input to onc.getDevices by
%providing the locationCodes


end

function print(~, data)
Expand Down Expand Up @@ -130,6 +158,7 @@ function print(~, data)
dt.Format = 'yyyy-MM-dd''T''HH:mm:ss.SSS''Z''';
text = sprintf('%s', char(dt));
end

end

methods (Access = private)
Expand Down

0 comments on commit 245b20f

Please sign in to comment.