Jump to content
Julian Carr

Converting Scientific Notation to Real

Recommended Posts

Sometimes when you use GetRField() to return a dimension value from a PIO, it returns the value in scientific notation, so a value of 900 (mm) becomes 9e02. You can use Str2Num('9e02') to convert this to a real number, however this does not work in python and produces this error:

 

Type Error. Can't convert 'float' object to str implicitly.

 

Here is a code snippet:

 

perimValue = vs.Str2Num(vs.GetRField( h, 'Space', 'Perim' ))

crit_ = "('Space'.'Perim' = "+ perimValue + ")"

vs.ForEachObject(DoIt, crit_)

 

The equivalent in Vectorscript works OK.

 

Thanks for any ideas.

 

Julian

Share this post


Link to post

Julian,

 

That error message makes me think it is already a Number (type Float) and that the problem is that Python can't convert the float into a string which is the required input of the Str2Num.

 

Perhaps use something like 

 

If Type ( vs.GetRField(.......)) = str then PerimValue=Num2Str(GetRField(.......)) else PerimValue = GetrRField(.......) 

Share this post


Link to post

Well I guess you are correct Pat, and thanks for your reply. It is already a number expressed in scientific notation, but that can't be used in a criteria string. This is the error it gives:

 

Error: Unable to parse Search Criteria.

Database(('Space'.'Perim' = 9e02))

 

so I need a way to change this:

 

perimValue = 9e02

 

to this:

 

perimValue = 900

 

Any ideas on that one?

Share this post


Link to post

Nice try Pat. It still produces an error. It doesn't like the 'f'. Run this snippet to see it:

 

widthValue = '9e02'
format(widthValue, 'f')
vs.Message(widthValue)

Share this post


Link to post

The quotes around the 9e02 are forcing it to a sting instead of a number. Also, the format command needs to be used in conjunction with an assignment (I think).

 

widthValue = 9e02
widthValue = format(widthValue, '.0f')
vs.Message(widthValue)

 

the .0 forces it to zero decimal places. Leave that off and the default is 6 decimal places. OK if you are doing a greater than/less than. Not so good if you are doing an equals.

 

Share this post


Link to post

PS. I really much prefer the mandatory typing of variables in Vectorscript. It makes sure you know what kind of a result you are getting.

 

And I really hate using white space as block delimiters. Being/End are so much easier to read.

 

Overtime i have to work in Python I feel like I am back in Fortran in 1983 and counting columns on a punch card.

 

Share this post


Link to post

I totally agree Pat. Even though Pascal is verbose compared to Python and doesn't have the same community support or external libraries, it requires special knowledge to understand the syntax.

 

Anyway thanks to you I figured a way to do it, though it only works with files in metric units. If you draw a Space, leave it selected the run this script, you will see the desired criteria string:

 

perimValueStr = vs.GetRField( vs.FSActLayer(), 'Space', 'Perim' )
(Flag, perimValue) = vs.ValidNumStr(perimValueStr) #convert notation string to real number
perimValueStr = format(perimValue, '.4f') #convert real back to string to 4 decimal places
crit_ = "('Space', 'Perim' = "+ perimValueStr + ")" 
vs.Message(crit_)

 

 

Share this post


Link to post

You can use float() to go straight from the string value to a decimal. repr() will convert back to a string if you need that for the criteria. It should also ignore any white space. 

 

repr(float(perimValueStr)) will do it in one go. 

 

eval() also works well to convert a string into whatever python variable type best matches. 

Share this post


Link to post

Thanks for the suggestion Josh. Unfortunately it doesn't work as the string remains in scientific notation.

 

If you draw a Space object in a file with units set to mm then run this script:

 

    perimValueStr = vs.GetRField( vs.FSActLayer(), 'Space', 'Perim' )
    repr(float(perimValueStr))
    crit_ = "('Space', 'Perim' = "+ perimValueStr + ")" 
    vs.Message(crit_)

 

you will get this result:

 

    ('Space', 'Perim' = 6.4e03)

 

If the units are changed to Ft & Ins, then it doesn't work at all and produces an error (could not convert string to float) as the notation value is too long.

 

Share this post


Link to post

Lots of special cases here.

 

The GetRField returns a value. In the case of units of mm, you get something back that Python interprets as a number (but in scientific notation). If you return feet and inches, it includes the unit marks and returns something that Python considers to be a string.

 

I have not tested it, but I would bet that if you had the unit mark turned on for mm, it would probably return something that python would consider to be a string also.

 

So, you either need to do special case for everything, or possibly turn on show units, run the script and then turn off show units. That way you should always end up with a value returned that is a string, so at least you don't have to fight with some returns as numbers and some as strings.

 

But if you can live with just mm, try this:

 

perimValue = (vs.GetRField( vs.FSActLayer(), 'Space', 'Perim' ))
perimValueStr = format(float(perimValue),'.4f')
crit_ = "('Space', 'Perim' = "+ perimValueStr + ")" 
vs.Message(crit_)

 

 

Share this post


Link to post

I had forgot about units.  In that case vs.ValidNumStr us the way to go, and should compensate for any units format.  That should take care of Pat's concern about special cases.  Using it in a function lets you easily return 0 VS can't convert the value.

 

def Str2Num(inStr):
    success, outNum = vs.ValidNumStr(inStr)
    if success:
        return outNum
    else:
        return 0

 

eval() and repr() return values, not converting the argument, which is why repr(float(perimValueStr)) as it's own line wasn't working.  If you define the above function, the one line version would be:

crit_ = "('Space', 'Perim' = "+ repr(Str2Num(perimValue)) + ")" 

 

This should give you a value without units, which is I believe what you want for the criteria.  If you need a dimension-formatted string, then you need to deal with escaping foot and inch marks.  I haven't tested much with python yet, but with native VS, 2018 is much more finicky about quotation marks in criteria strings.

Share this post


Link to post

Thanks Pat and Josh. I think Josh has nailed it with his last suggestion, which seems to work with any units. The script I am working on is for a worksheet and will populate a single cell with all the door IDs that match a particular door type (and optionally width), comma separated. A door type could be an internal door, an external door, the front door of an apartment, or a patio door of a particular style. Sometimes the doors can vary in size but are otherwise the same type. Something like this:

 

    TYPE                ID                   WIDTH     ETC

|  Type A   |   D01, D04, D07   |   1000   |             |

|  Type A   |   D02, D03, D05   |    900    |             |

|  Type B   |   D06, D11, D12   |   1000   |             |

|  Type B   |   D08, D09, D13   |    900    |             |

 

The RunScript() function is so powerful it has prompted me to dip my toes into the python pit.

Share this post


Link to post

RunScript works fine with Vectorscript. 

 

If you want to use the extra possibilities of Python, that is great, but the dozen or so short RunScripts I have written are all VS.

 

But I am sure you already know that.

Share this post


Link to post

 really? I just assumed they had to be Python as all the default ones were so. That opens a lot more possibilities. Thanks Pat.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

 

7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114

 

© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

×