Write scale/nested conversion with ASAMMDF - asammdf

I am using this snippet in order to create a mf4 file with a value to text table, found in the examples from asammdf's github.
vals = 5
conversion = {
'val_{}'.format(i): i
for i in range(vals)
}
conversion.update(
{
'text_{}'.format(i): 'key_{}'.format(i).encode('ascii')
for i in range(vals)
}
)
sig = Signal(
np.arange(cycles, dtype=np.uint32) % 30,
t,
name='Channel_value_to_text',
conversion=conversion,
comment='Value to text channel',
)
sigs.append(sig)
mdf.append(sigs, comment='arrays', common_timebase=True)
Is there a way to create a table with ##TX blocks and also ##CC blocks?(in order to simulate a scale conversion)
Thank you!

If anyone needs it, I found the answer and it was simpler than expected.
Create another conversion (i.e conversion2) in the same manner as the first one, then reassign the value of one of the references to it.
conversionBlock = from_dict(conversion)
conversionBlock.referenced_blocks["text_4"] = from_dict(conversion2)

Related

QgsField won't accept parameter typeName

I'm trying to create new vector layer with the same fields as contained in original layer.
original_layer_fields_list = original_layer.fields().toList()
new_layer = QgsVectorLayer("Point", "new_layer", "memory")
pr = new_layer.dataProvider()
However, when I try:
for fld in original_layer_fields_list:
type_name = fld.typeName()
pr.addAttributes([QgsField(name = fld.name(), typeName = type_name)])
new_layer.updateFields()
QgsProject.instance().addMapLayer(new_layer)
I get a layer with no fields in attribute table.
If I try something like:
for fld in original_layer_fields_list:
if fld.type() == 2:
pr.addAttributes([QgsField(name = fld.name(), type = QVariant.Int)])
new_layer.updateFields()
QgsProject.instance().addMapLayer(new_layer)
... it works like charm.
Anyway ... I'd rather like the first solution to work in case if one wants to automate the process and not check for every field type and then find an appropriate code. Besides - I really am not able to find any documentation about codes for data types. I managed to find this post https://gis.stackexchange.com/questions/353975/get-only-fields-with-datatype-int-in-pyqgis where in comments Kadir pointed on this sourcecode (https://codebrowser.dev/qt5/qtbase/src/corelib/kernel/qvariant.h.html#QVariant::Type).
I'd really be thankful for any kind of direction.

Salesforce trigger-Not able to understand

Below is the code written by my collegue who doesnt work in the firm anymore. I am inserting records in object with data loader and I can see success message but I do not see any records in my object. I am not able to understand what below trigger is doing.Please someone help me understand as I am new to salesforce.
trigger DataLoggingTrigger on QMBDataLogging__c (after insert) {
Map<string,Schema.RecordTypeInfo> recordTypeInfo = Schema.SObjectType.QMB_Initial_Letter__c.getRecordTypeInfosByName();
List<QMBDataLogging__c> logList = (List<QMBDataLogging__c>)Trigger.new;
List<Sobject> sobjList = (List<Sobject>)Type.forName('List<'+'QMB_Initial_Letter__c'+'>').newInstance();
Map<string, QMBLetteTypeToVfPage__c> QMBLetteTypeToVfPage = QMBLetteTypeToVfPage__c.getAll();
Map<String,QMBLetteTypeToVfPage__c> mapofLetterTypeRec = new Map<String,QMBLetteTypeToVfPage__c>();
set<Id>processdIds = new set<Id>();
for(string key : QMBLetteTypeToVfPage.keyset())
{
if(!mapofLetterTypeRec.containsKey(key)) mapofLetterTypeRec.put(QMBLetteTypeToVfPage.get(Key).Letter_Type__c, QMBLetteTypeToVfPage.get(Key));
}
for(QMBDataLogging__c log : logList)
{
Sobject logRecord = (sobject)log;
Sobject QMBLetterRecord = new QMB_Initial_Letter__c();
if(mapofLetterTypeRec.containskey(log.Field1__c))
{
string recordTypeId = recordTypeInfo.get(mapofLetterTypeRec.get(log.Field1__c).RecordType__c).isAvailable() ? recordTypeInfo.get(mapofLetterTypeRec.get(log.Field1__c).RecordType__c).getRecordTypeId() : recordTypeInfo.get('Master').getRecordTypeId();
string fieldApiNames = mapofLetterTypeRec.containskey(log.Field1__c) ? mapofLetterTypeRec.get(log.Field1__c).FieldAPINames__c : '';
//QMBLetterRecord.put('Letter_Type__c',log.Name);
QMBLetterRecord.put('RecordTypeId',tgh);
processdIds.add(log.Id);
if(string.isNotBlank(fieldApiNames) && fieldApiNames.contains(','))
{
Integer i = 1;
for(string fieldApiName : fieldApiNames.split(','))
{
string logFieldApiName = 'Field'+i+'__c';
fieldApiName = fieldApiName.trim();
system.debug('fieldApiName=='+fieldApiName);
Schema.DisplayType fielddataType = getFieldType('QMB_Initial_Letter__c',fieldApiName);
if(fielddataType == Schema.DisplayType.Date)
{
Date dateValue = Date.parse(string.valueof(logRecord.get(logFieldApiName)));
QMBLetterRecord.put(fieldApiName,dateValue);
}
else if(fielddataType == Schema.DisplayType.DOUBLE)
{
string value = (string)logRecord.get(logFieldApiName);
Double dec = Double.valueOf(value.replace(',',''));
QMBLetterRecord.put(fieldApiName,dec);
}
else if(fielddataType == Schema.DisplayType.CURRENCY)
{
Decimal decimalValue = Decimal.valueOf((string)logRecord.get(logFieldApiName));
QMBLetterRecord.put(fieldApiName,decimalValue);
}
else if(fielddataType == Schema.DisplayType.INTEGER)
{
string value = (string)logRecord.get(logFieldApiName);
Integer integerValue = Integer.valueOf(value.replace(',',''));
QMBLetterRecord.put(fieldApiName,integerValue);
}
else if(fielddataType == Schema.DisplayType.DATETIME)
{
DateTime dateTimeValue = DateTime.valueOf(logRecord.get(logFieldApiName));
QMBLetterRecord.put(fieldApiName,dateTimeValue);
}
else
{
QMBLetterRecord.put(fieldApiName,logRecord.get(logFieldApiName));
}
i++;
}
}
}
sobjList.add(QMBLetterRecord);
}
if(!sobjList.isEmpty())
{
insert sobjList;
if(!processdIds.isEmpty()) DeleteDoAsLoggingRecords.deleteTheProcessRecords(processdIds);
}
Public static Schema.DisplayType getFieldType(string objectName,string fieldName)
{
SObjectType r = ((SObject)(Type.forName('Schema.'+objectName).newInstance())).getSObjectType();
DescribeSObjectResult d = r.getDescribe();
return(d.fields.getMap().get(fieldName).getDescribe().getType());
}
}
You might be looking in the wrong place. Check if there's an unit test written for this thing (there should be one, especially if it's deployed to production), it should help you understand how it's supposed to be used.
You're inserting records of QMBDataLogging__c but then it seems they're immediately deleted in DeleteDoAsLoggingRecords.deleteTheProcessRecords(processdIds). Whether whatever this thing was supposed to do succeeds or not.
This seems to be some poor man's CSV parser or generic "upload anything"... that takes data stored in QMBDataLogging__c and creates QMB_Initial_Letter__c out of it.
QMBLetteTypeToVfPage__c.getAll() suggests you could go to Setup -> Custom Settings, try to find this thing and examine. Maybe it has some values in production but in your sandbox it's empty and that's why essentially nothing works? Or maybe some values that are there are outdated?
There's some comparison if what you upload into Field1__c can be matched to what's in that custom setting. I guess you load some kind of subtype of your QMB_Initial_Letter__c in there. Record Type name and list of fields to read from your log record is also fetched from custom setting based on that match.
Then this thing takes what you pasted, looks at the list of fields in from the custom setting and parses it.
Let's say the custom setting contains something like
Name = XYZ, FieldAPINames__c = 'Name,SomePicklist__c,SomeDate__c,IsActive__c'
This thing will look at first record you inserted, let's say you have the CSV like that
Field1__c,Field2__c,Field3__c,Field4__c
XYZ,Closed,2022-09-15,true
This thing will try to parse and map it so eventually you create record that a "normal" apex code would express as
new QMB_Initial_Letter__c(
Name = 'XYZ',
SomePicklist__c = 'Closed',
SomeDate__c = Date.parse('2022-09-15'),
IsActive__c = true
);
It's pretty fragile, as you probably already know. And because parsing CSV is an art - I expect it to absolutely crash and burn when text with commas in it shows up (some text,"text, with commas in it, should be quoted",more text).
In theory admin can change mapping in setup - but then they'd need to add new field anyway to the loaded file. Overcomplicated. I guess somebody did it to solve issue with Record Type Ids - but there are better ways to achieve that and still have normal CSV file with normal columns and strong type matching, not just chucking everything in as strings.
In theory this lets you have "jagged" csv files (row 1 having 5 fields, row 2 having different record type and 17 fields? no problem)
Your call whether it's salvageable or you'd rather ditch it and try normal loading of QMB_Initial_Letter__c records. (get back to your business people and ask for requirements?) If you do have variable number of columns at source - you'd need to standardise it or group the data so only 1 "type" of records (well, whatever's in that "Field1__c") goes into each file.

TabularAdapter customization/notifications?

Thanks to another user here on SO (Warren Weckesser), I found a nice way to format my TabularAdapter columns. There are some other customizations I'd like to accomplish, so I thought I'd put this out to SO to see if I can get more help.
The following code puts up a couple of TabularAdapter tables in the format that I want to use. What I'd like to be able to do are 2 things:
I'd like to set the first column as non-editable. I've found how to set a row to non-editable, but not a column -- is this possible?
What I'd really like (even more than #1 above) it to get a notification if one of the values in any of my columns changes! I've heard that there are some 'tweaks' that can be done with numpy arrays to accomplish this, but I'm way too inexperienced yet to pull this off. Is there any TraitsAdapter mentods that might be used to accomplish this feat?
Here's my code so far (thanks to Warren's modifications):
from traits.api import HasTraits, Array, Str
from traitsui.api import View, Item, TabularEditor
from traitsui.tabular_adapter import TabularAdapter
from numpy import dtype
test_dtype = dtype([('Integer#1', 'int'),
('Integer#2', 'int'),
('Float', 'float')])
class TestArrayAdapter1(TabularAdapter):
columns = [('Col1 #', 0), ('Col2', 1), ('Col3', 2)]
even_bg_color = 0xf4f4f4 # very light gray
width = 125
def get_format(self, object, name, row, column):
formats = ['%d', '%d', '%.4f']
return formats[column]
class TestArrayAdapter2(TabularAdapter):
columns = [('Col1 #', 0), ('Col2', 1), ('Col3', 2)]
even_bg_color = 0xf4f4f4 # very light gray
width = 125
object_0_format = Str("%d")
object_1_format = Str("%d")
object_2_format = Str("%.4f")
class Test(HasTraits):
test_array = Array(dtype=test_dtype)
view = \
View(
Item(name='test_array', show_label=False,
editor=TabularEditor(adapter=TestArrayAdapter1())),
Item(name='test_array', show_label=False,
editor=TabularEditor(adapter=TestArrayAdapter2())),
)
test = Test()
test.test_array.resize(5, refcheck=False)
test.configure_traits()
For your item #2, after talking to Enthought folks, I confirmed there isn't an official way to do this yet but:
I created a ticket for it: https://github.com/enthought/traitsui/issues/387
I worked around the issue, by keeping a handle on the ArrayAdapter, subclass it, and override the set_text method like so:
.
class NotifyingArrayAdapter(ArrayAdapter):
value_changed = Event
def set_text(self, object, trait, row, column, text):
super(NotifyingArrayAdapter, self).set_text(object, trait, row,
column, text)
self.value_changed = True
That way, I can just listen to the value_changed event, and do what I need with it.
You can get fancier, and make the event be a more complex object, for example storing information about the old/new values, and the row and column changed:
class ArrayAdapterEvent(HasStrictTraits):
row = Int
column = Int
old = Str
new = Str
class NotifyingArrayAdapter(ArrayAdapter):
value_changed = Event(Instance(ArrayAdapterEvent))
def set_text(self, object, trait, row, column, text):
old = self.get_text(object, trait, row, column)
super(NotifyingArrayAdapter, self).set_text(object, trait, row,
column, text)
event = ArrayAdapterEvent(old=old, new=text, row=row, column=column)
self.value_changed = event

String category names with Wisp scala plotting library

I am trying to plot bars for String categories with Wisp. In other words, I have a string (key) and a count (value) in my repl and I want to have a bar chart of the count versus the key.
I don't know if something easy exists. I went as far as the following hack:
val plot = bar(topWords.map(_._2).toList)
val axisType: com.quantifind.charts.highcharts.AxisType.Type = "category"
val newPlot = plot.copy(xAxis = plot.xAxis.map {
axisArray => axisArray.map { _.copy(axisType = Option(axisType),
categories = Option(topWords.map(_._1))) }
})
but I don't know if it works because I don't find a way to visualize newPlot. Or maybe adding a method to the Wisp source implementing the above is the way to go?
Thanks for any help.
PS : I don't have the reputation to create the wisp tag, but I would have...
Update: in wisp 0.0.5 or later this will be supported directly:
column(List(("alpha", 1), ("omega", 5), ("zeta", 8)))
====
Thanks for trying out wisp (I am the author). I think a problem that you may have encountered is by naming your variable plot, you overrode access to the plot method defined by Highcharts, which allows you to plot any Highchart object. (now that I see it, naming your plot "plot" is an unfortunately natural thing to do!)
I'm filing this as a github issue, as category names are very common.
This works for me. I used column for vertical bars:
import com.quantifind.charts.Highcharts._
val topWords = Array(("alpha", 14), ("beta", 23), ("omega", 18))
val numberedColumns = column(topWords.map(_._2).toList)
val axisType: com.quantifind.charts.highcharts.AxisType.Type = "category"
val namedColumns = numberedColumns.copy(xAxis = numberedColumns.xAxis.map {
axisArray => axisArray.map { _.copy(axisType = Option(axisType),
categories = Option(topWords.map(_._1))) }
})
plot(namedColumns)
producing this visualization:
(You could also consider creating one bar at a time, and use the legend to name them)

Copy range with conditional formatting

I have a range with Conditional Formatting in an existing Excel file. I used EPPlus to copy that range to a new sheet, then I found the conditional formatting was missing.
Is there any way to copy range with conditional formatting using EPPlus?
I found a solution for this. I did not test it on all formattingRuleTypes. (Only needed 2 of them for the moment)
In my application i have 1 template row for each sheet.
var formatList = fromSheet.ConditionalFormatting.ToList();
foreach (var cf in formatList)
{
// sourceRow is the row containing the formatting
if (cf.Address.Start.Row == sourceRow )
{
IExcelConditionalFormattingRule rule = null;
switch (cf.Type)
{
case OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType.GreaterThan:
rule = dest.ConditionalFormatting.AddGreaterThan();
break;
case OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType.GreaterThanOrEqual:
rule = dest.ConditionalFormatting.AddGreaterThanOrEqual();
break;
case OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType.LessThan:
rule = dest.ConditionalFormatting.AddLessThan();
break;
case OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType.LessThanOrEqual:
rule = dest.ConditionalFormatting.AddLessThanOrEqual();
break;
default:
break;
}
rule.Style.Fill = cf.Style.Fill;
rule.Style.Border = cf.Style.Border;
rule.Style.Font = cf.Style.Font;
rule.Style.NumberFormat = cf.Style.NumberFormat;
// I have no clue why the Formula property is not included in the IExcelConditionalFormattingRule interface. So I needed to cast this.
((ExcelConditionalFormattingRule)rule).Formula = ((ExcelConditionalFormattingRule)cf).Formula;
((ExcelConditionalFormattingRule)rule).Formula2 = ((ExcelConditionalFormattingRule)cf).Formula2;
// Calculate the new address for the formatting. This will be different in your case
var adr = new ExcelAddress( dest.Start.Row , cf.Address.Start.Column -1 , dest.Start.Row, cf.Address.Start.Column -1 + cf.Address.Columns -1 );
rule.Address = adr;
I have no clue why the Formula property is not included in the IExcelConditionalFormattingRule interface. So I needed to cast this.
To add to the answer of Luc Wuyts (I can't comment yet due to limited reputation):
// I have no clue why the Formula property is not included in the IExcelConditionalFormattingRule interface. So I needed to cast this.
((ExcelConditionalFormattingRule)rule).Formula = ((ExcelConditionalFormattingRule)cf).Formula;
((ExcelConditionalFormattingRule)rule).Formula2 = ((ExcelConditionalFormattingRule)cf).Formula2;
Some conditional formatting do not have the Formula-options. This cast will work, but applying the Formula properties to conditional formatting options which do not require it will have unforeseen results. Eg. the ConditionalFormatting.AddContainsBlanks() does not require Formula properties, and adding them might mess up the conditional formatting. A better approach is to check the type, and add the formula's only when required.
I had a similar problem, the only way I found to inspect, change or delete a conditional format of a cell or range is looking at the openxml specs. The conditional format is stored in the worksheet, with the range under the attribute sqref. So you can edit that range or add a new.
For example:
DIM p As New ExcelPackage(New FileInfo(ExlReportPath), True)
Dim ws As ExcelWorksheet = p.Workbook.Worksheets(ExlSheetName)
'--Find Node "worksheet" (1 in my case) , Find all Child Nodes "conditionalFormatting" (5 to 11 in my test)
Print.Debug(ws.WorksheetXml.ChildNodes(1).ChildNodes(5).Name)
'--You get: conditionalFormatting
'--Now you can inspect the range:
Print.Debug(ws.WorksheetXml.ChildNodes(1).ChildNodes(5).Attributes("sqref").Value)
'--Will give you the cell address that this formatting applies to example: "D11:D15"
'--you can change delete or add new range if you want, below I add F11:F15
ws.WorksheetXml.ChildNodes(1).ChildNodes(5).Attributes("sqref").Value="D11:D15 F11:F15"
'--You can inspect the rule itself in the InnerXml also...
If you need more details of the markup, google Wouter van Vugt, "Open XML The markup explained". I found it useful and the full document was online (free).
If you find an easier way please post it.
Regards